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