umap-project 3.0.5__py3-none-any.whl → 3.1.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/forms.py +1 -1
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +219 -72
- umap/locale/ca/LC_MESSAGES/django.mo +0 -0
- umap/locale/ca/LC_MESSAGES/django.po +286 -95
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +211 -65
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +394 -202
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +146 -75
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +125 -59
- umap/locale/en/LC_MESSAGES/django.mo +0 -0
- umap/locale/en/LC_MESSAGES/django.po +124 -58
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +125 -59
- umap/locale/et/LC_MESSAGES/django.mo +0 -0
- umap/locale/et/LC_MESSAGES/django.po +210 -64
- umap/locale/eu/LC_MESSAGES/django.mo +0 -0
- umap/locale/eu/LC_MESSAGES/django.po +212 -65
- umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
- umap/locale/fa_IR/LC_MESSAGES/django.po +286 -95
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +125 -59
- umap/locale/gl/LC_MESSAGES/django.mo +0 -0
- umap/locale/gl/LC_MESSAGES/django.po +212 -66
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +148 -78
- umap/locale/is/LC_MESSAGES/django.mo +0 -0
- umap/locale/is/LC_MESSAGES/django.po +130 -60
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +219 -73
- umap/locale/ms/LC_MESSAGES/django.mo +0 -0
- umap/locale/ms/LC_MESSAGES/django.po +289 -98
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +128 -61
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +287 -96
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +211 -65
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +212 -66
- umap/management/commands/migrate_to_S3.py +42 -20
- umap/management/commands/purge_old_versions.py +63 -0
- umap/management/commands/switch_user.py +52 -0
- umap/managers.py +29 -2
- umap/middleware.py +1 -1
- umap/migrations/0028_map_is_template.py +21 -0
- umap/models.py +14 -4
- umap/settings/base.py +22 -0
- umap/static/umap/base.css +4 -2
- umap/static/umap/content.css +1 -1
- umap/static/umap/css/dialog.css +5 -2
- umap/static/umap/css/form.css +19 -12
- umap/static/umap/css/icon.css +6 -0
- umap/static/umap/css/importers.css +4 -0
- umap/static/umap/css/panel.css +2 -0
- umap/static/umap/img/16-white.svg +5 -1
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/24-white.svg +3 -2
- umap/static/umap/img/24.svg +3 -4
- umap/static/umap/img/importers/opendata.svg +1 -0
- umap/static/umap/img/source/16-white.svg +8 -4
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/img/source/24-white.svg +5 -4
- umap/static/umap/img/source/24.svg +5 -6
- umap/static/umap/js/components/modal.js +27 -0
- umap/static/umap/js/modules/caption.js +4 -4
- umap/static/umap/js/modules/data/features.js +40 -4
- umap/static/umap/js/modules/data/layer.js +208 -138
- umap/static/umap/js/modules/form/builder.js +6 -14
- umap/static/umap/js/modules/form/fields.js +2 -2
- umap/static/umap/js/modules/help.js +15 -3
- umap/static/umap/js/modules/importer.js +7 -4
- umap/static/umap/js/modules/importers/opendata.js +142 -0
- umap/static/umap/js/modules/permissions.js +3 -3
- umap/static/umap/js/modules/rendering/controls.js +34 -2
- umap/static/umap/js/modules/rendering/icon.js +2 -2
- umap/static/umap/js/modules/rendering/layers/base.js +1 -1
- umap/static/umap/js/modules/rendering/layers/classified.js +55 -49
- umap/static/umap/js/modules/rendering/layers/cluster.js +16 -9
- umap/static/umap/js/modules/rendering/layers/heat.js +13 -11
- umap/static/umap/js/modules/rendering/map.js +5 -0
- umap/static/umap/js/modules/rendering/ui.js +23 -0
- umap/static/umap/js/modules/rules.js +24 -23
- umap/static/umap/js/modules/schema.js +60 -4
- umap/static/umap/js/modules/sync/updaters.js +7 -3
- umap/static/umap/js/modules/tableeditor.js +7 -30
- umap/static/umap/js/modules/templates.js +122 -0
- umap/static/umap/js/modules/ui/bar.js +13 -3
- umap/static/umap/js/modules/ui/panel.js +1 -1
- umap/static/umap/js/modules/umap.js +28 -13
- umap/static/umap/js/umap.controls.js +11 -4
- umap/static/umap/locale/br.js +51 -18
- umap/static/umap/locale/br.json +51 -18
- umap/static/umap/locale/da.js +343 -310
- umap/static/umap/locale/da.json +343 -310
- umap/static/umap/locale/de.js +40 -7
- umap/static/umap/locale/de.json +40 -7
- umap/static/umap/locale/el.js +31 -4
- umap/static/umap/locale/el.json +31 -4
- umap/static/umap/locale/en.js +34 -1
- umap/static/umap/locale/en.json +34 -1
- umap/static/umap/locale/es.js +37 -4
- umap/static/umap/locale/es.json +37 -4
- umap/static/umap/locale/fr.js +34 -1
- umap/static/umap/locale/fr.json +34 -1
- umap/static/umap/locale/hu.js +44 -17
- umap/static/umap/locale/hu.json +44 -17
- umap/static/umap/locale/it.js +74 -41
- umap/static/umap/locale/it.json +74 -41
- umap/static/umap/locale/nl.js +42 -9
- umap/static/umap/locale/nl.json +42 -9
- umap/static/umap/map.css +3 -23
- umap/static/umap/vendors/textpath/leaflet.textpath.js +184 -0
- umap/storage/fs.py +19 -9
- umap/templates/umap/dashboard_menu.html +5 -0
- umap/templates/umap/design_system.html +9 -0
- umap/templates/umap/js.html +3 -0
- umap/templates/umap/map_init.html +3 -1
- umap/templates/umap/map_list.html +2 -2
- umap/templates/umap/map_table.html +18 -18
- umap/templates/umap/user_dashboard.html +9 -58
- umap/templates/umap/user_map_table.html +36 -0
- umap/templates/umap/user_templates.html +19 -0
- umap/templatetags/umap_tags.py +5 -0
- umap/tests/integration/test_basics.py +9 -1
- umap/tests/integration/test_conditional_rules.py +57 -0
- umap/tests/integration/test_datalayer.py +16 -9
- umap/tests/integration/test_edit_marker.py +11 -0
- umap/tests/integration/test_tableeditor.py +42 -7
- umap/tests/integration/test_templates.py +44 -0
- umap/tests/test_dashboard.py +19 -0
- umap/tests/test_purge_old_versions.py +91 -0
- umap/tests/test_switch_user.py +31 -0
- umap/tests/test_views.py +67 -0
- umap/urls.py +7 -1
- umap/views.py +65 -19
- {umap_project-3.0.5.dist-info → umap_project-3.1.0.dist-info}/METADATA +15 -15
- {umap_project-3.0.5.dist-info → umap_project-3.1.0.dist-info}/RECORD +145 -132
- {umap_project-3.0.5.dist-info → umap_project-3.1.0.dist-info}/WHEEL +0 -0
- {umap_project-3.0.5.dist-info → umap_project-3.1.0.dist-info}/entry_points.txt +0 -0
- {umap_project-3.0.5.dist-info → umap_project-3.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -20,6 +20,7 @@ import * as Schema from '../schema.js'
|
|
|
20
20
|
import TableEditor from '../tableeditor.js'
|
|
21
21
|
import * as Utils from '../utils.js'
|
|
22
22
|
import { LineString, Point, Polygon } from './features.js'
|
|
23
|
+
import Rules from '../rules.js'
|
|
23
24
|
|
|
24
25
|
export const LAYER_TYPES = [
|
|
25
26
|
DefaultLayer,
|
|
@@ -49,7 +50,7 @@ export class DataLayer {
|
|
|
49
50
|
this.pane = this._leafletMap.createPane(`datalayer${stamp(this)}`, this.parentPane)
|
|
50
51
|
// FIXME: should be on layer
|
|
51
52
|
this.renderer = L.svg({ pane: this.pane })
|
|
52
|
-
this.
|
|
53
|
+
this.defaultProperties = {
|
|
53
54
|
displayOnLoad: true,
|
|
54
55
|
inCaption: true,
|
|
55
56
|
browsable: true,
|
|
@@ -62,27 +63,27 @@ export class DataLayer {
|
|
|
62
63
|
delete data._referenceVersion
|
|
63
64
|
data.id = data.id || crypto.randomUUID()
|
|
64
65
|
|
|
65
|
-
this.
|
|
66
|
+
this.setProperties(data)
|
|
66
67
|
this.pane.dataset.id = this.id
|
|
67
|
-
if (this.
|
|
68
|
-
this.
|
|
68
|
+
if (this.properties.rank === undefined) {
|
|
69
|
+
this.properties.rank = this._umap.datalayers.count()
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
if (!Utils.isObject(this.
|
|
72
|
-
this.
|
|
72
|
+
if (!Utils.isObject(this.properties.remoteData)) {
|
|
73
|
+
this.properties.remoteData = {}
|
|
73
74
|
}
|
|
74
75
|
// Retrocompat
|
|
75
|
-
if (this.
|
|
76
|
-
this.
|
|
77
|
-
delete this.
|
|
76
|
+
if (this.properties.remoteData?.from) {
|
|
77
|
+
this.properties.fromZoom = this.properties.remoteData.from
|
|
78
|
+
delete this.properties.remoteData.from
|
|
78
79
|
}
|
|
79
|
-
if (this.
|
|
80
|
-
this.
|
|
81
|
-
delete this.
|
|
80
|
+
if (this.properties.remoteData?.to) {
|
|
81
|
+
this.properties.toZoom = this.properties.remoteData.to
|
|
82
|
+
delete this.properties.remoteData.to
|
|
82
83
|
}
|
|
83
|
-
this.backupOptions()
|
|
84
84
|
this.connectToMap()
|
|
85
85
|
this.permissions = new DataLayerPermissions(this._umap, this)
|
|
86
|
+
this.rules = new Rules(umap, this)
|
|
86
87
|
|
|
87
88
|
this._needsFetch = this.createdOnServer || this.isRemoteLayer()
|
|
88
89
|
if (!this.createdOnServer) {
|
|
@@ -96,7 +97,7 @@ export class DataLayer {
|
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
get id() {
|
|
99
|
-
return this.
|
|
100
|
+
return this.properties.id
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
get createdOnServer() {
|
|
@@ -129,14 +130,14 @@ export class DataLayer {
|
|
|
129
130
|
// Make sure we always have a valid rank. Undefined rank may happen
|
|
130
131
|
// after importing an old umap backup, and not touching the layers
|
|
131
132
|
// after that.
|
|
132
|
-
if (this.
|
|
133
|
-
this.
|
|
133
|
+
if (this.properties.rank === undefined) {
|
|
134
|
+
this.properties.rank = this.getDOMOrder()
|
|
134
135
|
}
|
|
135
|
-
return this.
|
|
136
|
+
return this.properties.rank
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
set rank(value) {
|
|
139
|
-
this.
|
|
140
|
+
this.properties.rank = value
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
getSyncMetadata() {
|
|
@@ -159,7 +160,7 @@ export class DataLayer {
|
|
|
159
160
|
this._umap.onDataLayersChanged()
|
|
160
161
|
break
|
|
161
162
|
case 'data':
|
|
162
|
-
if (fields.includes('
|
|
163
|
+
if (fields.includes('properties.type')) {
|
|
163
164
|
this.resetLayer()
|
|
164
165
|
}
|
|
165
166
|
for (const field of fields) {
|
|
@@ -205,11 +206,11 @@ export class DataLayer {
|
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
autoLoaded() {
|
|
208
|
-
if (!this._umap.datalayersFromQueryString) return this.
|
|
209
|
+
if (!this._umap.datalayersFromQueryString) return this.properties.displayOnLoad
|
|
209
210
|
const datalayerIds = this._umap.datalayersFromQueryString
|
|
210
211
|
let loadMe = datalayerIds.includes(this.id.toString())
|
|
211
|
-
if (this.
|
|
212
|
-
loadMe = loadMe || datalayerIds.includes(this.
|
|
212
|
+
if (this.properties.old_id) {
|
|
213
|
+
loadMe = loadMe || datalayerIds.includes(this.properties.old_id.toString())
|
|
213
214
|
}
|
|
214
215
|
return loadMe
|
|
215
216
|
}
|
|
@@ -236,7 +237,7 @@ export class DataLayer {
|
|
|
236
237
|
// Only reset if type is defined (undefined is the default) and different from current type
|
|
237
238
|
if (
|
|
238
239
|
this.layer &&
|
|
239
|
-
(!this.
|
|
240
|
+
(!this.properties.type || this.properties.type === this.layer.getType()) &&
|
|
240
241
|
!force
|
|
241
242
|
) {
|
|
242
243
|
return
|
|
@@ -245,7 +246,7 @@ export class DataLayer {
|
|
|
245
246
|
if (this.layer) this.layer.clearLayers()
|
|
246
247
|
// delete this.layer?
|
|
247
248
|
if (visible) this._leafletMap.removeLayer(this.layer)
|
|
248
|
-
const Class = LAYER_MAP[this.
|
|
249
|
+
const Class = LAYER_MAP[this.properties.type] || DefaultLayer
|
|
249
250
|
this.layer = new Class(this)
|
|
250
251
|
// Rendering layer changed, so let's force reset the feature rendering too.
|
|
251
252
|
this.eachFeature((feature) => feature.makeUI())
|
|
@@ -273,7 +274,6 @@ export class DataLayer {
|
|
|
273
274
|
// In case of maps pre 1.0 still around
|
|
274
275
|
delete geojson._storage
|
|
275
276
|
await this.fromUmapGeoJSON(geojson)
|
|
276
|
-
this.backupOptions()
|
|
277
277
|
this._loading = false
|
|
278
278
|
}
|
|
279
279
|
}
|
|
@@ -300,7 +300,7 @@ export class DataLayer {
|
|
|
300
300
|
|
|
301
301
|
async fromUmapGeoJSON(geojson) {
|
|
302
302
|
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat
|
|
303
|
-
if (geojson._umap_options) this.
|
|
303
|
+
if (geojson._umap_options) this.setProperties(geojson._umap_options)
|
|
304
304
|
if (this.isRemoteLayer()) {
|
|
305
305
|
await this.fetchRemoteData()
|
|
306
306
|
} else {
|
|
@@ -321,14 +321,14 @@ export class DataLayer {
|
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
showAtZoom() {
|
|
324
|
-
const from = Number.parseInt(this.
|
|
325
|
-
const to = Number.parseInt(this.
|
|
324
|
+
const from = Number.parseInt(this.properties.fromZoom, 10)
|
|
325
|
+
const to = Number.parseInt(this.properties.toZoom, 10)
|
|
326
326
|
const zoom = this._leafletMap.getZoom()
|
|
327
327
|
return !((!Number.isNaN(from) && zoom < from) || (!Number.isNaN(to) && zoom > to))
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
hasDynamicData() {
|
|
331
|
-
return this.isRemoteLayer() && Boolean(this.
|
|
331
|
+
return this.isRemoteLayer() && Boolean(this.properties.remoteData?.dynamic)
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
async getUrl(url, initialUrl) {
|
|
@@ -352,15 +352,15 @@ export class DataLayer {
|
|
|
352
352
|
if (!this.hasDynamicData() && this.isLoaded() && !force) return
|
|
353
353
|
if (!this.isVisible()) return
|
|
354
354
|
// Keep non proxied url for later use in Alert.
|
|
355
|
-
const remoteUrl = this._umap.renderUrl(this.
|
|
355
|
+
const remoteUrl = this._umap.renderUrl(this.properties.remoteData.url)
|
|
356
356
|
let url = remoteUrl
|
|
357
|
-
if (this.
|
|
358
|
-
url = this._umap.proxyUrl(url, this.
|
|
357
|
+
if (this.properties.remoteData.proxy) {
|
|
358
|
+
url = this._umap.proxyUrl(url, this.properties.remoteData.ttl)
|
|
359
359
|
}
|
|
360
360
|
return await this.getUrl(url, remoteUrl).then((raw) => {
|
|
361
361
|
this.clear(false)
|
|
362
362
|
return this._umap.formatter
|
|
363
|
-
.parse(raw, this.
|
|
363
|
+
.parse(raw, this.properties.remoteData.format)
|
|
364
364
|
.then((geojson) => this.fromGeoJSON(geojson, false))
|
|
365
365
|
.catch((error) => {
|
|
366
366
|
console.debug(error)
|
|
@@ -378,22 +378,14 @@ export class DataLayer {
|
|
|
378
378
|
return !this._needsFetch
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
|
|
382
|
-
|
|
381
|
+
setProperties(properties) {
|
|
382
|
+
delete properties.geojson
|
|
383
|
+
this.properties = Utils.CopyJSON(this.defaultProperties) // Start from fresh.
|
|
384
|
+
this.updateProperties(properties)
|
|
383
385
|
}
|
|
384
386
|
|
|
385
|
-
|
|
386
|
-
this.
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
setOptions(options) {
|
|
390
|
-
delete options.geojson
|
|
391
|
-
this.options = Utils.CopyJSON(this.defaultOptions) // Start from fresh.
|
|
392
|
-
this.updateOptions(options)
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
updateOptions(options) {
|
|
396
|
-
this.options = Object.assign(this.options, options)
|
|
387
|
+
updateProperties(properties) {
|
|
388
|
+
this.properties = Object.assign(this.properties, properties)
|
|
397
389
|
this.resetLayer()
|
|
398
390
|
}
|
|
399
391
|
|
|
@@ -414,11 +406,11 @@ export class DataLayer {
|
|
|
414
406
|
}
|
|
415
407
|
|
|
416
408
|
isRemoteLayer() {
|
|
417
|
-
return Boolean(this.
|
|
409
|
+
return Boolean(this.properties.remoteData?.url && this.properties.remoteData.format)
|
|
418
410
|
}
|
|
419
411
|
|
|
420
412
|
isClustered() {
|
|
421
|
-
return this.
|
|
413
|
+
return this.properties.type === 'Cluster'
|
|
422
414
|
}
|
|
423
415
|
|
|
424
416
|
showFeature(feature) {
|
|
@@ -473,11 +465,67 @@ export class DataLayer {
|
|
|
473
465
|
}
|
|
474
466
|
}
|
|
475
467
|
|
|
468
|
+
checkIndexForProperty(name) {
|
|
469
|
+
for (const feature of Object.values(this._features)) {
|
|
470
|
+
if (name in feature.properties) {
|
|
471
|
+
this.indexProperty(name)
|
|
472
|
+
return
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
this.deindexProperty(name)
|
|
476
|
+
}
|
|
477
|
+
|
|
476
478
|
deindexProperty(name) {
|
|
477
479
|
const idx = this._propertiesIndex.indexOf(name)
|
|
478
480
|
if (idx !== -1) this._propertiesIndex.splice(idx, 1)
|
|
479
481
|
}
|
|
480
482
|
|
|
483
|
+
renameProperty(oldName, newName) {
|
|
484
|
+
this.sync.startBatch()
|
|
485
|
+
this.eachFeature((feature) => {
|
|
486
|
+
feature.renameProperty(oldName, newName)
|
|
487
|
+
})
|
|
488
|
+
this.sync.commitBatch()
|
|
489
|
+
this.deindexProperty(oldName)
|
|
490
|
+
this.indexProperty(newName)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
deleteProperty(property) {
|
|
494
|
+
this.sync.startBatch()
|
|
495
|
+
this.eachFeature((feature) => {
|
|
496
|
+
feature.deleteProperty(property)
|
|
497
|
+
})
|
|
498
|
+
this.sync.commitBatch()
|
|
499
|
+
this.deindexProperty(property)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
addProperty() {
|
|
503
|
+
let resolve = undefined
|
|
504
|
+
const promise = new Promise((r) => {
|
|
505
|
+
resolve = r
|
|
506
|
+
})
|
|
507
|
+
this._umap.dialog
|
|
508
|
+
.prompt(translate('Please enter the name of the property'))
|
|
509
|
+
.then(({ prompt }) => {
|
|
510
|
+
if (!prompt || !this.validateName(prompt)) return
|
|
511
|
+
this.indexProperty(prompt)
|
|
512
|
+
resolve()
|
|
513
|
+
})
|
|
514
|
+
return promise
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
validateName(name) {
|
|
518
|
+
if (name.includes('.')) {
|
|
519
|
+
Alert.error(translate('Name “{name}” should not contain a dot.', { name }))
|
|
520
|
+
return false
|
|
521
|
+
}
|
|
522
|
+
if (this.allProperties().includes(name)) {
|
|
523
|
+
Alert.error(translate('This name already exists: “{name}”', { name }))
|
|
524
|
+
return false
|
|
525
|
+
}
|
|
526
|
+
return true
|
|
527
|
+
}
|
|
528
|
+
|
|
481
529
|
allProperties() {
|
|
482
530
|
return this._propertiesIndex
|
|
483
531
|
}
|
|
@@ -502,7 +550,7 @@ export class DataLayer {
|
|
|
502
550
|
}
|
|
503
551
|
|
|
504
552
|
sortFeatures(collection) {
|
|
505
|
-
const sortKeys = this.
|
|
553
|
+
const sortKeys = this.getProperty('sortKey') || U.DEFAULT_LABEL_KEY
|
|
506
554
|
return Utils.sortFeatures(collection, sortKeys, U.lang)
|
|
507
555
|
}
|
|
508
556
|
|
|
@@ -615,7 +663,7 @@ export class DataLayer {
|
|
|
615
663
|
}
|
|
616
664
|
|
|
617
665
|
getColor() {
|
|
618
|
-
return this.
|
|
666
|
+
return this.properties.color || this._umap.getProperty('color')
|
|
619
667
|
}
|
|
620
668
|
|
|
621
669
|
getDeleteUrl() {
|
|
@@ -672,11 +720,11 @@ export class DataLayer {
|
|
|
672
720
|
}
|
|
673
721
|
|
|
674
722
|
clone() {
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
delete
|
|
723
|
+
const properties = Utils.CopyJSON(this.properties)
|
|
724
|
+
properties.name = translate('Clone of {name}', { name: this.properties.name })
|
|
725
|
+
delete properties.id
|
|
678
726
|
const geojson = Utils.CopyJSON(this._geojson)
|
|
679
|
-
const datalayer = this._umap.createDirtyDataLayer(
|
|
727
|
+
const datalayer = this._umap.createDirtyDataLayer(properties)
|
|
680
728
|
datalayer.fromGeoJSON(geojson)
|
|
681
729
|
return datalayer
|
|
682
730
|
}
|
|
@@ -692,19 +740,19 @@ export class DataLayer {
|
|
|
692
740
|
}
|
|
693
741
|
const container = DomUtil.create('div', 'umap-layer-properties-container')
|
|
694
742
|
const metadataFields = [
|
|
695
|
-
'
|
|
696
|
-
'
|
|
743
|
+
'properties.name',
|
|
744
|
+
'properties.description',
|
|
697
745
|
[
|
|
698
|
-
'
|
|
746
|
+
'properties.type',
|
|
699
747
|
{ handler: 'LayerTypeChooser', label: translate('Type of layer') },
|
|
700
748
|
],
|
|
701
|
-
'
|
|
749
|
+
'properties.labelKey',
|
|
702
750
|
[
|
|
703
|
-
'
|
|
751
|
+
'properties.displayOnLoad',
|
|
704
752
|
{ label: translate('Display on load'), handler: 'Switch' },
|
|
705
753
|
],
|
|
706
754
|
[
|
|
707
|
-
'
|
|
755
|
+
'properties.browsable',
|
|
708
756
|
{
|
|
709
757
|
label: translate('Data is browsable'),
|
|
710
758
|
handler: 'Switch',
|
|
@@ -712,7 +760,7 @@ export class DataLayer {
|
|
|
712
760
|
},
|
|
713
761
|
],
|
|
714
762
|
[
|
|
715
|
-
'
|
|
763
|
+
'properties.inCaption',
|
|
716
764
|
{
|
|
717
765
|
label: translate('Show this layer in the caption'),
|
|
718
766
|
handler: 'Switch',
|
|
@@ -723,16 +771,16 @@ export class DataLayer {
|
|
|
723
771
|
let builder = new MutatingForm(this, metadataFields)
|
|
724
772
|
builder.on('set', ({ detail }) => {
|
|
725
773
|
this._umap.onDataLayersChanged()
|
|
726
|
-
if (detail.helper.field === '
|
|
774
|
+
if (detail.helper.field === 'properties.type') {
|
|
727
775
|
this.edit()
|
|
728
776
|
}
|
|
729
777
|
})
|
|
730
778
|
container.appendChild(builder.build())
|
|
731
779
|
|
|
732
|
-
const
|
|
780
|
+
const layerFields = this.layer.getEditableProperties()
|
|
733
781
|
|
|
734
|
-
if (
|
|
735
|
-
builder = new MutatingForm(this,
|
|
782
|
+
if (layerFields.length) {
|
|
783
|
+
builder = new MutatingForm(this, layerFields, {
|
|
736
784
|
id: 'datalayer-layer-properties',
|
|
737
785
|
})
|
|
738
786
|
const layerProperties = DomUtil.createFieldset(
|
|
@@ -742,60 +790,60 @@ export class DataLayer {
|
|
|
742
790
|
layerProperties.appendChild(builder.build())
|
|
743
791
|
}
|
|
744
792
|
|
|
745
|
-
const
|
|
746
|
-
'
|
|
747
|
-
'
|
|
748
|
-
'
|
|
749
|
-
'
|
|
750
|
-
'
|
|
751
|
-
'
|
|
752
|
-
'
|
|
753
|
-
'
|
|
754
|
-
'
|
|
755
|
-
'
|
|
793
|
+
const shapeFields = [
|
|
794
|
+
'properties.color',
|
|
795
|
+
'properties.iconClass',
|
|
796
|
+
'properties.iconUrl',
|
|
797
|
+
'properties.iconOpacity',
|
|
798
|
+
'properties.opacity',
|
|
799
|
+
'properties.stroke',
|
|
800
|
+
'properties.weight',
|
|
801
|
+
'properties.fill',
|
|
802
|
+
'properties.fillColor',
|
|
803
|
+
'properties.fillOpacity',
|
|
756
804
|
]
|
|
757
805
|
|
|
758
|
-
builder = new MutatingForm(this,
|
|
806
|
+
builder = new MutatingForm(this, shapeFields, {
|
|
759
807
|
id: 'datalayer-advanced-properties',
|
|
760
808
|
})
|
|
761
|
-
const
|
|
809
|
+
const shapeFieldset = DomUtil.createFieldset(
|
|
762
810
|
container,
|
|
763
811
|
translate('Shape properties')
|
|
764
812
|
)
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const
|
|
768
|
-
'
|
|
769
|
-
'
|
|
770
|
-
'
|
|
771
|
-
'
|
|
772
|
-
'
|
|
773
|
-
'
|
|
813
|
+
shapeFieldset.appendChild(builder.build())
|
|
814
|
+
|
|
815
|
+
const advancedFields = [
|
|
816
|
+
'properties.smoothFactor',
|
|
817
|
+
'properties.dashArray',
|
|
818
|
+
'properties.zoomTo',
|
|
819
|
+
'properties.fromZoom',
|
|
820
|
+
'properties.toZoom',
|
|
821
|
+
'properties.sortKey',
|
|
774
822
|
]
|
|
775
823
|
|
|
776
|
-
builder = new MutatingForm(this,
|
|
824
|
+
builder = new MutatingForm(this, advancedFields, {
|
|
777
825
|
id: 'datalayer-advanced-properties',
|
|
778
826
|
})
|
|
779
827
|
builder.on('set', ({ detail }) => {
|
|
780
|
-
if (detail.helper.field === '
|
|
828
|
+
if (detail.helper.field === 'properties.sortKey') {
|
|
781
829
|
this.reindex()
|
|
782
830
|
}
|
|
783
831
|
})
|
|
784
|
-
const
|
|
832
|
+
const advancedFieldset = DomUtil.createFieldset(
|
|
785
833
|
container,
|
|
786
834
|
translate('Advanced properties')
|
|
787
835
|
)
|
|
788
|
-
|
|
836
|
+
advancedFieldset.appendChild(builder.build())
|
|
789
837
|
|
|
790
838
|
const popupFields = [
|
|
791
|
-
'
|
|
792
|
-
'
|
|
793
|
-
'
|
|
794
|
-
'
|
|
795
|
-
'
|
|
796
|
-
'
|
|
797
|
-
'
|
|
798
|
-
'
|
|
839
|
+
'properties.popupShape',
|
|
840
|
+
'properties.popupTemplate',
|
|
841
|
+
'properties.popupContentTemplate',
|
|
842
|
+
'properties.showLabel',
|
|
843
|
+
'properties.labelDirection',
|
|
844
|
+
'properties.labelInteractive',
|
|
845
|
+
'properties.outlinkTarget',
|
|
846
|
+
'properties.interactive',
|
|
799
847
|
]
|
|
800
848
|
builder = new MutatingForm(this, popupFields)
|
|
801
849
|
const popupFieldset = DomUtil.createFieldset(
|
|
@@ -804,25 +852,38 @@ export class DataLayer {
|
|
|
804
852
|
)
|
|
805
853
|
popupFieldset.appendChild(builder.build())
|
|
806
854
|
|
|
855
|
+
const textPathFields = [
|
|
856
|
+
'properties.textPath',
|
|
857
|
+
'properties.textPathColor',
|
|
858
|
+
'properties.textPathRepeat',
|
|
859
|
+
'properties.textPathRotate',
|
|
860
|
+
'properties.textPathSize',
|
|
861
|
+
'properties.textPathOffset',
|
|
862
|
+
'properties.textPathPosition',
|
|
863
|
+
]
|
|
864
|
+
builder = new MutatingForm(this, textPathFields)
|
|
865
|
+
const fieldset = DomUtil.createFieldset(container, translate('Line decoration'))
|
|
866
|
+
fieldset.appendChild(builder.build())
|
|
867
|
+
|
|
807
868
|
// XXX I'm not sure **why** this is needed (as it's set during `this.initialize`)
|
|
808
869
|
// but apparently it's needed.
|
|
809
|
-
if (!Utils.isObject(this.
|
|
810
|
-
this.
|
|
870
|
+
if (!Utils.isObject(this.properties.remoteData)) {
|
|
871
|
+
this.properties.remoteData = {}
|
|
811
872
|
}
|
|
812
873
|
|
|
813
874
|
const remoteDataFields = [
|
|
814
875
|
[
|
|
815
|
-
'
|
|
876
|
+
'properties.remoteData.url',
|
|
816
877
|
{ handler: 'Url', label: translate('Url'), helpEntries: ['formatURL'] },
|
|
817
878
|
],
|
|
818
879
|
[
|
|
819
|
-
'
|
|
880
|
+
'properties.remoteData.format',
|
|
820
881
|
{ handler: 'DataFormat', label: translate('Format') },
|
|
821
882
|
],
|
|
822
|
-
'
|
|
823
|
-
'
|
|
883
|
+
'properties.fromZoom',
|
|
884
|
+
'properties.toZoom',
|
|
824
885
|
[
|
|
825
|
-
'
|
|
886
|
+
'properties.remoteData.dynamic',
|
|
826
887
|
{
|
|
827
888
|
handler: 'Switch',
|
|
828
889
|
label: translate('Dynamic'),
|
|
@@ -830,7 +891,7 @@ export class DataLayer {
|
|
|
830
891
|
},
|
|
831
892
|
],
|
|
832
893
|
[
|
|
833
|
-
'
|
|
894
|
+
'properties.remoteData.licence',
|
|
834
895
|
{
|
|
835
896
|
label: translate('Licence'),
|
|
836
897
|
helpText: translate('Please be sure the licence is compliant with your use.'),
|
|
@@ -839,14 +900,14 @@ export class DataLayer {
|
|
|
839
900
|
]
|
|
840
901
|
if (this._umap.properties.urls.ajax_proxy) {
|
|
841
902
|
remoteDataFields.push([
|
|
842
|
-
'
|
|
903
|
+
'properties.remoteData.proxy',
|
|
843
904
|
{
|
|
844
905
|
handler: 'Switch',
|
|
845
906
|
label: translate('Proxy request'),
|
|
846
907
|
helpEntries: ['proxyRemoteData'],
|
|
847
908
|
},
|
|
848
909
|
])
|
|
849
|
-
remoteDataFields.push('
|
|
910
|
+
remoteDataFields.push('properties.remoteData.ttl')
|
|
850
911
|
}
|
|
851
912
|
|
|
852
913
|
const remoteDataContainer = DomUtil.createFieldset(
|
|
@@ -862,6 +923,7 @@ export class DataLayer {
|
|
|
862
923
|
() => this.fetchRemoteData(true),
|
|
863
924
|
this
|
|
864
925
|
)
|
|
926
|
+
this.rules.edit(container)
|
|
865
927
|
|
|
866
928
|
if (this._umap.properties.urls.datalayer_versions) {
|
|
867
929
|
this.buildVersionsFieldset(container)
|
|
@@ -871,7 +933,7 @@ export class DataLayer {
|
|
|
871
933
|
container,
|
|
872
934
|
translate('Advanced actions')
|
|
873
935
|
)
|
|
874
|
-
const filename = `${Utils.slugify(this.
|
|
936
|
+
const filename = `${Utils.slugify(this.properties.name)}.geojson`
|
|
875
937
|
const tpl = `
|
|
876
938
|
<div class="button-bar half">
|
|
877
939
|
<button class="button" type="button" data-ref=del>
|
|
@@ -918,22 +980,31 @@ export class DataLayer {
|
|
|
918
980
|
})
|
|
919
981
|
}
|
|
920
982
|
|
|
921
|
-
|
|
922
|
-
if (Utils.usableOption(this.
|
|
983
|
+
getOwnProperty(option) {
|
|
984
|
+
if (Utils.usableOption(this.properties, option)) return this.properties[option]
|
|
923
985
|
}
|
|
924
986
|
|
|
925
|
-
|
|
987
|
+
getProperty(key, feature) {
|
|
926
988
|
if (this.layer?.getOption) {
|
|
927
|
-
const value = this.layer.getOption(
|
|
989
|
+
const value = this.layer.getOption(key, feature)
|
|
928
990
|
if (value !== undefined) return value
|
|
929
991
|
}
|
|
930
|
-
if (
|
|
931
|
-
|
|
992
|
+
if (feature) {
|
|
993
|
+
const value = this.rules.getOption(key, feature)
|
|
994
|
+
if (value !== undefined) return value
|
|
995
|
+
}
|
|
996
|
+
if (this.getOwnProperty(key) !== undefined) {
|
|
997
|
+
return this.getOwnProperty(key)
|
|
932
998
|
}
|
|
933
|
-
if (this.layer?.defaults?.[
|
|
934
|
-
return this.layer.defaults[
|
|
999
|
+
if (this.layer?.defaults?.[key]) {
|
|
1000
|
+
return this.layer.defaults[key]
|
|
935
1001
|
}
|
|
936
|
-
return this._umap.getProperty(
|
|
1002
|
+
return this._umap.getProperty(key, feature)
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
getOption(key, feature) {
|
|
1006
|
+
// TODO: remove when field.js does not call blindly obj.getOption anymore
|
|
1007
|
+
return this.getProperty(key, feature)
|
|
937
1008
|
}
|
|
938
1009
|
|
|
939
1010
|
async buildVersionsFieldset(container) {
|
|
@@ -973,9 +1044,9 @@ export class DataLayer {
|
|
|
973
1044
|
if (!error) {
|
|
974
1045
|
if (geojson._storage) geojson._umap_options = geojson._storage // Retrocompat.
|
|
975
1046
|
if (geojson._umap_options) {
|
|
976
|
-
const
|
|
977
|
-
this.
|
|
978
|
-
this.sync.update('
|
|
1047
|
+
const oldProperties = Utils.CopyJSON(this.properties)
|
|
1048
|
+
this.setProperties(geojson._umap_options)
|
|
1049
|
+
this.sync.update('properties', this.properties, oldProperties)
|
|
979
1050
|
}
|
|
980
1051
|
this.empty()
|
|
981
1052
|
if (this.isRemoteLayer()) {
|
|
@@ -1028,7 +1099,7 @@ export class DataLayer {
|
|
|
1028
1099
|
|
|
1029
1100
|
zoomToBounds(bounds) {
|
|
1030
1101
|
if (bounds.isValid()) {
|
|
1031
|
-
const options = { maxZoom: this.
|
|
1102
|
+
const options = { maxZoom: this.getProperty('zoomTo') }
|
|
1032
1103
|
this._leafletMap.fitBounds(bounds, options)
|
|
1033
1104
|
}
|
|
1034
1105
|
}
|
|
@@ -1041,7 +1112,7 @@ export class DataLayer {
|
|
|
1041
1112
|
// Is this layer browsable in theorie
|
|
1042
1113
|
// AND the user allows it
|
|
1043
1114
|
allowBrowse() {
|
|
1044
|
-
return !!this.
|
|
1115
|
+
return !!this.properties.browsable && this.isBrowsable()
|
|
1045
1116
|
}
|
|
1046
1117
|
|
|
1047
1118
|
// Is this layer browsable in theorie
|
|
@@ -1106,7 +1177,7 @@ export class DataLayer {
|
|
|
1106
1177
|
return {
|
|
1107
1178
|
type: 'FeatureCollection',
|
|
1108
1179
|
features: this.isRemoteLayer() ? [] : this.featuresToGeoJSON(),
|
|
1109
|
-
_umap_options: this.
|
|
1180
|
+
_umap_options: this.properties,
|
|
1110
1181
|
}
|
|
1111
1182
|
}
|
|
1112
1183
|
|
|
@@ -1116,7 +1187,7 @@ export class DataLayer {
|
|
|
1116
1187
|
|
|
1117
1188
|
isReadOnly() {
|
|
1118
1189
|
// isReadOnly must return true if unset
|
|
1119
|
-
return this.
|
|
1190
|
+
return this.properties.editMode === 'disabled'
|
|
1120
1191
|
}
|
|
1121
1192
|
|
|
1122
1193
|
isDataReadOnly() {
|
|
@@ -1133,10 +1204,10 @@ export class DataLayer {
|
|
|
1133
1204
|
}
|
|
1134
1205
|
}
|
|
1135
1206
|
|
|
1136
|
-
|
|
1137
|
-
const
|
|
1138
|
-
delete
|
|
1139
|
-
return JSON.stringify(
|
|
1207
|
+
prepareProperties() {
|
|
1208
|
+
const properties = Utils.CopyJSON(this.properties)
|
|
1209
|
+
delete properties.permissions
|
|
1210
|
+
return JSON.stringify(properties)
|
|
1140
1211
|
}
|
|
1141
1212
|
|
|
1142
1213
|
async save() {
|
|
@@ -1144,10 +1215,10 @@ export class DataLayer {
|
|
|
1144
1215
|
if (!this.isRemoteLayer() && !this.isLoaded()) return
|
|
1145
1216
|
const geojson = this.umapGeoJSON()
|
|
1146
1217
|
const formData = new FormData()
|
|
1147
|
-
formData.append('name', this.
|
|
1148
|
-
formData.append('display_on_load', !!this.
|
|
1218
|
+
formData.append('name', this.properties.name)
|
|
1219
|
+
formData.append('display_on_load', !!this.properties.displayOnLoad)
|
|
1149
1220
|
formData.append('rank', this.rank)
|
|
1150
|
-
formData.append('settings', this.
|
|
1221
|
+
formData.append('settings', this.prepareProperties())
|
|
1151
1222
|
// Filename support is shaky, don't do it for now.
|
|
1152
1223
|
const blob = new Blob([JSON.stringify(geojson)], { type: 'application/json' })
|
|
1153
1224
|
formData.append('geojson', blob)
|
|
@@ -1196,11 +1267,10 @@ export class DataLayer {
|
|
|
1196
1267
|
}
|
|
1197
1268
|
delete data.id
|
|
1198
1269
|
delete data._referenceVersion
|
|
1199
|
-
this.
|
|
1270
|
+
this.updateProperties(data)
|
|
1200
1271
|
|
|
1201
1272
|
this.setReferenceVersion({ response, sync: true })
|
|
1202
1273
|
|
|
1203
|
-
this.backupOptions()
|
|
1204
1274
|
this.backupData()
|
|
1205
1275
|
this.connectToMap()
|
|
1206
1276
|
this.redraw() // Needed for reordering features
|
|
@@ -1221,7 +1291,7 @@ export class DataLayer {
|
|
|
1221
1291
|
}
|
|
1222
1292
|
|
|
1223
1293
|
getName() {
|
|
1224
|
-
return this.
|
|
1294
|
+
return this.properties.name || translate('Untitled layer')
|
|
1225
1295
|
}
|
|
1226
1296
|
|
|
1227
1297
|
getPermalink() {
|
|
@@ -1241,7 +1311,7 @@ export class DataLayer {
|
|
|
1241
1311
|
// By default, it will we use the "name" property, which is also the one used as label in the features list.
|
|
1242
1312
|
// When map owner has configured another label or sort key, we try to be smart and search in the same keys.
|
|
1243
1313
|
if (this._umap.properties.filterKey) return this._umap.properties.filterKey
|
|
1244
|
-
if (this.
|
|
1314
|
+
if (this.getProperty('labelKey')) return this.getProperty('labelKey')
|
|
1245
1315
|
if (this._umap.properties.sortKey) return this._umap.properties.sortKey
|
|
1246
1316
|
return 'displayName'
|
|
1247
1317
|
}
|