umap-project 3.4.0b3__py3-none-any.whl → 3.6.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.
- umap/__init__.py +1 -1
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +71 -57
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +18 -14
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +20 -16
- umap/locale/en/LC_MESSAGES/django.po +18 -14
- 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/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +20 -16
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +101 -95
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +20 -16
- umap/management/commands/clean_tilelayer.py +0 -1
- umap/management/commands/search_maps.py +95 -0
- umap/settings/__init__.py +9 -1
- umap/settings/base.py +7 -6
- 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/icon.css +8 -0
- umap/static/umap/css/popup.css +1 -0
- umap/static/umap/img/16-white.svg +5 -2
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/source/16-white.svg +7 -4
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/js/components/copiable.js +47 -0
- umap/static/umap/js/modules/autocomplete.js +32 -67
- umap/static/umap/js/modules/browser.js +31 -14
- umap/static/umap/js/modules/data/features.js +34 -36
- umap/static/umap/js/modules/data/fields.js +199 -23
- umap/static/umap/js/modules/data/layer.js +85 -96
- umap/static/umap/js/modules/domutils.js +25 -1
- umap/static/umap/js/modules/filters.js +24 -50
- umap/static/umap/js/modules/form/builder.js +17 -16
- umap/static/umap/js/modules/form/fields.js +20 -20
- 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 +15 -5
- umap/static/umap/js/modules/rendering/controls.js +203 -10
- 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 +16 -11
- umap/static/umap/js/modules/rendering/layers/heat.js +1 -0
- umap/static/umap/js/modules/rendering/map.js +67 -57
- umap/static/umap/js/modules/rendering/popup.js +6 -3
- umap/static/umap/js/modules/rendering/template.js +40 -40
- 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 +53 -33
- umap/static/umap/js/modules/ui/hash.js +36 -0
- umap/static/umap/js/modules/ui/loader.js +26 -0
- umap/static/umap/js/modules/ui/panel.js +33 -21
- umap/static/umap/js/modules/ui/tooltip.js +1 -1
- umap/static/umap/js/modules/umap.js +81 -80
- umap/static/umap/js/modules/utils.js +13 -3
- umap/static/umap/js/umap.controls.js +16 -179
- umap/static/umap/locale/am_ET.js +7 -8
- umap/static/umap/locale/am_ET.json +7 -8
- umap/static/umap/locale/ar.js +7 -8
- umap/static/umap/locale/ar.json +7 -8
- umap/static/umap/locale/ast.js +7 -8
- umap/static/umap/locale/ast.json +7 -8
- umap/static/umap/locale/bg.js +7 -8
- umap/static/umap/locale/bg.json +7 -8
- umap/static/umap/locale/br.js +44 -36
- umap/static/umap/locale/br.json +44 -36
- umap/static/umap/locale/ca.js +7 -8
- umap/static/umap/locale/ca.json +7 -8
- umap/static/umap/locale/cs_CZ.js +7 -8
- umap/static/umap/locale/cs_CZ.json +7 -8
- umap/static/umap/locale/da.js +8 -9
- umap/static/umap/locale/da.json +8 -9
- umap/static/umap/locale/de.js +62 -63
- umap/static/umap/locale/de.json +62 -63
- umap/static/umap/locale/el.js +7 -8
- umap/static/umap/locale/el.json +7 -8
- umap/static/umap/locale/en.js +7 -8
- umap/static/umap/locale/en.json +7 -8
- umap/static/umap/locale/en_US.json +7 -8
- umap/static/umap/locale/es.js +19 -20
- umap/static/umap/locale/es.json +19 -20
- umap/static/umap/locale/et.js +7 -8
- umap/static/umap/locale/et.json +7 -8
- umap/static/umap/locale/eu.js +23 -24
- umap/static/umap/locale/eu.json +23 -24
- umap/static/umap/locale/fa_IR.js +7 -8
- umap/static/umap/locale/fa_IR.json +7 -8
- umap/static/umap/locale/fi.js +7 -8
- umap/static/umap/locale/fi.json +7 -8
- umap/static/umap/locale/fr.js +11 -12
- umap/static/umap/locale/fr.json +11 -12
- umap/static/umap/locale/gl.js +147 -148
- umap/static/umap/locale/gl.json +147 -148
- umap/static/umap/locale/he.js +7 -8
- umap/static/umap/locale/he.json +7 -8
- umap/static/umap/locale/hr.js +7 -8
- umap/static/umap/locale/hr.json +7 -8
- umap/static/umap/locale/hu.js +8 -9
- umap/static/umap/locale/hu.json +8 -9
- umap/static/umap/locale/id.js +7 -8
- umap/static/umap/locale/id.json +7 -8
- umap/static/umap/locale/is.js +7 -8
- umap/static/umap/locale/is.json +7 -8
- umap/static/umap/locale/it.js +7 -8
- umap/static/umap/locale/it.json +7 -8
- umap/static/umap/locale/ja.js +7 -8
- umap/static/umap/locale/ja.json +7 -8
- umap/static/umap/locale/ko.js +7 -8
- umap/static/umap/locale/ko.json +7 -8
- umap/static/umap/locale/lt.js +7 -8
- umap/static/umap/locale/lt.json +7 -8
- umap/static/umap/locale/ms.js +7 -8
- umap/static/umap/locale/ms.json +7 -8
- umap/static/umap/locale/nl.js +7 -8
- umap/static/umap/locale/nl.json +7 -8
- umap/static/umap/locale/no.js +7 -8
- umap/static/umap/locale/no.json +7 -8
- umap/static/umap/locale/pl.js +53 -54
- umap/static/umap/locale/pl.json +53 -54
- umap/static/umap/locale/pl_PL.json +7 -8
- umap/static/umap/locale/pt.js +7 -8
- umap/static/umap/locale/pt.json +7 -8
- umap/static/umap/locale/pt_BR.js +7 -8
- umap/static/umap/locale/pt_BR.json +7 -8
- umap/static/umap/locale/pt_PT.js +7 -8
- umap/static/umap/locale/pt_PT.json +7 -8
- umap/static/umap/locale/ro.js +7 -8
- umap/static/umap/locale/ro.json +7 -8
- umap/static/umap/locale/ru.js +7 -8
- umap/static/umap/locale/ru.json +7 -8
- umap/static/umap/locale/sk_SK.js +7 -8
- umap/static/umap/locale/sk_SK.json +7 -8
- umap/static/umap/locale/sl.js +7 -8
- umap/static/umap/locale/sl.json +7 -8
- umap/static/umap/locale/sr.js +7 -8
- umap/static/umap/locale/sr.json +7 -8
- umap/static/umap/locale/sv.js +7 -8
- umap/static/umap/locale/sv.json +7 -8
- umap/static/umap/locale/th_TH.js +7 -8
- umap/static/umap/locale/th_TH.json +7 -8
- umap/static/umap/locale/tr.js +7 -8
- umap/static/umap/locale/tr.json +7 -8
- umap/static/umap/locale/uk_UA.js +7 -8
- umap/static/umap/locale/uk_UA.json +7 -8
- umap/static/umap/locale/vi.js +7 -8
- umap/static/umap/locale/vi.json +7 -8
- umap/static/umap/locale/vi_VN.json +7 -8
- umap/static/umap/locale/zh.js +7 -8
- umap/static/umap/locale/zh.json +7 -8
- umap/static/umap/locale/zh_CN.json +7 -8
- umap/static/umap/locale/zh_TW.Big5.json +7 -8
- umap/static/umap/locale/zh_TW.js +20 -21
- umap/static/umap/locale/zh_TW.json +20 -21
- umap/static/umap/map.css +6 -21
- umap/static/umap/unittests/utils.js +7 -7
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.esm.js +942 -0
- umap/static/umap/vendors/photon/leaflet.photon.esm.js +472 -0
- umap/sync/app.py +4 -1
- umap/templates/umap/content_footer.html +1 -0
- umap/templates/umap/css.html +0 -4
- umap/templates/umap/js.html +1 -8
- umap/templates/umap/team_form.html +2 -1
- 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_edit_map.py +2 -0
- umap/tests/integration/test_fields.py +19 -0
- umap/tests/integration/test_filters.py +24 -0
- umap/tests/integration/test_iframe.py +1 -1
- umap/tests/integration/test_import.py +26 -0
- umap/tests/integration/test_map.py +3 -3
- umap/tests/integration/test_optimistic_merge.py +7 -1
- umap/tests/integration/test_owned_map.py +2 -2
- umap/tests/integration/test_popup.py +31 -0
- umap/tests/integration/test_remote_data.py +5 -5
- 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_search_maps_command.py +44 -0
- umap/tests/test_utils.py +4 -1
- umap/utils.py +10 -3
- umap/views.py +17 -4
- {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/METADATA +29 -23
- {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/RECORD +210 -214
- {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/WHEEL +1 -1
- 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/static/umap/vendors/hash/leaflet-hash.js +0 -162
- umap/static/umap/vendors/loading/Control.Loading.css +0 -26
- umap/static/umap/vendors/loading/Control.Loading.js +0 -351
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css +0 -1
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css.map +0 -1
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +0 -4
- umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +0 -1
- umap/static/umap/vendors/photon/leaflet.photon.js +0 -487
- {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/entry_points.txt +0 -0
- {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
// Goes here all code related to Leaflet, DOM and user interactions.
|
|
2
2
|
import {
|
|
3
3
|
Map as BaseMap,
|
|
4
|
+
Browser,
|
|
4
5
|
Control,
|
|
5
6
|
DomEvent,
|
|
6
|
-
DomUtil,
|
|
7
7
|
latLng,
|
|
8
|
-
|
|
8
|
+
LatLng,
|
|
9
|
+
LatLngBounds,
|
|
10
|
+
stamp,
|
|
9
11
|
setOptions,
|
|
12
|
+
TileLayer,
|
|
10
13
|
} from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
11
14
|
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
|
|
12
15
|
import DropControl from '../drop.js'
|
|
@@ -18,6 +21,7 @@ import {
|
|
|
18
21
|
EmbedControl,
|
|
19
22
|
EditControl,
|
|
20
23
|
HomeControl,
|
|
24
|
+
LocateControl,
|
|
21
25
|
MoreControl,
|
|
22
26
|
PermanentCreditsControl,
|
|
23
27
|
TileLayerChooser,
|
|
@@ -46,7 +50,6 @@ const ControlsMixin = {
|
|
|
46
50
|
'caption',
|
|
47
51
|
'locate',
|
|
48
52
|
'measure',
|
|
49
|
-
'editinosm',
|
|
50
53
|
'print',
|
|
51
54
|
'tilelayers',
|
|
52
55
|
],
|
|
@@ -68,19 +71,7 @@ const ControlsMixin = {
|
|
|
68
71
|
})
|
|
69
72
|
this._controls.datalayers = new DataLayersControl(this._umap)
|
|
70
73
|
this._controls.caption = new CaptionControl(this._umap)
|
|
71
|
-
this._controls.locate = new
|
|
72
|
-
strings: {
|
|
73
|
-
title: translate('Center map on your location'),
|
|
74
|
-
},
|
|
75
|
-
showPopup: false,
|
|
76
|
-
// We style this control in our own CSS for consistency with other controls,
|
|
77
|
-
// but the control breaks if we don't specify a class here, so a fake class
|
|
78
|
-
// will do.
|
|
79
|
-
icon: 'umap-fake-class',
|
|
80
|
-
iconLoading: 'umap-fake-class',
|
|
81
|
-
flyTo: this.options.easing,
|
|
82
|
-
onLocationError: (err) => U.Alert.error(err.message),
|
|
83
|
-
})
|
|
74
|
+
this._controls.locate = new LocateControl(this._umap)
|
|
84
75
|
this._controls.fullscreen = new Control.Fullscreen({
|
|
85
76
|
title: {
|
|
86
77
|
false: translate('View Fullscreen'),
|
|
@@ -91,17 +82,9 @@ const ControlsMixin = {
|
|
|
91
82
|
this._controls.embed = new EmbedControl(this._umap)
|
|
92
83
|
this._controls.print = new PrintControl(this._umap)
|
|
93
84
|
this._controls.tilelayersChooser = new TileLayerChooser(this._umap)
|
|
94
|
-
this._controls.editinosm = new Control.EditInOSM({
|
|
95
|
-
position: 'topleft',
|
|
96
|
-
widgetOptions: {
|
|
97
|
-
helpText: translate(
|
|
98
|
-
'Open this map extent in a map editor to provide more accurate data to OpenStreetMap'
|
|
99
|
-
),
|
|
100
|
-
},
|
|
101
|
-
})
|
|
102
85
|
this._controls.measure = new L.MeasureControl().initHandler(this)
|
|
103
86
|
this._controls.more = new MoreControl()
|
|
104
|
-
this._controls.scale =
|
|
87
|
+
this._controls.scale = new Control.Scale()
|
|
105
88
|
this._controls.permanentCredit = new PermanentCreditsControl(this)
|
|
106
89
|
this._umap.drop = new DropControl(this._umap, this, this._container)
|
|
107
90
|
this._controls.tilelayers = new U.TileLayerControl(this)
|
|
@@ -138,11 +121,10 @@ const ControlsMixin = {
|
|
|
138
121
|
const control = this._controls[name]
|
|
139
122
|
if (!control) continue
|
|
140
123
|
control.addTo(this)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
124
|
+
control._container.classList.toggle(
|
|
125
|
+
'display-on-more',
|
|
126
|
+
status === undefined || status === null
|
|
127
|
+
)
|
|
146
128
|
}
|
|
147
129
|
if (this._umap.getProperty('permanentCredit'))
|
|
148
130
|
this._controls.permanentCredit.addTo(this)
|
|
@@ -176,13 +158,25 @@ const ManageTilelayerMixin = {
|
|
|
176
158
|
if (this._controls) this._controls.tilelayers.setLayers()
|
|
177
159
|
},
|
|
178
160
|
|
|
179
|
-
createTileLayer: (tilelayer) => new
|
|
161
|
+
createTileLayer: (tilelayer) => new TileLayer(tilelayer.url_template, tilelayer),
|
|
180
162
|
|
|
181
163
|
selectTileLayer: function (tilelayer) {
|
|
182
164
|
if (tilelayer === this.selectedTilelayer) {
|
|
183
165
|
return
|
|
184
166
|
}
|
|
167
|
+
const onLoading = () => {
|
|
168
|
+
this._umap.loader.start(stamp(tilelayer))
|
|
169
|
+
}
|
|
170
|
+
const onLoad = () => {
|
|
171
|
+
this._umap.loader.stop(stamp(tilelayer))
|
|
172
|
+
}
|
|
185
173
|
try {
|
|
174
|
+
tilelayer.on('loading', onLoading)
|
|
175
|
+
tilelayer.on('load', onLoad)
|
|
176
|
+
tilelayer.on('remove', () => {
|
|
177
|
+
tilelayer.off('loading', onLoading)
|
|
178
|
+
tilelayer.off('load', onLoad)
|
|
179
|
+
})
|
|
186
180
|
this.addLayer(tilelayer)
|
|
187
181
|
this.fire('baselayerchange', { layer: tilelayer })
|
|
188
182
|
if (this.selectedTilelayer) {
|
|
@@ -261,19 +255,13 @@ export const LeafletMap = BaseMap.extend({
|
|
|
261
255
|
|
|
262
256
|
BaseMap.prototype.initialize.call(this, element, options)
|
|
263
257
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.fire('dataloading', event.detail)
|
|
272
|
-
)
|
|
273
|
-
DomEvent.on(document.body, 'dataload', (event) =>
|
|
274
|
-
this.fire('dataload', event.detail)
|
|
275
|
-
)
|
|
276
|
-
}
|
|
258
|
+
document.body.addEventListener('mapview:update', (event) => {
|
|
259
|
+
let { zoom, latlng } = event.detail
|
|
260
|
+
if (!Utils.LatLngIsValid(latlng)) return
|
|
261
|
+
zoom = Math.min(zoom, this.getMaxZoom())
|
|
262
|
+
zoom = Math.max(zoom, this.getMinZoom())
|
|
263
|
+
this.setView(latlng, zoom)
|
|
264
|
+
})
|
|
277
265
|
|
|
278
266
|
this.on('baselayerchange', (e) => {
|
|
279
267
|
if (this._controls.miniMap) this._controls.miniMap.onMainMapBaseLayerChange(e)
|
|
@@ -284,6 +272,21 @@ export const LeafletMap = BaseMap.extend({
|
|
|
284
272
|
this.initControls()
|
|
285
273
|
// Needs locate control and hash to exist
|
|
286
274
|
this.initCenter()
|
|
275
|
+
|
|
276
|
+
// Wait for URL to have been parsed before modifying the hash
|
|
277
|
+
const updateHash = () => {
|
|
278
|
+
const center = this.getCenter()
|
|
279
|
+
document.body.dispatchEvent(
|
|
280
|
+
new CustomEvent('mapview:updated', {
|
|
281
|
+
detail: {
|
|
282
|
+
zoom: this.getZoom(),
|
|
283
|
+
latlng: [center.lat.toFixed(6), center.lng.toFixed(6)],
|
|
284
|
+
},
|
|
285
|
+
})
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
this.on('moveend', updateHash)
|
|
289
|
+
updateHash()
|
|
287
290
|
this.initTileLayers()
|
|
288
291
|
this.renderUI()
|
|
289
292
|
},
|
|
@@ -303,7 +306,7 @@ export const LeafletMap = BaseMap.extend({
|
|
|
303
306
|
// when scrolling the main page and touching the
|
|
304
307
|
// map in an iframe. May be a bit dumb, but let's
|
|
305
308
|
// try like this for now.
|
|
306
|
-
if (
|
|
309
|
+
if (Browser.mobile) this.dragging.disable()
|
|
307
310
|
}
|
|
308
311
|
// Needs tilelayer to exist for minimap
|
|
309
312
|
this.renderControls()
|
|
@@ -312,7 +315,7 @@ export const LeafletMap = BaseMap.extend({
|
|
|
312
315
|
|
|
313
316
|
latLng: (a, b, c) => {
|
|
314
317
|
// manage geojson case and call original method
|
|
315
|
-
if (!(a instanceof
|
|
318
|
+
if (!(a instanceof LatLng) && a.coordinates) {
|
|
316
319
|
// Guess it's a geojson
|
|
317
320
|
a = [a.coordinates[1], a.coordinates[0]]
|
|
318
321
|
}
|
|
@@ -324,14 +327,13 @@ export const LeafletMap = BaseMap.extend({
|
|
|
324
327
|
this.setView(this.options.center, this.options.zoom)
|
|
325
328
|
},
|
|
326
329
|
|
|
327
|
-
initCenter: function () {
|
|
330
|
+
initCenter: async function () {
|
|
328
331
|
this._setDefaultCenter()
|
|
329
|
-
if (this.options.hash
|
|
330
|
-
if (this.options.hash && this._hash.parseHash(location.hash)) {
|
|
332
|
+
if (this.options.hash && window.location.hash) {
|
|
331
333
|
// FIXME An invalid hash will cause the load to fail
|
|
332
|
-
this.
|
|
334
|
+
this._umap.hash.parse()
|
|
333
335
|
} else if (this.options.defaultView === 'locate' && !this.options.noControl) {
|
|
334
|
-
this._controls.locate.start()
|
|
336
|
+
await this._controls.locate.start()
|
|
335
337
|
} else if (this.options.defaultView === 'data') {
|
|
336
338
|
this._umap.onceDataLoaded(this._umap.fitDataBounds)
|
|
337
339
|
} else if (this.options.defaultView === 'latest') {
|
|
@@ -351,17 +353,17 @@ export const LeafletMap = BaseMap.extend({
|
|
|
351
353
|
},
|
|
352
354
|
|
|
353
355
|
handleLimitBounds: function () {
|
|
354
|
-
const south = Number.parseFloat(this.options.limitBounds
|
|
355
|
-
const west = Number.parseFloat(this.options.limitBounds
|
|
356
|
-
const north = Number.parseFloat(this.options.limitBounds
|
|
357
|
-
const east = Number.parseFloat(this.options.limitBounds
|
|
356
|
+
const south = Number.parseFloat(this.options.limitBounds?.south)
|
|
357
|
+
const west = Number.parseFloat(this.options.limitBounds?.west)
|
|
358
|
+
const north = Number.parseFloat(this.options.limitBounds?.north)
|
|
359
|
+
const east = Number.parseFloat(this.options.limitBounds?.east)
|
|
358
360
|
if (
|
|
359
361
|
!Number.isNaN(south) &&
|
|
360
362
|
!Number.isNaN(west) &&
|
|
361
363
|
!Number.isNaN(north) &&
|
|
362
364
|
!Number.isNaN(east)
|
|
363
365
|
) {
|
|
364
|
-
const bounds =
|
|
366
|
+
const bounds = new LatLngBounds([
|
|
365
367
|
[south, west],
|
|
366
368
|
[north, east],
|
|
367
369
|
])
|
|
@@ -381,7 +383,7 @@ export const LeafletMap = BaseMap.extend({
|
|
|
381
383
|
setMaxBounds: function (bounds) {
|
|
382
384
|
// Hack. Remove me when fix is released:
|
|
383
385
|
// https://github.com/Leaflet/Leaflet/pull/4494
|
|
384
|
-
bounds =
|
|
386
|
+
bounds = new LatLngBounds(bounds)
|
|
385
387
|
|
|
386
388
|
if (!bounds.isValid()) {
|
|
387
389
|
this.options.maxBounds = null
|
|
@@ -390,6 +392,14 @@ export const LeafletMap = BaseMap.extend({
|
|
|
390
392
|
return BaseMap.prototype.setMaxBounds.call(this, bounds)
|
|
391
393
|
},
|
|
392
394
|
|
|
395
|
+
getLayersBounds: (layers) => {
|
|
396
|
+
const bounds = new LatLngBounds()
|
|
397
|
+
for (const layer of layers) {
|
|
398
|
+
bounds.extend(layer.getBounds())
|
|
399
|
+
}
|
|
400
|
+
return bounds
|
|
401
|
+
},
|
|
402
|
+
|
|
393
403
|
initEditTools: function () {
|
|
394
404
|
this.editTools = new U.Editable(this._umap)
|
|
395
405
|
},
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Popup as BasePopup,
|
|
3
3
|
DomEvent,
|
|
4
|
-
DomUtil,
|
|
5
4
|
Path,
|
|
6
5
|
} from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
7
6
|
import Browser from '../browser.js'
|
|
8
7
|
import loadTemplate from './template.js'
|
|
8
|
+
import * as DOMUtils from '../domutils.js'
|
|
9
9
|
|
|
10
10
|
export default function loadPopup(name) {
|
|
11
11
|
switch (name) {
|
|
@@ -25,7 +25,8 @@ const Popup = BasePopup.extend({
|
|
|
25
25
|
},
|
|
26
26
|
|
|
27
27
|
loadContent: async function () {
|
|
28
|
-
const container =
|
|
28
|
+
const container = document.createElement('div')
|
|
29
|
+
container.classList.add('umap-popup')
|
|
29
30
|
const name = this.feature.getOption('popupTemplate')
|
|
30
31
|
this.content = await loadTemplate(name, this.feature, container)
|
|
31
32
|
const elements = container.querySelectorAll('img,iframe')
|
|
@@ -34,7 +35,9 @@ const Popup = BasePopup.extend({
|
|
|
34
35
|
}
|
|
35
36
|
if (!elements.length && container.textContent.replace('\n', '') === '') {
|
|
36
37
|
container.innerHTML = ''
|
|
37
|
-
|
|
38
|
+
container.appendChild(
|
|
39
|
+
DOMUtils.loadTemplate(`<h3>${this.feature.getDisplayName()}</h3>`)
|
|
40
|
+
)
|
|
38
41
|
}
|
|
39
42
|
this.setContent(container)
|
|
40
43
|
},
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DomEvent,
|
|
3
|
-
DomUtil,
|
|
4
|
-
CircleMarker,
|
|
5
|
-
} from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
1
|
+
import { DomEvent, CircleMarker } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
6
2
|
import { getLocale, translate } from '../i18n.js'
|
|
7
3
|
import { Request } from '../request.js'
|
|
8
4
|
import * as Utils from '../utils.js'
|
|
@@ -38,8 +34,7 @@ export default async function loadTemplate(name, feature, container) {
|
|
|
38
34
|
class PopupTemplate {
|
|
39
35
|
renderTitle(feature) {}
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
const template = feature.getOption('popupContentTemplate')
|
|
37
|
+
toHTML(feature, template) {
|
|
43
38
|
const target = feature.getOption('outlinkTarget')
|
|
44
39
|
const properties = feature.extendedProperties()
|
|
45
40
|
// Resolve properties inside description
|
|
@@ -48,9 +43,15 @@ class PopupTemplate {
|
|
|
48
43
|
properties
|
|
49
44
|
)
|
|
50
45
|
properties.name = properties.name ?? feature.getDisplayName()
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
const content = Utils.greedyTemplate(template, properties)
|
|
47
|
+
return Utils.toHTML(content, { target })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
renderBody(feature) {
|
|
51
|
+
const template = feature.getOption('popupContentTemplate')
|
|
52
|
+
return Utils.loadTemplate(
|
|
53
|
+
`<div class="umap-popup-container text">${this.toHTML(feature, template)}</div>`
|
|
54
|
+
)
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
renderFooter(feature) {
|
|
@@ -92,7 +93,11 @@ class PopupTemplate {
|
|
|
92
93
|
const title = this.renderTitle(feature)
|
|
93
94
|
if (title) container.appendChild(title)
|
|
94
95
|
const body = await this.renderBody(feature)
|
|
95
|
-
if (body)
|
|
96
|
+
if (body) {
|
|
97
|
+
const div = DOMUtils.loadTemplate('<div class="umap-popup-content"></div>')
|
|
98
|
+
div.appendChild(body)
|
|
99
|
+
container.appendChild(div)
|
|
100
|
+
}
|
|
96
101
|
const footer = this.renderFooter(feature)
|
|
97
102
|
if (footer) container.appendChild(footer)
|
|
98
103
|
}
|
|
@@ -108,18 +113,9 @@ export const TitleMixin = (Base) =>
|
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
class Table extends TitleMixin(PopupTemplate) {
|
|
111
|
-
|
|
112
|
-
// TODO, manage links (url, mailto, wikipedia...)
|
|
113
|
-
const value = Utils.escapeHTML(feature.properties[key]).trim()
|
|
114
|
-
if (value.indexOf('http') === 0) {
|
|
115
|
-
return `<a href="${value}" target="_blank">${value}</a>`
|
|
116
|
-
}
|
|
117
|
-
return value
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
makeRow(feature, key) {
|
|
116
|
+
makeRow(feature, field) {
|
|
121
117
|
return Utils.loadTemplate(
|
|
122
|
-
`<tr><th>${key}</th><td>${
|
|
118
|
+
`<tr><th>${field.key}</th><td>${field.render(feature.properties[field.key])}</td></tr>`
|
|
123
119
|
)
|
|
124
120
|
}
|
|
125
121
|
|
|
@@ -130,7 +126,7 @@ class Table extends TitleMixin(PopupTemplate) {
|
|
|
130
126
|
if (U.LABEL_KEYS.includes(field.key)) {
|
|
131
127
|
continue
|
|
132
128
|
}
|
|
133
|
-
table.appendChild(this.makeRow(feature, field
|
|
129
|
+
table.appendChild(this.makeRow(feature, field))
|
|
134
130
|
}
|
|
135
131
|
return table
|
|
136
132
|
}
|
|
@@ -138,16 +134,17 @@ class Table extends TitleMixin(PopupTemplate) {
|
|
|
138
134
|
|
|
139
135
|
class GeoRSSImage extends TitleMixin(PopupTemplate) {
|
|
140
136
|
async renderBody(feature) {
|
|
141
|
-
const body =
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
const body = DOMUtils.loadTemplate(
|
|
138
|
+
`<a href="${feature.properties.link}" target="_blank"></a>`
|
|
139
|
+
)
|
|
144
140
|
if (feature.properties.img) {
|
|
145
|
-
const img = DomUtil.create('img', '', body)
|
|
146
|
-
img.src = feature.properties.img
|
|
147
141
|
// Sadly, we are unable to override this from JS the clean way
|
|
148
142
|
// See https://github.com/Leaflet/Leaflet/commit/61d746818b99d362108545c151a27f09d60960ee#commitcomment-6061847
|
|
149
|
-
|
|
150
|
-
|
|
143
|
+
body.appendChild(
|
|
144
|
+
DOMUtils.loadTemplate(
|
|
145
|
+
`<img src=${feature.properties.img} style="max-width: 500px; max-height: 500px;">`
|
|
146
|
+
)
|
|
147
|
+
)
|
|
151
148
|
}
|
|
152
149
|
return body
|
|
153
150
|
}
|
|
@@ -165,15 +162,16 @@ class GeoRSSLink extends PopupTemplate {
|
|
|
165
162
|
|
|
166
163
|
class OSM extends PopupTemplate {
|
|
167
164
|
renderTitle(feature) {
|
|
168
|
-
const title = DomUtil.add('h3', 'popup-title')
|
|
169
165
|
const color = feature.getPreviewColor()
|
|
170
|
-
title
|
|
166
|
+
const [title, { iconContainer }] = DOMUtils.loadTemplateWithRefs(`
|
|
167
|
+
<h3 class="popup-title" style="background-color: ${color};">
|
|
168
|
+
<span data-ref="iconContainer"></span> ${this.getName(feature)}
|
|
169
|
+
</h3>`)
|
|
171
170
|
const iconUrl = feature.getDynamicOption('iconUrl')
|
|
172
|
-
const icon = Icon.makeElement(iconUrl,
|
|
173
|
-
|
|
171
|
+
const icon = Icon.makeElement(iconUrl, iconContainer)
|
|
172
|
+
icon.classList.add('icon')
|
|
174
173
|
Icon.setContrast(icon, title, iconUrl, color)
|
|
175
174
|
if (DOMUtils.contrastedColor(title, color)) title.style.color = 'white'
|
|
176
|
-
DomUtil.add('span', '', title, this.getName(feature))
|
|
177
175
|
return title
|
|
178
176
|
}
|
|
179
177
|
|
|
@@ -190,15 +188,16 @@ class OSM extends PopupTemplate {
|
|
|
190
188
|
const locale = getLocale()
|
|
191
189
|
const street = props['addr:street']
|
|
192
190
|
if (street) {
|
|
193
|
-
const row = DomUtil.add('address', 'address', body)
|
|
194
191
|
const number = props['addr:housenumber']
|
|
192
|
+
let content
|
|
195
193
|
if (number) {
|
|
196
194
|
// Poor way to deal with international forms of writing addresses
|
|
197
|
-
|
|
198
|
-
DomUtil.add('span', '', row, `${translate('Street')}: ${street}`)
|
|
195
|
+
content = `<span>${translate('№')}: ${number}</span><span>${translate('Street')}: ${street}</span>`
|
|
199
196
|
} else {
|
|
200
|
-
|
|
197
|
+
content = street
|
|
201
198
|
}
|
|
199
|
+
const row = DOMUtils.loadTemplate(`<address class="address">${content}</address>`)
|
|
200
|
+
body.appendChild(row)
|
|
202
201
|
}
|
|
203
202
|
if (props.website) {
|
|
204
203
|
body.appendChild(
|
|
@@ -383,7 +382,8 @@ class Route extends TitleMixin(PopupTemplate) {
|
|
|
383
382
|
}).addTo(map)
|
|
384
383
|
})
|
|
385
384
|
if (feature.properties.description) {
|
|
386
|
-
|
|
385
|
+
const content = this.toHTML(feature, feature.properties.description)
|
|
386
|
+
root.appendChild(Utils.loadTemplate(`<p>${content}</p>`))
|
|
387
387
|
}
|
|
388
388
|
return root
|
|
389
389
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CircleMarker as BaseCircleMarker,
|
|
4
4
|
DomEvent,
|
|
5
|
-
DomUtil,
|
|
6
5
|
GeoJSON,
|
|
7
6
|
LatLng,
|
|
8
7
|
LatLngBounds,
|
|
@@ -314,7 +313,7 @@ const PathMixin = {
|
|
|
314
313
|
this.enableEdit()
|
|
315
314
|
} else {
|
|
316
315
|
this._map._umap.tooltip.open({
|
|
317
|
-
content:
|
|
316
|
+
content: translate('Please zoom in to edit the geometry'),
|
|
318
317
|
})
|
|
319
318
|
this.disableEdit()
|
|
320
319
|
}
|
|
@@ -6,6 +6,7 @@ import Orderable from './orderable.js'
|
|
|
6
6
|
import * as Utils from './utils.js'
|
|
7
7
|
import * as Icon from './rendering/icon.js'
|
|
8
8
|
import { SCHEMA } from './schema.js'
|
|
9
|
+
import { Registry as Fields } from './data/fields.js'
|
|
9
10
|
|
|
10
11
|
const EMPTY_VALUES = ['', undefined, null]
|
|
11
12
|
|
|
@@ -28,12 +29,12 @@ class Rule {
|
|
|
28
29
|
// cf https://caniuse.com/?search=public%20class%20field
|
|
29
30
|
this._condition = null
|
|
30
31
|
this.OPERATORS = [
|
|
31
|
-
['>',
|
|
32
|
-
['<',
|
|
32
|
+
['>', 'gt'],
|
|
33
|
+
['<', 'lt'],
|
|
33
34
|
// When sent by Django
|
|
34
|
-
['<',
|
|
35
|
-
['!=',
|
|
36
|
-
['=',
|
|
35
|
+
['<', 'lt'],
|
|
36
|
+
['!=', 'not_equal'],
|
|
37
|
+
['=', 'equal'],
|
|
37
38
|
]
|
|
38
39
|
this.parent = parent
|
|
39
40
|
this._umap = umap
|
|
@@ -47,58 +48,47 @@ class Rule {
|
|
|
47
48
|
this.parent.render(fields)
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
equal(other) {
|
|
51
|
-
return this.expected === other
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
not_equal(other) {
|
|
55
|
-
return this.expected !== other
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
gt(other) {
|
|
59
|
-
return other > this.expected
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
lt(other) {
|
|
63
|
-
return other < this.expected
|
|
64
|
-
}
|
|
65
|
-
|
|
66
51
|
parse() {
|
|
67
52
|
let vars = []
|
|
68
53
|
this.cast = (v) => v
|
|
69
54
|
this.operator = undefined
|
|
70
|
-
|
|
55
|
+
let operator = undefined
|
|
56
|
+
for (const [sign, funcName] of this.OPERATORS) {
|
|
71
57
|
if (this.condition.includes(sign)) {
|
|
72
|
-
|
|
58
|
+
operator = funcName
|
|
73
59
|
vars = this.condition.split(sign)
|
|
74
60
|
break
|
|
75
61
|
}
|
|
76
62
|
}
|
|
77
63
|
if (vars.length !== 2) return
|
|
78
|
-
this.
|
|
64
|
+
this.field = this.parent.fields.get(vars[0]) || new Fields.String(vars[0])
|
|
65
|
+
this.operator = this.field[operator]
|
|
79
66
|
this.expected = vars[1]
|
|
80
67
|
if (EMPTY_VALUES.includes(this.expected)) {
|
|
81
68
|
this.cast = (v) => EMPTY_VALUES.includes(v)
|
|
82
69
|
}
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
70
|
+
// TODO: deal with legacy rules on non typed fields
|
|
71
|
+
else {
|
|
72
|
+
this.cast = this.field.parse
|
|
73
|
+
if (
|
|
74
|
+
// Special cases where we want to be lousy when checking isNaN without
|
|
75
|
+
// coercing to a Number first because we handle multiple types.
|
|
76
|
+
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/
|
|
77
|
+
// Reference/Global_Objects/Number/isNaN
|
|
78
|
+
// biome-ignore lint/suspicious/noGlobalIsNan: expected might not be a number.
|
|
79
|
+
!isNaN(this.expected) &&
|
|
80
|
+
['gt', 'lt'].includes(operator) &&
|
|
81
|
+
this.field.TYPE !== 'Number'
|
|
82
|
+
) {
|
|
83
|
+
this.cast = Number.parseFloat
|
|
94
84
|
}
|
|
95
85
|
}
|
|
96
86
|
this.expected = this.cast(this.expected)
|
|
97
87
|
}
|
|
98
88
|
|
|
99
89
|
match(props) {
|
|
100
|
-
if (!this.operator || !this.active) return false
|
|
101
|
-
return this.operator(this.cast(props[this.key]))
|
|
90
|
+
if (!this.operator || !this.active || !this.field) return false
|
|
91
|
+
return this.operator(this.expected, this.cast(props[this.field.key]))
|
|
102
92
|
}
|
|
103
93
|
|
|
104
94
|
getOption(option) {
|
|
@@ -118,6 +108,7 @@ class Rule {
|
|
|
118
108
|
'name',
|
|
119
109
|
'properties.color',
|
|
120
110
|
'properties.iconClass',
|
|
111
|
+
'properties.iconSize',
|
|
121
112
|
'properties.iconUrl',
|
|
122
113
|
'properties.iconOpacity',
|
|
123
114
|
'properties.opacity',
|
|
@@ -132,7 +123,7 @@ class Rule {
|
|
|
132
123
|
const container = document.createElement('div')
|
|
133
124
|
container.appendChild(builder.build())
|
|
134
125
|
const autocomplete = new AutocompleteDatalist(builder.helpers.condition.input)
|
|
135
|
-
const properties = this.parent.
|
|
126
|
+
const properties = Array.from(this.parent.fields.keys())
|
|
136
127
|
autocomplete.suggestions = properties
|
|
137
128
|
autocomplete.input.addEventListener('input', (event) => {
|
|
138
129
|
const value = event.target.value
|
|
@@ -140,9 +131,11 @@ class Rule {
|
|
|
140
131
|
autocomplete.suggestions = [`${value}=`, `${value}!=`, `${value}>`, `${value}<`]
|
|
141
132
|
} else if (value.endsWith('=')) {
|
|
142
133
|
const key = value.split('!')[0].split('=')[0]
|
|
143
|
-
|
|
144
|
-
.
|
|
145
|
-
|
|
134
|
+
if (key) {
|
|
135
|
+
autocomplete.suggestions = this.parent
|
|
136
|
+
.sortedValues(key)
|
|
137
|
+
.map((str) => `${value}${str ?? ''}`)
|
|
138
|
+
}
|
|
146
139
|
}
|
|
147
140
|
})
|
|
148
141
|
const backButton = Utils.loadTemplate(`
|
|
@@ -123,13 +123,6 @@ export const SCHEMA = {
|
|
|
123
123
|
edit_status: {
|
|
124
124
|
type: Number,
|
|
125
125
|
},
|
|
126
|
-
editinosmControl: {
|
|
127
|
-
type: Boolean,
|
|
128
|
-
impacts: ['ui'],
|
|
129
|
-
nullable: true,
|
|
130
|
-
label: translate('Display the control to open OpenStreetMap editor'),
|
|
131
|
-
default: null,
|
|
132
|
-
},
|
|
133
126
|
editors: {
|
|
134
127
|
type: Array,
|
|
135
128
|
},
|