umap-project 2.9.3__py3-none-any.whl → 3.0.0__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/context_processors.py +1 -0
- umap/forms.py +1 -2
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +218 -96
- umap/locale/en/LC_MESSAGES/django.po +128 -52
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +128 -52
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +209 -88
- umap/locale/is/LC_MESSAGES/django.mo +0 -0
- umap/locale/is/LC_MESSAGES/django.po +296 -175
- umap/migrations/0027_map_tags.py +23 -0
- umap/models.py +13 -2
- umap/settings/base.py +23 -5
- umap/static/umap/base.css +41 -8
- umap/static/umap/content.css +72 -37
- umap/static/umap/css/bar.css +43 -21
- umap/static/umap/css/dialog.css +4 -1
- umap/static/umap/css/form.css +40 -27
- umap/static/umap/css/icon.css +11 -1
- umap/static/umap/css/importers.css +7 -0
- umap/static/umap/img/16-white.svg +23 -2
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/24.svg +4 -4
- umap/static/umap/img/home.svg +7 -0
- umap/static/umap/img/importers/banfr.svg +1 -0
- umap/static/umap/img/marker.svg +2 -5
- umap/static/umap/img/source/16-white.svg +24 -3
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/img/source/24.svg +5 -5
- umap/static/umap/img/target.svg +1 -0
- umap/static/umap/js/components/alerts/alert.js +0 -1
- umap/static/umap/js/modules/browser.js +4 -4
- umap/static/umap/js/modules/caption.js +1 -1
- umap/static/umap/js/modules/data/features.js +25 -25
- umap/static/umap/js/modules/data/layer.js +91 -97
- umap/static/umap/js/modules/facets.js +9 -5
- umap/static/umap/js/modules/form/builder.js +21 -29
- umap/static/umap/js/modules/form/fields.js +40 -14
- umap/static/umap/js/modules/formatter.js +1 -1
- umap/static/umap/js/modules/global.js +9 -5
- umap/static/umap/js/modules/help.js +18 -5
- umap/static/umap/js/modules/importer.js +5 -2
- umap/static/umap/js/modules/importers/banfr.js +93 -0
- umap/static/umap/js/modules/importers/cadastrefr.js +2 -2
- umap/static/umap/js/modules/importers/communesfr.js +1 -1
- umap/static/umap/js/modules/permissions.js +20 -10
- umap/static/umap/js/modules/rendering/icon.js +15 -2
- umap/static/umap/js/modules/rendering/layers/classified.js +7 -7
- umap/static/umap/js/modules/rendering/layers/cluster.js +2 -2
- umap/static/umap/js/modules/rendering/layers/heat.js +4 -4
- umap/static/umap/js/modules/rendering/map.js +14 -6
- umap/static/umap/js/modules/rendering/popup.js +2 -2
- umap/static/umap/js/modules/rendering/template.js +3 -3
- umap/static/umap/js/modules/rendering/ui.js +17 -11
- umap/static/umap/js/modules/rules.js +13 -16
- umap/static/umap/js/modules/schema.js +23 -1
- umap/static/umap/js/modules/share.js +1 -1
- umap/static/umap/js/modules/slideshow.js +1 -0
- umap/static/umap/js/modules/sync/engine.js +141 -19
- umap/static/umap/js/modules/sync/undo.js +101 -0
- umap/static/umap/js/modules/sync/updaters.js +51 -28
- umap/static/umap/js/modules/tableeditor.js +1 -1
- umap/static/umap/js/modules/ui/bar.js +61 -21
- umap/static/umap/js/modules/ui/tooltip.js +1 -1
- umap/static/umap/js/modules/umap.js +190 -176
- umap/static/umap/js/modules/utils.js +30 -4
- umap/static/umap/js/umap.controls.js +82 -38
- umap/static/umap/locale/am_ET.js +11 -6
- umap/static/umap/locale/am_ET.json +11 -6
- umap/static/umap/locale/ar.js +11 -6
- umap/static/umap/locale/ar.json +11 -6
- umap/static/umap/locale/ast.js +11 -6
- umap/static/umap/locale/ast.json +11 -6
- umap/static/umap/locale/bg.js +11 -6
- umap/static/umap/locale/bg.json +11 -6
- umap/static/umap/locale/br.js +12 -7
- umap/static/umap/locale/br.json +12 -7
- umap/static/umap/locale/ca.js +11 -6
- umap/static/umap/locale/ca.json +11 -6
- umap/static/umap/locale/cs_CZ.js +11 -6
- umap/static/umap/locale/cs_CZ.json +11 -6
- umap/static/umap/locale/da.js +11 -6
- umap/static/umap/locale/da.json +11 -6
- umap/static/umap/locale/de.js +47 -42
- umap/static/umap/locale/de.json +47 -42
- umap/static/umap/locale/el.js +11 -6
- umap/static/umap/locale/el.json +11 -6
- umap/static/umap/locale/en.js +11 -6
- umap/static/umap/locale/en.json +11 -6
- umap/static/umap/locale/en_US.json +11 -6
- umap/static/umap/locale/es.js +11 -6
- umap/static/umap/locale/es.json +11 -6
- umap/static/umap/locale/et.js +11 -6
- umap/static/umap/locale/et.json +11 -6
- umap/static/umap/locale/eu.js +11 -6
- umap/static/umap/locale/eu.json +11 -6
- umap/static/umap/locale/fa_IR.js +11 -6
- umap/static/umap/locale/fa_IR.json +11 -6
- umap/static/umap/locale/fi.js +11 -6
- umap/static/umap/locale/fi.json +11 -6
- umap/static/umap/locale/fr.js +11 -6
- umap/static/umap/locale/fr.json +11 -6
- umap/static/umap/locale/gl.js +12 -7
- umap/static/umap/locale/gl.json +12 -7
- umap/static/umap/locale/he.js +11 -6
- umap/static/umap/locale/he.json +11 -6
- umap/static/umap/locale/hr.js +11 -6
- umap/static/umap/locale/hr.json +11 -6
- umap/static/umap/locale/hu.js +25 -20
- umap/static/umap/locale/hu.json +25 -20
- umap/static/umap/locale/id.js +11 -6
- umap/static/umap/locale/id.json +11 -6
- umap/static/umap/locale/is.js +151 -146
- umap/static/umap/locale/is.json +151 -146
- umap/static/umap/locale/it.js +11 -6
- umap/static/umap/locale/it.json +11 -6
- umap/static/umap/locale/ja.js +11 -6
- umap/static/umap/locale/ja.json +11 -6
- umap/static/umap/locale/ko.js +11 -6
- umap/static/umap/locale/ko.json +11 -6
- umap/static/umap/locale/lt.js +11 -6
- umap/static/umap/locale/lt.json +11 -6
- umap/static/umap/locale/ms.js +11 -6
- umap/static/umap/locale/ms.json +11 -6
- umap/static/umap/locale/nl.js +12 -7
- umap/static/umap/locale/nl.json +12 -7
- umap/static/umap/locale/no.js +11 -6
- umap/static/umap/locale/no.json +11 -6
- umap/static/umap/locale/pl.js +11 -6
- umap/static/umap/locale/pl.json +11 -6
- umap/static/umap/locale/pl_PL.json +11 -6
- umap/static/umap/locale/pt.js +11 -6
- umap/static/umap/locale/pt.json +11 -6
- umap/static/umap/locale/pt_BR.js +11 -6
- umap/static/umap/locale/pt_BR.json +11 -6
- umap/static/umap/locale/pt_PT.js +11 -6
- umap/static/umap/locale/pt_PT.json +11 -6
- umap/static/umap/locale/ro.js +11 -6
- umap/static/umap/locale/ro.json +11 -6
- umap/static/umap/locale/ru.js +11 -6
- umap/static/umap/locale/ru.json +11 -6
- umap/static/umap/locale/sk_SK.js +11 -6
- umap/static/umap/locale/sk_SK.json +11 -6
- umap/static/umap/locale/sl.js +11 -6
- umap/static/umap/locale/sl.json +11 -6
- umap/static/umap/locale/sr.js +11 -6
- umap/static/umap/locale/sr.json +11 -6
- umap/static/umap/locale/sv.js +11 -6
- umap/static/umap/locale/sv.json +11 -6
- umap/static/umap/locale/th_TH.js +11 -6
- umap/static/umap/locale/th_TH.json +11 -6
- umap/static/umap/locale/tr.js +11 -6
- umap/static/umap/locale/tr.json +11 -6
- umap/static/umap/locale/uk_UA.js +11 -6
- umap/static/umap/locale/uk_UA.json +11 -6
- umap/static/umap/locale/vi.js +11 -6
- umap/static/umap/locale/vi.json +11 -6
- umap/static/umap/locale/vi_VN.json +11 -6
- umap/static/umap/locale/zh.js +11 -6
- umap/static/umap/locale/zh.json +11 -6
- umap/static/umap/locale/zh_CN.json +11 -6
- umap/static/umap/locale/zh_TW.Big5.json +11 -6
- umap/static/umap/locale/zh_TW.js +19 -14
- umap/static/umap/locale/zh_TW.json +19 -14
- umap/static/umap/map.css +58 -28
- umap/static/umap/unittests/sync.js +0 -57
- umap/static/umap/unittests/utils.js +47 -0
- umap/static/umap/vars.css +5 -2
- umap/static/umap/vendors/photon/leaflet.photon.js +3 -0
- umap/sync/payloads.py +3 -2
- umap/templates/auth/user_detail.html +1 -1
- umap/templates/auth/user_stars.html +1 -1
- umap/templates/umap/content.html +17 -12
- umap/templates/umap/home.html +7 -5
- umap/templates/umap/map_fragment.html +1 -1
- umap/templates/umap/map_list.html +20 -13
- umap/templates/umap/search.html +7 -3
- umap/templates/umap/search_bar.html +13 -11
- umap/templates/umap/team_detail.html +1 -1
- umap/tests/base.py +2 -1
- umap/tests/fixtures/remote_data.umap +55 -0
- umap/tests/fixtures/test_upload_data_with_iconurl.umap +122 -0
- umap/tests/integration/test_browser.py +1 -3
- umap/tests/integration/test_conditional_rules.py +3 -0
- umap/tests/integration/test_edit_datalayer.py +2 -7
- umap/tests/integration/test_edit_map.py +15 -0
- umap/tests/integration/test_edit_polygon.py +1 -2
- umap/tests/integration/test_import.py +59 -2
- umap/tests/integration/test_optimistic_merge.py +4 -3
- umap/tests/integration/test_owned_map.py +0 -1
- umap/tests/integration/test_save.py +2 -4
- umap/tests/integration/test_undo_redo.py +267 -0
- umap/tests/integration/test_websocket_sync.py +78 -11
- umap/tests/settings.py +1 -3
- umap/tests/test_datalayer_s3.py +1 -0
- umap/tests/test_map_views.py +1 -0
- umap/tests/test_views.py +34 -0
- umap/utils.py +1 -1
- umap/views.py +23 -2
- {umap_project-2.9.3.dist-info → umap_project-3.0.0.dist-info}/METADATA +13 -12
- {umap_project-2.9.3.dist-info → umap_project-3.0.0.dist-info}/RECORD +206 -208
- umap/static/umap/js/modules/saving.js +0 -52
- umap/static/umap/test/.eslintrc +0 -21
- umap/static/umap/test/DataLayer.js +0 -463
- umap/static/umap/test/Feature.js +0 -131
- umap/static/umap/test/Map.js +0 -37
- umap/static/umap/test/Marker.js +0 -126
- umap/static/umap/test/Polygon.js +0 -111
- umap/static/umap/test/Polyline.js +0 -286
- umap/static/umap/test/Util.js +0 -28
- umap/static/umap/test/_pre.js +0 -455
- umap/static/umap/test/index.html +0 -139
- {umap_project-2.9.3.dist-info → umap_project-3.0.0.dist-info}/WHEEL +0 -0
- {umap_project-2.9.3.dist-info → umap_project-3.0.0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.9.3.dist-info → umap_project-3.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
// FIXME: this module should not depend on Leaflet
|
|
2
2
|
import {
|
|
3
|
-
DomUtil,
|
|
4
3
|
DomEvent,
|
|
5
|
-
|
|
4
|
+
DomUtil,
|
|
6
5
|
GeoJSON,
|
|
6
|
+
stamp,
|
|
7
7
|
} from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
8
|
-
import * as Utils from '../utils.js'
|
|
9
|
-
import { Default as DefaultLayer } from '../rendering/layers/base.js'
|
|
10
|
-
import { Cluster } from '../rendering/layers/cluster.js'
|
|
11
|
-
import { Heat } from '../rendering/layers/heat.js'
|
|
12
|
-
import { Categorized, Choropleth, Circles } from '../rendering/layers/classified.js'
|
|
13
8
|
import {
|
|
14
9
|
uMapAlert as Alert,
|
|
15
10
|
uMapAlertConflict as AlertConflict,
|
|
16
11
|
} from '../../components/alerts/alert.js'
|
|
12
|
+
import { MutatingForm } from '../form/builder.js'
|
|
17
13
|
import { translate } from '../i18n.js'
|
|
18
14
|
import { DataLayerPermissions } from '../permissions.js'
|
|
19
|
-
import {
|
|
20
|
-
import
|
|
21
|
-
import {
|
|
15
|
+
import { Default as DefaultLayer } from '../rendering/layers/base.js'
|
|
16
|
+
import { Categorized, Choropleth, Circles } from '../rendering/layers/classified.js'
|
|
17
|
+
import { Cluster } from '../rendering/layers/cluster.js'
|
|
18
|
+
import { Heat } from '../rendering/layers/heat.js'
|
|
22
19
|
import * as Schema from '../schema.js'
|
|
23
|
-
import
|
|
20
|
+
import TableEditor from '../tableeditor.js'
|
|
21
|
+
import * as Utils from '../utils.js'
|
|
22
|
+
import { LineString, Point, Polygon } from './features.js'
|
|
24
23
|
|
|
25
24
|
export const LAYER_TYPES = [
|
|
26
25
|
DefaultLayer,
|
|
@@ -36,9 +35,8 @@ const LAYER_MAP = LAYER_TYPES.reduce((acc, klass) => {
|
|
|
36
35
|
return acc
|
|
37
36
|
}, {})
|
|
38
37
|
|
|
39
|
-
export class DataLayer
|
|
38
|
+
export class DataLayer {
|
|
40
39
|
constructor(umap, leafletMap, data = {}) {
|
|
41
|
-
super()
|
|
42
40
|
this._umap = umap
|
|
43
41
|
this.sync = umap.syncEngine.proxy(this)
|
|
44
42
|
this._index = Array()
|
|
@@ -49,7 +47,6 @@ export class DataLayer extends ServerStored {
|
|
|
49
47
|
this._leafletMap = leafletMap
|
|
50
48
|
this.parentPane = this._leafletMap.getPane('overlayPane')
|
|
51
49
|
this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane)
|
|
52
|
-
this.pane.dataset.id = stamp(this)
|
|
53
50
|
// FIXME: should be on layer
|
|
54
51
|
this.renderer = L.svg({ pane: this.pane })
|
|
55
52
|
this.defaultOptions = {
|
|
@@ -66,6 +63,7 @@ export class DataLayer extends ServerStored {
|
|
|
66
63
|
data.id = data.id || crypto.randomUUID()
|
|
67
64
|
|
|
68
65
|
this.setOptions(data)
|
|
66
|
+
this.pane.dataset.id = this.id
|
|
69
67
|
|
|
70
68
|
if (!Utils.isObject(this.options.remoteData)) {
|
|
71
69
|
this.options.remoteData = {}
|
|
@@ -83,7 +81,7 @@ export class DataLayer extends ServerStored {
|
|
|
83
81
|
this.connectToMap()
|
|
84
82
|
this.permissions = new DataLayerPermissions(this._umap, this)
|
|
85
83
|
|
|
86
|
-
this._needsFetch = this.createdOnServer
|
|
84
|
+
this._needsFetch = this.createdOnServer || this.isRemoteLayer()
|
|
87
85
|
if (!this.createdOnServer) {
|
|
88
86
|
if (this.showAtLoad()) this.show()
|
|
89
87
|
}
|
|
@@ -114,7 +112,6 @@ export class DataLayer extends ServerStored {
|
|
|
114
112
|
|
|
115
113
|
set isDeleted(status) {
|
|
116
114
|
this._isDeleted = status
|
|
117
|
-
if (status) this.isDirty = status
|
|
118
115
|
}
|
|
119
116
|
|
|
120
117
|
get isDeleted() {
|
|
@@ -144,11 +141,10 @@ export class DataLayer extends ServerStored {
|
|
|
144
141
|
if (fields.includes('options.type')) {
|
|
145
142
|
this.resetLayer()
|
|
146
143
|
}
|
|
147
|
-
this.hide()
|
|
148
144
|
for (const field of fields) {
|
|
149
145
|
this.layer.onEdit(field, builder)
|
|
150
146
|
}
|
|
151
|
-
this.
|
|
147
|
+
this.redraw()
|
|
152
148
|
break
|
|
153
149
|
case 'remote-data':
|
|
154
150
|
this.fetchRemoteData()
|
|
@@ -265,18 +261,19 @@ export class DataLayer extends ServerStored {
|
|
|
265
261
|
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
|
|
266
262
|
geojson._umap_options.id = this.id
|
|
267
263
|
if (geojson._umap_options) this.setOptions(geojson._umap_options)
|
|
268
|
-
if (this.isRemoteLayer())
|
|
269
|
-
|
|
264
|
+
if (this.isRemoteLayer()) {
|
|
265
|
+
await this.fetchRemoteData()
|
|
266
|
+
} else {
|
|
267
|
+
this.fromGeoJSON(geojson, false)
|
|
268
|
+
}
|
|
270
269
|
}
|
|
271
270
|
|
|
272
271
|
clear() {
|
|
273
|
-
this.
|
|
274
|
-
this._features
|
|
275
|
-
|
|
276
|
-
if (this._geojson) {
|
|
277
|
-
this.backupData()
|
|
278
|
-
this._geojson = null
|
|
272
|
+
this.sync.startBatch()
|
|
273
|
+
for (const feature of Object.values(this._features)) {
|
|
274
|
+
feature.del()
|
|
279
275
|
}
|
|
276
|
+
this.sync.commitBatch()
|
|
280
277
|
this.dataChanged()
|
|
281
278
|
}
|
|
282
279
|
|
|
@@ -330,8 +327,9 @@ export class DataLayer extends ServerStored {
|
|
|
330
327
|
this.clear()
|
|
331
328
|
return this._umap.formatter
|
|
332
329
|
.parse(raw, this.options.remoteData.format)
|
|
333
|
-
.then((geojson) => this.fromGeoJSON(geojson))
|
|
330
|
+
.then((geojson) => this.fromGeoJSON(geojson, false))
|
|
334
331
|
.catch((error) => {
|
|
332
|
+
console.debug(error)
|
|
335
333
|
Alert.error(
|
|
336
334
|
translate('Cannot parse remote data for layer "{layer}" with url "{url}"', {
|
|
337
335
|
layer: this.getName(),
|
|
@@ -366,9 +364,8 @@ export class DataLayer extends ServerStored {
|
|
|
366
364
|
}
|
|
367
365
|
|
|
368
366
|
connectToMap() {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
this._umap.datalayers[id] = this
|
|
367
|
+
if (!this._umap.datalayers[this.id]) {
|
|
368
|
+
this._umap.datalayers[this.id] = this
|
|
372
369
|
}
|
|
373
370
|
if (!this._umap.datalayersIndex.includes(this)) {
|
|
374
371
|
this._umap.datalayersIndex.push(this)
|
|
@@ -417,7 +414,10 @@ export class DataLayer extends ServerStored {
|
|
|
417
414
|
|
|
418
415
|
removeFeature(feature, sync) {
|
|
419
416
|
const id = stamp(feature)
|
|
420
|
-
if (sync !== false)
|
|
417
|
+
if (sync !== false) {
|
|
418
|
+
const oldValue = feature.toGeoJSON()
|
|
419
|
+
feature.sync.delete(oldValue)
|
|
420
|
+
}
|
|
421
421
|
this.hideFeature(feature)
|
|
422
422
|
delete this._umap.featuresIndex[feature.getSlug()]
|
|
423
423
|
feature.disconnectFromDataLayer(this)
|
|
@@ -518,7 +518,7 @@ export class DataLayer extends ServerStored {
|
|
|
518
518
|
}
|
|
519
519
|
if (feature && !feature.isEmpty()) {
|
|
520
520
|
this.addFeature(feature)
|
|
521
|
-
if (sync) feature.
|
|
521
|
+
if (sync) feature.sync.upsert(feature.toGeoJSON(), null)
|
|
522
522
|
return feature
|
|
523
523
|
}
|
|
524
524
|
}
|
|
@@ -526,12 +526,14 @@ export class DataLayer extends ServerStored {
|
|
|
526
526
|
async importRaw(raw, format) {
|
|
527
527
|
return this._umap.formatter
|
|
528
528
|
.parse(raw, format)
|
|
529
|
-
.then((geojson) =>
|
|
530
|
-
|
|
531
|
-
|
|
529
|
+
.then((geojson) => {
|
|
530
|
+
this.sync.startBatch()
|
|
531
|
+
const data = this.addData(geojson)
|
|
532
|
+
this.sync.commitBatch()
|
|
532
533
|
return data
|
|
533
534
|
})
|
|
534
535
|
.catch((error) => {
|
|
536
|
+
console.debug(error)
|
|
535
537
|
Alert.error(translate('Import failed: invalid data'))
|
|
536
538
|
})
|
|
537
539
|
}
|
|
@@ -595,17 +597,17 @@ export class DataLayer extends ServerStored {
|
|
|
595
597
|
}
|
|
596
598
|
|
|
597
599
|
del(sync = true) {
|
|
600
|
+
const oldValue = Utils.CopyJSON(this.umapGeoJSON())
|
|
598
601
|
this.erase()
|
|
599
602
|
if (sync) {
|
|
600
603
|
this.isDeleted = true
|
|
601
|
-
this.sync.delete()
|
|
604
|
+
this.sync.delete(oldValue)
|
|
602
605
|
}
|
|
603
606
|
}
|
|
604
607
|
|
|
605
608
|
empty() {
|
|
606
609
|
if (this.isRemoteLayer()) return
|
|
607
610
|
this.clear()
|
|
608
|
-
this.isDirty = true
|
|
609
611
|
}
|
|
610
612
|
|
|
611
613
|
clone() {
|
|
@@ -629,29 +631,9 @@ export class DataLayer extends ServerStored {
|
|
|
629
631
|
this.clear()
|
|
630
632
|
}
|
|
631
633
|
|
|
632
|
-
reset() {
|
|
633
|
-
if (!this.createdOnServer) {
|
|
634
|
-
this.erase()
|
|
635
|
-
return
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
this.resetOptions()
|
|
639
|
-
this.parentPane.appendChild(this.pane)
|
|
640
|
-
if (this._leaflet_events_bk && !this._leaflet_events) {
|
|
641
|
-
this._leaflet_events = this._leaflet_events_bk
|
|
642
|
-
}
|
|
643
|
-
this.clear()
|
|
644
|
-
this.hide()
|
|
645
|
-
if (this.isRemoteLayer()) this.fetchRemoteData()
|
|
646
|
-
else if (this._geojson_bk) this.fromGeoJSON(this._geojson_bk)
|
|
647
|
-
this.show()
|
|
648
|
-
this.isDirty = false
|
|
649
|
-
}
|
|
650
|
-
|
|
651
634
|
redraw() {
|
|
652
635
|
if (!this.isVisible()) return
|
|
653
|
-
this.
|
|
654
|
-
this.show()
|
|
636
|
+
this.eachFeature((feature) => feature.redraw())
|
|
655
637
|
}
|
|
656
638
|
|
|
657
639
|
edit() {
|
|
@@ -831,8 +813,9 @@ export class DataLayer extends ServerStored {
|
|
|
831
813
|
this
|
|
832
814
|
)
|
|
833
815
|
|
|
834
|
-
if (this._umap.properties.urls.datalayer_versions)
|
|
816
|
+
if (this._umap.properties.urls.datalayer_versions) {
|
|
835
817
|
this.buildVersionsFieldset(container)
|
|
818
|
+
}
|
|
836
819
|
|
|
837
820
|
const advancedActions = DomUtil.createFieldset(
|
|
838
821
|
container,
|
|
@@ -907,10 +890,15 @@ export class DataLayer extends ServerStored {
|
|
|
907
890
|
const appendVersion = (data) => {
|
|
908
891
|
const date = new Date(Number.parseInt(data.at, 10))
|
|
909
892
|
const content = `${date.toLocaleString(U.lang)} (${Number.parseInt(data.size) / 1000}Kb)`
|
|
910
|
-
const el =
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
893
|
+
const [el, { button }] = Utils.loadTemplateWithRefs(
|
|
894
|
+
`<div class="umap-datalayer-version">
|
|
895
|
+
<button type="button" title="${translate('Restore this version')}" data-ref=button>
|
|
896
|
+
<i class="icon icon-16 icon-restore"></i> ${content}
|
|
897
|
+
</button>
|
|
898
|
+
</div>`
|
|
899
|
+
)
|
|
900
|
+
versionsContainer.appendChild(el)
|
|
901
|
+
button.addEventListener('click', () => this.restore(data.ref))
|
|
914
902
|
}
|
|
915
903
|
|
|
916
904
|
const versionsContainer = DomUtil.createFieldset(container, translate('Versions'), {
|
|
@@ -934,11 +922,19 @@ export class DataLayer extends ServerStored {
|
|
|
934
922
|
)
|
|
935
923
|
if (!error) {
|
|
936
924
|
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat.
|
|
937
|
-
if (geojson._umap_options)
|
|
925
|
+
if (geojson._umap_options) {
|
|
926
|
+
const oldOptions = Utils.CopyJSON(this.options)
|
|
927
|
+
this.setOptions(geojson._umap_options)
|
|
928
|
+
this.sync.update('options', this.options, oldOptions)
|
|
929
|
+
}
|
|
938
930
|
this.empty()
|
|
939
|
-
if (this.isRemoteLayer())
|
|
940
|
-
|
|
941
|
-
|
|
931
|
+
if (this.isRemoteLayer()) {
|
|
932
|
+
this.fetchRemoteData()
|
|
933
|
+
} else {
|
|
934
|
+
this.sync.startBatch()
|
|
935
|
+
this.addData(geojson)
|
|
936
|
+
this.sync.commitBatch()
|
|
937
|
+
}
|
|
942
938
|
}
|
|
943
939
|
})
|
|
944
940
|
}
|
|
@@ -960,12 +956,18 @@ export class DataLayer extends ServerStored {
|
|
|
960
956
|
this.propagateHide()
|
|
961
957
|
}
|
|
962
958
|
|
|
963
|
-
toggle() {
|
|
959
|
+
toggle(force) {
|
|
964
960
|
// From now on, do not try to how/hidedataChanged
|
|
965
961
|
// automatically this layer.
|
|
962
|
+
let display = force
|
|
966
963
|
this._forcedVisibility = true
|
|
967
|
-
if (
|
|
964
|
+
if (force === undefined) {
|
|
965
|
+
if (!this.isVisible()) display = true
|
|
966
|
+
else display = false
|
|
967
|
+
}
|
|
968
|
+
if (display) this.show()
|
|
968
969
|
else this.hide()
|
|
970
|
+
this._umap.bottomBar.redraw()
|
|
969
971
|
}
|
|
970
972
|
|
|
971
973
|
zoomTo() {
|
|
@@ -1086,7 +1088,11 @@ export class DataLayer extends ServerStored {
|
|
|
1086
1088
|
|
|
1087
1089
|
setReferenceVersion({ response, sync }) {
|
|
1088
1090
|
this._referenceVersion = response.headers.get('X-Datalayer-Version')
|
|
1089
|
-
if (sync)
|
|
1091
|
+
if (sync) {
|
|
1092
|
+
this.sync.update('_referenceVersion', this._referenceVersion, null, {
|
|
1093
|
+
undo: false,
|
|
1094
|
+
})
|
|
1095
|
+
}
|
|
1090
1096
|
}
|
|
1091
1097
|
|
|
1092
1098
|
async save() {
|
|
@@ -1115,6 +1121,10 @@ export class DataLayer extends ServerStored {
|
|
|
1115
1121
|
}
|
|
1116
1122
|
|
|
1117
1123
|
async _trySave(url, headers, formData) {
|
|
1124
|
+
if (this._forceSave) {
|
|
1125
|
+
headers = {}
|
|
1126
|
+
this._forceSave = false
|
|
1127
|
+
}
|
|
1118
1128
|
const [data, response, error] = await this._umap.server.post(url, headers, formData)
|
|
1119
1129
|
if (error) {
|
|
1120
1130
|
if (response && response.status === 412) {
|
|
@@ -1124,15 +1134,8 @@ export class DataLayer extends ServerStored {
|
|
|
1124
1134
|
'This situation is tricky, you have to choose carefully which version is pertinent.'
|
|
1125
1135
|
),
|
|
1126
1136
|
async () => {
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
if (status) {
|
|
1130
|
-
this.isDirty = false
|
|
1131
|
-
|
|
1132
|
-
// Call the main save, in case something else needs to be saved
|
|
1133
|
-
// as the conflict stopped the saving flow
|
|
1134
|
-
await this._umap.saveAll()
|
|
1135
|
-
}
|
|
1137
|
+
this._forceSave = true
|
|
1138
|
+
await this._umap.saveAll()
|
|
1136
1139
|
}
|
|
1137
1140
|
)
|
|
1138
1141
|
}
|
|
@@ -1167,7 +1170,7 @@ export class DataLayer extends ServerStored {
|
|
|
1167
1170
|
}
|
|
1168
1171
|
|
|
1169
1172
|
commitDelete() {
|
|
1170
|
-
delete this._umap.datalayers[
|
|
1173
|
+
delete this._umap.datalayers[this.id]
|
|
1171
1174
|
}
|
|
1172
1175
|
|
|
1173
1176
|
getName() {
|
|
@@ -1234,25 +1237,16 @@ export class DataLayer extends ServerStored {
|
|
|
1234
1237
|
translate('Delete layer')
|
|
1235
1238
|
)
|
|
1236
1239
|
if (this.isReadOnly()) {
|
|
1237
|
-
|
|
1240
|
+
container.classList.add('readonly')
|
|
1238
1241
|
} else {
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
if (!this.isVisible()) return
|
|
1246
|
-
this._umap.dialog
|
|
1247
|
-
.confirm(translate('Are you sure you want to delete this layer?'))
|
|
1248
|
-
.then(() => {
|
|
1249
|
-
this.del()
|
|
1250
|
-
})
|
|
1251
|
-
},
|
|
1252
|
-
this
|
|
1253
|
-
)
|
|
1242
|
+
edit.addEventListener('click', () => this.edit())
|
|
1243
|
+
table.addEventListener('click', () => this.tableEdit())
|
|
1244
|
+
remove.addEventListener('click', () => {
|
|
1245
|
+
if (!this.isVisible()) return
|
|
1246
|
+
this.del()
|
|
1247
|
+
})
|
|
1254
1248
|
}
|
|
1255
|
-
DomEvent.on(toggle, 'click', this.toggle
|
|
1249
|
+
DomEvent.on(toggle, 'click', () => this.toggle())
|
|
1256
1250
|
DomEvent.on(zoomTo, 'click', this.zoomTo, this)
|
|
1257
1251
|
container.classList.add(this.getHidableClass())
|
|
1258
1252
|
container.classList.toggle('off', !this.isVisible())
|
|
@@ -135,7 +135,13 @@ export default class Facets {
|
|
|
135
135
|
for (const [property, { label, type }] of parsed) {
|
|
136
136
|
dumped.push([property, label, type].filter(Boolean).join('|'))
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
const oldValue = this._umap.properties.facetKey
|
|
139
|
+
this._umap.properties.facetKey = dumped.join(',')
|
|
140
|
+
this._umap.sync.update(
|
|
141
|
+
'properties.facetKey',
|
|
142
|
+
this._umap.properties.facetKey,
|
|
143
|
+
oldValue
|
|
144
|
+
)
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
has(property) {
|
|
@@ -146,15 +152,13 @@ export default class Facets {
|
|
|
146
152
|
const defined = this.getDefined()
|
|
147
153
|
if (!defined.has(property)) {
|
|
148
154
|
defined.set(property, { label, type })
|
|
149
|
-
this.
|
|
150
|
-
this._umap.isDirty = true
|
|
155
|
+
this.dumps(defined)
|
|
151
156
|
}
|
|
152
157
|
}
|
|
153
158
|
|
|
154
159
|
remove(property) {
|
|
155
160
|
const defined = this.getDefined()
|
|
156
161
|
defined.delete(property)
|
|
157
|
-
this.
|
|
158
|
-
this._umap.isDirty = true
|
|
162
|
+
this.dumps(defined)
|
|
159
163
|
}
|
|
160
164
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import getClass from './fields.js'
|
|
2
|
-
import * as Utils from '../utils.js'
|
|
3
|
-
import { SCHEMA } from '../schema.js'
|
|
4
1
|
import { translate } from '../i18n.js'
|
|
2
|
+
import { SCHEMA } from '../schema.js'
|
|
3
|
+
import * as Utils from '../utils.js'
|
|
4
|
+
import getClass from './fields.js'
|
|
5
5
|
|
|
6
6
|
export class Form extends Utils.WithEvents {
|
|
7
7
|
constructor(obj, fields, properties) {
|
|
@@ -70,21 +70,7 @@ export class Form extends Utils.WithEvents {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
setter(field, value) {
|
|
73
|
-
|
|
74
|
-
let obj = this.obj
|
|
75
|
-
let what
|
|
76
|
-
for (let i = 0, l = path.length; i < l; i++) {
|
|
77
|
-
what = path[i]
|
|
78
|
-
if (what === path[l - 1]) {
|
|
79
|
-
if (typeof value === 'undefined') {
|
|
80
|
-
delete obj[what]
|
|
81
|
-
} else {
|
|
82
|
-
obj[what] = value
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
obj = obj[what]
|
|
86
|
-
}
|
|
87
|
-
}
|
|
73
|
+
Utils.setObjectValue(this.obj, field, value)
|
|
88
74
|
}
|
|
89
75
|
|
|
90
76
|
restoreField(field) {
|
|
@@ -144,14 +130,8 @@ export class MutatingForm extends Form {
|
|
|
144
130
|
}
|
|
145
131
|
for (const [key, defaults] of Object.entries(SCHEMA)) {
|
|
146
132
|
const properties = Object.assign({}, defaults)
|
|
147
|
-
if (properties.type ===
|
|
148
|
-
|
|
149
|
-
else properties.handler = 'Switch'
|
|
150
|
-
} else if (properties.type === 'Text') {
|
|
151
|
-
properties.handler = 'Textarea'
|
|
152
|
-
} else if (properties.type === Number) {
|
|
153
|
-
if (properties.step) properties.handler = 'Range'
|
|
154
|
-
else properties.handler = 'IntInput'
|
|
133
|
+
if (properties.type === Array) {
|
|
134
|
+
properties.handler = 'CheckBoxes'
|
|
155
135
|
} else if (properties.choices) {
|
|
156
136
|
const text_length = properties.choices.reduce(
|
|
157
137
|
(acc, [_, label]) => acc + label.length,
|
|
@@ -165,6 +145,14 @@ export class MutatingForm extends Form {
|
|
|
165
145
|
properties.handler = 'Select'
|
|
166
146
|
properties.selectOptions = properties.choices
|
|
167
147
|
}
|
|
148
|
+
} else if (properties.type === Boolean) {
|
|
149
|
+
if (properties.nullable) properties.handler = 'NullableChoices'
|
|
150
|
+
else properties.handler = 'Switch'
|
|
151
|
+
} else if (properties.type === 'Text') {
|
|
152
|
+
properties.handler = 'Textarea'
|
|
153
|
+
} else if (properties.type === Number) {
|
|
154
|
+
if (properties.step) properties.handler = 'Range'
|
|
155
|
+
else properties.handler = 'IntInput'
|
|
168
156
|
} else {
|
|
169
157
|
switch (key) {
|
|
170
158
|
case 'color':
|
|
@@ -190,13 +178,17 @@ export class MutatingForm extends Form {
|
|
|
190
178
|
}
|
|
191
179
|
|
|
192
180
|
setter(field, value) {
|
|
193
|
-
|
|
194
|
-
this.obj
|
|
181
|
+
const oldValue = this.getter(field)
|
|
182
|
+
if ('setter' in this.obj) {
|
|
183
|
+
this.obj.setter(field, value)
|
|
184
|
+
} else {
|
|
185
|
+
super.setter(field, value)
|
|
186
|
+
}
|
|
195
187
|
if ('render' in this.obj) {
|
|
196
188
|
this.obj.render([field], this)
|
|
197
189
|
}
|
|
198
190
|
if ('sync' in this.obj) {
|
|
199
|
-
this.obj.sync.update(field, value)
|
|
191
|
+
this.obj.sync.update(field, value, oldValue)
|
|
200
192
|
}
|
|
201
193
|
}
|
|
202
194
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import * as Utils from '../utils.js'
|
|
2
|
-
import { translate } from '../i18n.js'
|
|
3
1
|
import {
|
|
4
2
|
AjaxAutocomplete,
|
|
5
3
|
AjaxAutocompleteMultiple,
|
|
6
4
|
AutocompleteDatalist,
|
|
7
5
|
} from '../autocomplete.js'
|
|
8
|
-
import {
|
|
6
|
+
import { translate } from '../i18n.js'
|
|
9
7
|
import * as Icon from '../rendering/icon.js'
|
|
8
|
+
import { SCHEMA } from '../schema.js'
|
|
9
|
+
import * as Utils from '../utils.js'
|
|
10
10
|
|
|
11
11
|
const Fields = {}
|
|
12
12
|
|
|
@@ -152,7 +152,9 @@ Fields.Textarea = class extends BaseElement {
|
|
|
152
152
|
this.textarea.value = value
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
-
|
|
155
|
+
clear() {
|
|
156
|
+
this.textarea.value = ''
|
|
157
|
+
}
|
|
156
158
|
value() {
|
|
157
159
|
return this.textarea.value
|
|
158
160
|
}
|
|
@@ -254,8 +256,8 @@ Fields.BlurInput = class extends Fields.Input {
|
|
|
254
256
|
const IntegerMixin = (Base) =>
|
|
255
257
|
class extends Base {
|
|
256
258
|
value() {
|
|
257
|
-
return !isNaN(this.input.value) && this.input.value !== ''
|
|
258
|
-
? parseInt(this.input.value, 10)
|
|
259
|
+
return !Number.isNaN(this.input.value) && this.input.value !== ''
|
|
260
|
+
? Number.parseInt(this.input.value, 10)
|
|
259
261
|
: undefined
|
|
260
262
|
}
|
|
261
263
|
|
|
@@ -270,8 +272,8 @@ Fields.BlurIntInput = class extends IntegerMixin(Fields.BlurInput) {}
|
|
|
270
272
|
const FloatMixin = (Base) =>
|
|
271
273
|
class extends Base {
|
|
272
274
|
value() {
|
|
273
|
-
return !isNaN(this.input.value) && this.input.value !== ''
|
|
274
|
-
? parseFloat(this.input.value)
|
|
275
|
+
return !Number.isNaN(this.input.value) && this.input.value !== ''
|
|
276
|
+
? Number.parseFloat(this.input.value)
|
|
275
277
|
: undefined
|
|
276
278
|
}
|
|
277
279
|
|
|
@@ -324,6 +326,29 @@ Fields.CheckBox = class extends BaseElement {
|
|
|
324
326
|
}
|
|
325
327
|
}
|
|
326
328
|
|
|
329
|
+
Fields.CheckBoxes = class extends BaseElement {
|
|
330
|
+
getInputTemplate(value, label) {
|
|
331
|
+
return `<label><input type=checkbox value="${value}" name="${this.name}" data-ref=input />${label}</label>`
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
build() {
|
|
335
|
+
const initial = this.get() || []
|
|
336
|
+
for (const [value, label] of this.properties.choices) {
|
|
337
|
+
const [root, { input }] = Utils.loadTemplateWithRefs(
|
|
338
|
+
this.getInputTemplate(value, label)
|
|
339
|
+
)
|
|
340
|
+
this.container.appendChild(root)
|
|
341
|
+
input.checked = initial.includes(value)
|
|
342
|
+
input.addEventListener('change', () => this.sync())
|
|
343
|
+
}
|
|
344
|
+
super.build()
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
value() {
|
|
348
|
+
return Array.from(this.root.querySelectorAll('input:checked')).map((el) => el.value)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
327
352
|
Fields.Select = class extends BaseElement {
|
|
328
353
|
getTemplate() {
|
|
329
354
|
return `<select name="${this.name}" data-ref=select></select>`
|
|
@@ -390,7 +415,7 @@ Fields.Select = class extends BaseElement {
|
|
|
390
415
|
|
|
391
416
|
Fields.IntSelect = class extends Fields.Select {
|
|
392
417
|
value() {
|
|
393
|
-
return parseInt(super.value(), 10)
|
|
418
|
+
return Number.parseInt(super.value(), 10)
|
|
394
419
|
}
|
|
395
420
|
}
|
|
396
421
|
|
|
@@ -541,14 +566,14 @@ Fields.DataLayerSwitcher = class extends Fields.Select {
|
|
|
541
566
|
!datalayer.isDataReadOnly() &&
|
|
542
567
|
datalayer.isBrowsable()
|
|
543
568
|
) {
|
|
544
|
-
options.push([
|
|
569
|
+
options.push([datalayer.id, datalayer.getName()])
|
|
545
570
|
}
|
|
546
571
|
})
|
|
547
572
|
return options
|
|
548
573
|
}
|
|
549
574
|
|
|
550
575
|
toHTML() {
|
|
551
|
-
return
|
|
576
|
+
return this.obj.datalayer.id
|
|
552
577
|
}
|
|
553
578
|
|
|
554
579
|
toJS() {
|
|
@@ -805,7 +830,7 @@ Fields.IconUrl = class extends Fields.BlurInput {
|
|
|
805
830
|
categories[category] = categories[category] || []
|
|
806
831
|
categories[category].push(props)
|
|
807
832
|
}
|
|
808
|
-
const sorted = Object.entries(categories).
|
|
833
|
+
const sorted = Object.entries(categories).sort(([a], [b]) =>
|
|
809
834
|
Utils.naturalSort(a, b, U.lang)
|
|
810
835
|
)
|
|
811
836
|
for (const [name, items] of sorted) {
|
|
@@ -1296,12 +1321,13 @@ Fields.ManageEditors = class extends BaseElement {
|
|
|
1296
1321
|
placeholder: translate("Type editor's username"),
|
|
1297
1322
|
}
|
|
1298
1323
|
this.autocomplete = new AjaxAutocompleteMultiple(this.container, options)
|
|
1299
|
-
this._values = this.toHTML()
|
|
1300
|
-
if (this._values)
|
|
1324
|
+
this._values = this.toHTML() || []
|
|
1325
|
+
if (this._values) {
|
|
1301
1326
|
for (let i = 0; i < this._values.length; i++)
|
|
1302
1327
|
this.autocomplete.displaySelected({
|
|
1303
1328
|
item: { value: this._values[i].id, label: this._values[i].name },
|
|
1304
1329
|
})
|
|
1330
|
+
}
|
|
1305
1331
|
}
|
|
1306
1332
|
|
|
1307
1333
|
value() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { uMapAlert as Alert } from '../components/alerts/alert.js'
|
|
1
2
|
/* Uses globals for: csv2geojson, osmtogeojson (not available as ESM) */
|
|
2
3
|
import { translate } from './i18n.js'
|
|
3
|
-
import { uMapAlert as Alert } from '../components/alerts/alert.js'
|
|
4
4
|
|
|
5
5
|
export const EXPORT_FORMATS = {
|
|
6
6
|
geojson: {
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { uMapAlert as Alert } from '../components/alerts/alert.js'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AjaxAutocomplete,
|
|
4
|
+
AjaxAutocompleteMultiple,
|
|
5
|
+
AutocompleteDatalist,
|
|
6
|
+
} from './autocomplete.js'
|
|
7
|
+
import { LineString, Point, Polygon } from './data/features.js'
|
|
8
|
+
import { LAYER_TYPES } from './data/layer.js'
|
|
3
9
|
import Help from './help.js'
|
|
10
|
+
import * as Icon from './rendering/icon.js'
|
|
11
|
+
import { LeafletMarker, LeafletPolygon, LeafletPolyline } from './rendering/ui.js'
|
|
4
12
|
import { ServerRequest } from './request.js'
|
|
5
13
|
import { SCHEMA } from './schema.js'
|
|
6
14
|
import * as Utils from './utils.js'
|
|
7
|
-
import * as Icon from './rendering/icon.js'
|
|
8
|
-
import { LAYER_TYPES } from './data/layer.js'
|
|
9
|
-
import { Point, LineString, Polygon } from './data/features.js'
|
|
10
|
-
import { LeafletMarker, LeafletPolyline, LeafletPolygon } from './rendering/ui.js'
|
|
11
15
|
|
|
12
16
|
// Import modules and export them to the global scope.
|
|
13
17
|
// For the not yet module-compatible JS out there.
|