umap-project 2.3.1__py3-none-any.whl → 2.4.0b0__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/.DS_Store +0 -0
- umap/__init__.py +1 -1
- umap/locale/en/LC_MESSAGES/django.po +81 -31
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +109 -59
- umap/management/commands/run_websocket_server.py +23 -0
- umap/models.py +6 -1
- umap/settings/base.py +11 -3
- umap/static/.DS_Store +0 -0
- umap/static/umap/.DS_Store +0 -0
- umap/static/umap/base.css +53 -162
- umap/static/umap/content.css +3 -2
- umap/static/umap/css/dialog.css +18 -0
- umap/static/umap/css/icon.css +8 -0
- umap/static/umap/css/importers.css +44 -0
- umap/static/umap/css/panel.css +19 -57
- umap/static/umap/css/tooltip.css +59 -0
- umap/static/umap/css/window.css +35 -0
- umap/static/umap/favicons/.DS_Store +0 -0
- umap/static/umap/fonts/.DS_Store +0 -0
- umap/static/umap/img/.DS_Store +0 -0
- umap/static/umap/img/alert-icon-error.svg +8 -0
- umap/static/umap/img/alert-icon-info.svg +4 -0
- umap/static/umap/img/alert-icon-success.svg +3 -0
- umap/static/umap/img/icon-external-link.svg +3 -0
- umap/static/umap/img/importers/communesfr.svg +5 -0
- umap/static/umap/img/importers/datasets.svg +13 -0
- umap/static/umap/img/importers/geodatamine.svg +10 -0
- umap/static/umap/img/importers/overpass.svg +7 -0
- umap/static/umap/img/importers/random.svg +18 -0
- umap/static/umap/img/importers/random1.svg +4 -0
- umap/static/umap/img/importers/random2.svg +4 -0
- umap/static/umap/img/source/.DS_Store +0 -0
- umap/static/umap/js/components/alerts/alert.css +160 -0
- umap/static/umap/js/components/alerts/alert.js +169 -0
- umap/static/umap/js/components/base.js +54 -0
- umap/static/umap/js/modules/autocomplete.js +347 -0
- umap/static/umap/js/modules/browser.js +1 -1
- umap/static/umap/js/modules/caption.js +4 -3
- umap/static/umap/js/modules/global.js +36 -12
- umap/static/umap/js/modules/help.js +255 -0
- umap/static/umap/js/modules/importer.js +280 -0
- umap/static/umap/js/modules/importers/communesfr.js +44 -0
- umap/static/umap/js/modules/importers/datasets.js +41 -0
- umap/static/umap/js/modules/importers/geodatamine.js +95 -0
- umap/static/umap/js/modules/importers/overpass.js +84 -0
- umap/static/umap/js/modules/request.js +12 -14
- umap/static/umap/js/modules/rules.js +241 -0
- umap/static/umap/js/modules/schema.js +63 -14
- umap/static/umap/js/modules/sync/engine.js +93 -0
- umap/static/umap/js/modules/sync/updaters.js +109 -0
- umap/static/umap/js/modules/sync/websocket.js +25 -0
- umap/static/umap/js/modules/ui/dialog.js +52 -0
- umap/static/umap/js/modules/{panel.js → ui/panel.js} +25 -14
- umap/static/umap/js/modules/ui/tooltip.js +116 -0
- umap/static/umap/js/modules/utils.js +25 -18
- umap/static/umap/js/umap.controls.js +13 -14
- umap/static/umap/js/umap.core.js +1 -324
- umap/static/umap/js/umap.features.js +67 -27
- umap/static/umap/js/umap.forms.js +9 -13
- umap/static/umap/js/umap.js +220 -180
- umap/static/umap/js/umap.layer.js +142 -74
- umap/static/umap/js/umap.permissions.js +5 -9
- umap/static/umap/js/umap.tableeditor.js +8 -8
- umap/static/umap/locale/am_ET.js +51 -16
- umap/static/umap/locale/am_ET.json +51 -16
- umap/static/umap/locale/ar.js +51 -16
- umap/static/umap/locale/ar.json +51 -16
- umap/static/umap/locale/ast.js +51 -16
- umap/static/umap/locale/ast.json +51 -16
- umap/static/umap/locale/bg.js +51 -16
- umap/static/umap/locale/bg.json +51 -16
- umap/static/umap/locale/br.js +55 -20
- umap/static/umap/locale/br.json +55 -20
- umap/static/umap/locale/ca.js +51 -16
- umap/static/umap/locale/ca.json +51 -16
- umap/static/umap/locale/cs_CZ.js +93 -58
- umap/static/umap/locale/cs_CZ.json +93 -58
- umap/static/umap/locale/da.js +51 -16
- umap/static/umap/locale/da.json +51 -16
- umap/static/umap/locale/de.js +56 -21
- umap/static/umap/locale/de.json +56 -21
- umap/static/umap/locale/el.js +51 -16
- umap/static/umap/locale/el.json +51 -16
- umap/static/umap/locale/en.js +51 -16
- umap/static/umap/locale/en.json +51 -16
- umap/static/umap/locale/en_US.json +51 -16
- umap/static/umap/locale/es.js +51 -16
- umap/static/umap/locale/es.json +51 -16
- umap/static/umap/locale/et.js +51 -16
- umap/static/umap/locale/et.json +51 -16
- umap/static/umap/locale/eu.js +51 -16
- umap/static/umap/locale/eu.json +51 -16
- umap/static/umap/locale/fa_IR.js +51 -16
- umap/static/umap/locale/fa_IR.json +51 -16
- umap/static/umap/locale/fi.js +51 -16
- umap/static/umap/locale/fi.json +51 -16
- umap/static/umap/locale/fr.js +52 -17
- umap/static/umap/locale/fr.json +52 -17
- umap/static/umap/locale/gl.js +51 -16
- umap/static/umap/locale/gl.json +51 -16
- umap/static/umap/locale/he.js +51 -16
- umap/static/umap/locale/he.json +51 -16
- umap/static/umap/locale/hr.js +51 -16
- umap/static/umap/locale/hr.json +51 -16
- umap/static/umap/locale/hu.js +51 -16
- umap/static/umap/locale/hu.json +51 -16
- umap/static/umap/locale/id.js +51 -16
- umap/static/umap/locale/id.json +51 -16
- umap/static/umap/locale/is.js +51 -16
- umap/static/umap/locale/is.json +51 -16
- umap/static/umap/locale/it.js +51 -16
- umap/static/umap/locale/it.json +51 -16
- umap/static/umap/locale/ja.js +51 -16
- umap/static/umap/locale/ja.json +51 -16
- umap/static/umap/locale/ko.js +51 -16
- umap/static/umap/locale/ko.json +51 -16
- umap/static/umap/locale/lt.js +51 -16
- umap/static/umap/locale/lt.json +51 -16
- umap/static/umap/locale/ms.js +51 -16
- umap/static/umap/locale/ms.json +51 -16
- umap/static/umap/locale/nl.js +51 -16
- umap/static/umap/locale/nl.json +51 -16
- umap/static/umap/locale/no.js +51 -16
- umap/static/umap/locale/no.json +51 -16
- umap/static/umap/locale/pl.js +93 -58
- umap/static/umap/locale/pl.json +93 -58
- umap/static/umap/locale/pl_PL.json +51 -16
- umap/static/umap/locale/pt.js +215 -180
- umap/static/umap/locale/pt.json +215 -180
- umap/static/umap/locale/pt_BR.js +51 -16
- umap/static/umap/locale/pt_BR.json +51 -16
- umap/static/umap/locale/pt_PT.js +51 -16
- umap/static/umap/locale/pt_PT.json +51 -16
- umap/static/umap/locale/ro.js +51 -16
- umap/static/umap/locale/ro.json +51 -16
- umap/static/umap/locale/ru.js +51 -16
- umap/static/umap/locale/ru.json +51 -16
- umap/static/umap/locale/si.js +51 -16
- umap/static/umap/locale/si.json +51 -16
- umap/static/umap/locale/sk_SK.js +51 -16
- umap/static/umap/locale/sk_SK.json +51 -16
- umap/static/umap/locale/sl.js +51 -16
- umap/static/umap/locale/sl.json +51 -16
- umap/static/umap/locale/sr.js +51 -16
- umap/static/umap/locale/sr.json +51 -16
- umap/static/umap/locale/sv.js +51 -16
- umap/static/umap/locale/sv.json +51 -16
- umap/static/umap/locale/th_TH.js +51 -16
- umap/static/umap/locale/th_TH.json +51 -16
- umap/static/umap/locale/tr.js +51 -16
- umap/static/umap/locale/tr.json +51 -16
- umap/static/umap/locale/uk_UA.js +51 -16
- umap/static/umap/locale/uk_UA.json +51 -16
- umap/static/umap/locale/vi.js +51 -16
- umap/static/umap/locale/vi.json +51 -16
- umap/static/umap/locale/vi_VN.json +51 -16
- umap/static/umap/locale/zh.js +51 -16
- umap/static/umap/locale/zh.json +51 -16
- umap/static/umap/locale/zh_CN.json +51 -16
- umap/static/umap/locale/zh_TW.Big5.json +51 -16
- umap/static/umap/locale/zh_TW.js +51 -16
- umap/static/umap/locale/zh_TW.json +51 -16
- umap/static/umap/map.css +27 -41
- umap/static/umap/unittests/sync.js +105 -0
- umap/static/umap/unittests/utils.js +76 -34
- umap/static/umap/vars.css +18 -1
- umap/static/umap/vendors/dompurify/purify.es.js +5 -59
- umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
- umap/templates/umap/components/alerts/alert.html +89 -0
- umap/templates/umap/content.html +4 -3
- umap/templates/umap/css.html +4 -0
- umap/templates/umap/home.html +3 -0
- umap/templates/umap/js.html +0 -3
- umap/templates/umap/map_init.html +2 -8
- umap/templates/umap/messages.html +9 -11
- umap/templates/umap/search.html +3 -0
- umap/tests/.DS_Store +0 -0
- umap/tests/base.py +2 -0
- umap/tests/integration/.DS_Store +0 -0
- umap/tests/integration/conftest.py +30 -0
- umap/tests/integration/test_anonymous_owned_map.py +8 -13
- umap/tests/integration/test_browser.py +1 -1
- umap/tests/integration/test_conditional_rules.py +201 -0
- umap/tests/integration/test_dashboard.py +1 -1
- umap/tests/integration/test_datalayer.py +2 -3
- umap/tests/integration/test_edit_datalayer.py +4 -4
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_facets_browser.py +3 -3
- umap/tests/integration/test_import.py +138 -49
- umap/tests/integration/test_map.py +2 -2
- umap/tests/integration/{test_collaborative_editing.py → test_optimistic_merge.py} +7 -7
- umap/tests/integration/test_owned_map.py +1 -1
- umap/tests/integration/test_picto.py +2 -2
- umap/tests/integration/test_statics.py +1 -1
- umap/tests/integration/test_websocket_sync.py +283 -0
- umap/tests/settings.py +5 -0
- umap/tests/test_datalayer_views.py +0 -1
- umap/tests/test_views.py +53 -0
- umap/urls.py +5 -0
- umap/views.py +40 -11
- umap/websocket_server.py +92 -0
- {umap_project-2.3.1.dist-info → umap_project-2.4.0b0.dist-info}/METADATA +11 -9
- {umap_project-2.3.1.dist-info → umap_project-2.4.0b0.dist-info}/RECORD +207 -164
- {umap_project-2.3.1.dist-info → umap_project-2.4.0b0.dist-info}/WHEEL +1 -1
- umap/static/umap/js/umap.autocomplete.js +0 -341
- umap/static/umap/js/umap.importer.js +0 -187
- umap/static/umap/js/umap.ui.js +0 -190
- {umap_project-2.3.1.dist-info → umap_project-2.4.0b0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.3.1.dist-info → umap_project-2.4.0b0.dist-info}/licenses/LICENSE +0 -0
umap/static/umap/js/umap.js
CHANGED
|
@@ -20,9 +20,6 @@ L.Map.mergeOptions({
|
|
|
20
20
|
enablePolygonDraw: true,
|
|
21
21
|
enablePolylineDraw: true,
|
|
22
22
|
limitBounds: {},
|
|
23
|
-
importPresets: [
|
|
24
|
-
// {url: 'http://localhost:8019/en/datalayer/1502/', label: 'Simplified World Countries', format: 'geojson'}
|
|
25
|
-
],
|
|
26
23
|
slideshow: {},
|
|
27
24
|
clickable: true,
|
|
28
25
|
permissions: {},
|
|
@@ -33,6 +30,8 @@ U.Map = L.Map.extend({
|
|
|
33
30
|
includes: [ControlsMixin],
|
|
34
31
|
|
|
35
32
|
initialize: function (el, geojson) {
|
|
33
|
+
this.sync_engine = new U.SyncEngine(this)
|
|
34
|
+
this.sync = this.sync_engine.proxy(this)
|
|
36
35
|
// Locale name (pt_PT, en_US…)
|
|
37
36
|
// To be used for Django localization
|
|
38
37
|
if (geojson.properties.locale) L.setLocale(geojson.properties.locale)
|
|
@@ -57,15 +56,16 @@ U.Map = L.Map.extend({
|
|
|
57
56
|
this.urls = new U.URLs(this.options.urls)
|
|
58
57
|
|
|
59
58
|
this.panel = new U.Panel(this)
|
|
59
|
+
this.tooltip = new U.Tooltip(this._controlContainer)
|
|
60
|
+
this.dialog = new U.Dialog(this._controlContainer)
|
|
60
61
|
if (this.hasEditMode()) {
|
|
61
62
|
this.editPanel = new U.EditPanel(this)
|
|
62
63
|
this.fullPanel = new U.FullPanel(this)
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
68
|
-
this.request = new U.Request(this.ui)
|
|
65
|
+
L.DomEvent.on(document.body, 'dataloading', (e) => this.fire('dataloading', e))
|
|
66
|
+
L.DomEvent.on(document.body, 'dataload', (e) => this.fire('dataload', e))
|
|
67
|
+
this.server = new U.ServerRequest()
|
|
68
|
+
this.request = new U.Request()
|
|
69
69
|
|
|
70
70
|
this.initLoader()
|
|
71
71
|
this.name = this.options.name
|
|
@@ -205,6 +205,13 @@ U.Map = L.Map.extend({
|
|
|
205
205
|
this.editTools = new U.Editable(this)
|
|
206
206
|
this.renderEditToolbar()
|
|
207
207
|
}
|
|
208
|
+
if (!U.Utils.isObject(this.options.overlay)) {
|
|
209
|
+
this.options.overlay = {}
|
|
210
|
+
}
|
|
211
|
+
if (!U.Utils.isObject(this.options.tilelayer)) {
|
|
212
|
+
this.options.tilelayer = {}
|
|
213
|
+
}
|
|
214
|
+
|
|
208
215
|
this.initShortcuts()
|
|
209
216
|
this.onceDataLoaded(function () {
|
|
210
217
|
const slug = L.Util.queryString('feature')
|
|
@@ -248,6 +255,25 @@ U.Map = L.Map.extend({
|
|
|
248
255
|
this.on('click contextmenu.show', this.closeInplaceToolbar)
|
|
249
256
|
},
|
|
250
257
|
|
|
258
|
+
initSyncEngine: async function () {
|
|
259
|
+
if (this.options.websocketEnabled == false) return
|
|
260
|
+
if (this.options.syncEnabled != true) {
|
|
261
|
+
this.sync.stop()
|
|
262
|
+
} else {
|
|
263
|
+
const ws_token_uri = this.urls.get('map_websocket_auth_token', {
|
|
264
|
+
map_id: this.options.umap_id,
|
|
265
|
+
})
|
|
266
|
+
await this.sync.authenticate(ws_token_uri, this.options.websocketURI, this.server)
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
getSyncMetadata: function () {
|
|
271
|
+
return {
|
|
272
|
+
engine: this.sync,
|
|
273
|
+
subject: 'map',
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
|
|
251
277
|
render: function (fields) {
|
|
252
278
|
let impacts = U.Utils.getImpactsFromSchema(fields)
|
|
253
279
|
|
|
@@ -271,6 +297,8 @@ U.Map = L.Map.extend({
|
|
|
271
297
|
case 'bounds':
|
|
272
298
|
this.handleLimitBounds()
|
|
273
299
|
break
|
|
300
|
+
case 'sync':
|
|
301
|
+
this.initSyncEngine()
|
|
274
302
|
}
|
|
275
303
|
}
|
|
276
304
|
},
|
|
@@ -359,7 +387,7 @@ U.Map = L.Map.extend({
|
|
|
359
387
|
icon: 'umap-fake-class',
|
|
360
388
|
iconLoading: 'umap-fake-class',
|
|
361
389
|
flyTo: this.options.easing,
|
|
362
|
-
onLocationError: (err) =>
|
|
390
|
+
onLocationError: (err) => U.Alert.error(err.message),
|
|
363
391
|
})
|
|
364
392
|
this._controls.fullscreen = new L.Control.Fullscreen({
|
|
365
393
|
title: { false: L._('View Fullscreen'), true: L._('Exit Fullscreen') },
|
|
@@ -388,11 +416,14 @@ U.Map = L.Map.extend({
|
|
|
388
416
|
this.importer = new U.Importer(this)
|
|
389
417
|
this.drop = new U.DropControl(this)
|
|
390
418
|
this.share = new U.Share(this)
|
|
419
|
+
this.rules = new U.Rules(this)
|
|
391
420
|
this._controls.tilelayers = new U.TileLayerControl(this)
|
|
392
421
|
},
|
|
393
422
|
|
|
394
423
|
renderControls: function () {
|
|
395
|
-
const hasSlideshow = Boolean(
|
|
424
|
+
const hasSlideshow = Boolean(
|
|
425
|
+
this.options.slideshow && this.options.slideshow.active
|
|
426
|
+
)
|
|
396
427
|
const barEnabled = this.options.captionBar || hasSlideshow
|
|
397
428
|
document.body.classList.toggle('umap-caption-bar-enabled', barEnabled)
|
|
398
429
|
document.body.classList.toggle('umap-slideshow-enabled', hasSlideshow)
|
|
@@ -514,73 +545,80 @@ U.Map = L.Map.extend({
|
|
|
514
545
|
|
|
515
546
|
initShortcuts: function () {
|
|
516
547
|
const globalShortcuts = function (e) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
} else {
|
|
528
|
-
this.panel.close()
|
|
548
|
+
if (e.key === 'Escape') {
|
|
549
|
+
if (this.dialog.visible) {
|
|
550
|
+
this.dialog.close()
|
|
551
|
+
} else if (this.importer.dialog.visible) {
|
|
552
|
+
this.importer.dialog.close()
|
|
553
|
+
} else if (this.editEnabled && this.editTools.drawing()) {
|
|
554
|
+
this.editTools.stopDrawing()
|
|
555
|
+
} else if (this.measureTools.enabled()) {
|
|
556
|
+
this.measureTools.stopDrawing()
|
|
557
|
+
} else if (this.editPanel?.isOpen()) {
|
|
529
558
|
this.editPanel?.close()
|
|
559
|
+
} else if (this.fullPanel?.isOpen()) {
|
|
530
560
|
this.fullPanel?.close()
|
|
561
|
+
} else if (this.panel.isOpen()) {
|
|
562
|
+
this.panel.close()
|
|
531
563
|
}
|
|
532
564
|
}
|
|
533
565
|
|
|
534
|
-
|
|
566
|
+
// From now on, only ctrl/meta shortcut
|
|
567
|
+
if (!(e.ctrlKey || e.metaKey) || e.shiftKey) return
|
|
535
568
|
|
|
536
|
-
|
|
537
|
-
if (key === U.Keys.E && hasModifier && !this.editEnabled) {
|
|
538
|
-
L.DomEvent.stop(e)
|
|
539
|
-
this.enableEdit()
|
|
540
|
-
} else if (key === U.Keys.E && hasModifier && this.editEnabled && !this.isDirty) {
|
|
569
|
+
if (e.key === 'f') {
|
|
541
570
|
L.DomEvent.stop(e)
|
|
542
|
-
this.
|
|
571
|
+
this.search()
|
|
543
572
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
573
|
+
|
|
574
|
+
/* Edit mode only shortcuts */
|
|
575
|
+
if (!this.hasEditMode()) return
|
|
576
|
+
|
|
577
|
+
// Edit mode Off
|
|
578
|
+
if (!this.editEnabled) {
|
|
579
|
+
switch (e.key) {
|
|
580
|
+
case 'e':
|
|
581
|
+
L.DomEvent.stop(e)
|
|
582
|
+
this.enableEdit()
|
|
583
|
+
break
|
|
548
584
|
}
|
|
585
|
+
return
|
|
549
586
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
587
|
+
|
|
588
|
+
// Edit mode on
|
|
589
|
+
let used = true
|
|
590
|
+
switch (e.key) {
|
|
591
|
+
case 'e':
|
|
592
|
+
if (!this.isDirty) this.disableEdit()
|
|
593
|
+
break
|
|
594
|
+
case 's':
|
|
595
|
+
if (this.isDirty) this.save()
|
|
596
|
+
break
|
|
597
|
+
case 'z':
|
|
598
|
+
if (this.isDirty) this.askForReset()
|
|
599
|
+
break
|
|
600
|
+
case 'm':
|
|
601
|
+
this.editTools.startMarker()
|
|
602
|
+
break
|
|
603
|
+
case 'p':
|
|
604
|
+
this.editTools.startPolygon()
|
|
605
|
+
break
|
|
606
|
+
case 'l':
|
|
607
|
+
this.editTools.startPolyline()
|
|
608
|
+
break
|
|
609
|
+
case 'i':
|
|
610
|
+
this.importer.open()
|
|
611
|
+
break
|
|
612
|
+
case 'o':
|
|
613
|
+
this.importer.openFiles()
|
|
614
|
+
break
|
|
615
|
+
case 'h':
|
|
616
|
+
this.help.show('edit')
|
|
617
|
+
break
|
|
618
|
+
default:
|
|
619
|
+
used = false
|
|
583
620
|
}
|
|
621
|
+
if (used) L.DomEvent.stop(e)
|
|
584
622
|
}
|
|
585
623
|
L.DomEvent.addListener(document, 'keydown', globalShortcuts, this)
|
|
586
624
|
},
|
|
@@ -641,10 +679,7 @@ U.Map = L.Map.extend({
|
|
|
641
679
|
} catch (e) {
|
|
642
680
|
console.error(e)
|
|
643
681
|
this.removeLayer(tilelayer)
|
|
644
|
-
|
|
645
|
-
content: `${L._('Error in the tilelayer URL')}: ${tilelayer._url}`,
|
|
646
|
-
level: 'error',
|
|
647
|
-
})
|
|
682
|
+
U.Alert.error(`${L._('Error in the tilelayer URL')}: ${tilelayer._url}`)
|
|
648
683
|
// Users can put tilelayer URLs by hand, and if they add wrong {variable},
|
|
649
684
|
// Leaflet throw an error, and then the map is no more editable
|
|
650
685
|
}
|
|
@@ -676,10 +711,7 @@ U.Map = L.Map.extend({
|
|
|
676
711
|
} catch (e) {
|
|
677
712
|
this.removeLayer(overlay)
|
|
678
713
|
console.error(e)
|
|
679
|
-
|
|
680
|
-
content: `${L._('Error in the overlay URL')}: ${overlay._url}`,
|
|
681
|
-
level: 'error',
|
|
682
|
-
})
|
|
714
|
+
U.Alert.error(`${L._('Error in the overlay URL')}: ${overlay._url}`)
|
|
683
715
|
}
|
|
684
716
|
},
|
|
685
717
|
|
|
@@ -770,11 +802,14 @@ U.Map = L.Map.extend({
|
|
|
770
802
|
return L.Map.prototype.setMaxBounds.call(this, bounds)
|
|
771
803
|
},
|
|
772
804
|
|
|
773
|
-
createDataLayer: function (
|
|
774
|
-
|
|
775
|
-
|
|
805
|
+
createDataLayer: function (options = {}, sync) {
|
|
806
|
+
options.name = options.name || `${L._('Layer')} ${this.datalayers_index.length + 1}`
|
|
807
|
+
const datalayer = new U.DataLayer(this, options, sync)
|
|
808
|
+
|
|
809
|
+
if (sync !== false) {
|
|
810
|
+
datalayer.sync.upsert(datalayer.options)
|
|
776
811
|
}
|
|
777
|
-
return
|
|
812
|
+
return datalayer
|
|
778
813
|
},
|
|
779
814
|
|
|
780
815
|
newDataLayer: function () {
|
|
@@ -786,24 +821,25 @@ U.Map = L.Map.extend({
|
|
|
786
821
|
return U.SCHEMA[option] && U.SCHEMA[option].default
|
|
787
822
|
},
|
|
788
823
|
|
|
789
|
-
getOption: function (option) {
|
|
824
|
+
getOption: function (option, feature) {
|
|
825
|
+
if (feature) {
|
|
826
|
+
const value = this.rules.getOption(option, feature)
|
|
827
|
+
if (value !== undefined) return value
|
|
828
|
+
}
|
|
790
829
|
if (U.Utils.usableOption(this.options, option)) return this.options[option]
|
|
791
830
|
return this.getDefaultOption(option)
|
|
792
831
|
},
|
|
793
832
|
|
|
794
|
-
|
|
833
|
+
setCenterAndZoom: function () {
|
|
834
|
+
this._setCenterAndZoom()
|
|
835
|
+
U.Alert.success(L._('The zoom and center have been modified.'))
|
|
836
|
+
},
|
|
837
|
+
|
|
838
|
+
_setCenterAndZoom: function () {
|
|
795
839
|
this.options.center = this.getCenter()
|
|
796
840
|
this.options.zoom = this.getZoom()
|
|
797
841
|
this.isDirty = true
|
|
798
842
|
this._default_extent = false
|
|
799
|
-
if (this.options.umap_id) {
|
|
800
|
-
// We do not want an extra message during the map creation
|
|
801
|
-
// to avoid the double notification/alert.
|
|
802
|
-
this.ui.alert({
|
|
803
|
-
content: L._('The zoom and center have been modified.'),
|
|
804
|
-
level: 'info',
|
|
805
|
-
})
|
|
806
|
-
}
|
|
807
843
|
},
|
|
808
844
|
|
|
809
845
|
updateTileLayers: function () {
|
|
@@ -842,12 +878,11 @@ U.Map = L.Map.extend({
|
|
|
842
878
|
processFileToImport: function (file, layer, type) {
|
|
843
879
|
type = type || U.Utils.detectFileType(file)
|
|
844
880
|
if (!type) {
|
|
845
|
-
|
|
846
|
-
|
|
881
|
+
U.Alert.error(
|
|
882
|
+
L._('Unable to detect format of file {filename}', {
|
|
847
883
|
filename: file.name,
|
|
848
|
-
})
|
|
849
|
-
|
|
850
|
-
})
|
|
884
|
+
})
|
|
885
|
+
)
|
|
851
886
|
return
|
|
852
887
|
}
|
|
853
888
|
if (type === 'umap') {
|
|
@@ -858,6 +893,13 @@ U.Map = L.Map.extend({
|
|
|
858
893
|
}
|
|
859
894
|
},
|
|
860
895
|
|
|
896
|
+
importFromUrl: async function (uri) {
|
|
897
|
+
const response = await this.request.get(uri)
|
|
898
|
+
if (response && response.ok) {
|
|
899
|
+
this.importRaw(await response.text())
|
|
900
|
+
}
|
|
901
|
+
},
|
|
902
|
+
|
|
861
903
|
importRaw: function (rawData) {
|
|
862
904
|
const importedData = JSON.parse(rawData)
|
|
863
905
|
|
|
@@ -873,7 +915,11 @@ U.Map = L.Map.extend({
|
|
|
873
915
|
if (importedData.geometry) this.options.center = this.latLng(importedData.geometry)
|
|
874
916
|
const self = this
|
|
875
917
|
importedData.layers.forEach((geojson) => {
|
|
876
|
-
|
|
918
|
+
if (!geojson._umap_options && geojson._storage) {
|
|
919
|
+
geojson._umap_options = geojson._storage
|
|
920
|
+
delete geojson._storage
|
|
921
|
+
}
|
|
922
|
+
delete geojson._umap_options?.id // Never trust an id at this stage
|
|
877
923
|
const dataLayer = self.createDataLayer(geojson._umap_options)
|
|
878
924
|
dataLayer.fromUmapGeoJSON(geojson)
|
|
879
925
|
})
|
|
@@ -899,10 +945,7 @@ U.Map = L.Map.extend({
|
|
|
899
945
|
self.importRaw(rawData)
|
|
900
946
|
} catch (e) {
|
|
901
947
|
console.error('Error importing data', e)
|
|
902
|
-
|
|
903
|
-
content: L._('Invalid umap data in {filename}', { filename: file.name }),
|
|
904
|
-
level: 'error',
|
|
905
|
-
})
|
|
948
|
+
U.Alert.error(L._('Invalid umap data in {filename}', { filename: file.name }))
|
|
906
949
|
}
|
|
907
950
|
}
|
|
908
951
|
},
|
|
@@ -997,6 +1040,7 @@ U.Map = L.Map.extend({
|
|
|
997
1040
|
},
|
|
998
1041
|
|
|
999
1042
|
saveSelf: async function () {
|
|
1043
|
+
this.rules.commit()
|
|
1000
1044
|
const geojson = {
|
|
1001
1045
|
type: 'Feature',
|
|
1002
1046
|
geometry: this.geometry(),
|
|
@@ -1007,65 +1051,56 @@ U.Map = L.Map.extend({
|
|
|
1007
1051
|
formData.append('center', JSON.stringify(this.geometry()))
|
|
1008
1052
|
formData.append('settings', JSON.stringify(geojson))
|
|
1009
1053
|
const uri = this.urls.get('map_save', { map_id: this.options.umap_id })
|
|
1010
|
-
const [data,
|
|
1054
|
+
const [data, _, error] = await this.server.post(uri, {}, formData)
|
|
1011
1055
|
// FIXME: login_required response will not be an error, so it will not
|
|
1012
1056
|
// stop code while it should
|
|
1013
|
-
if (
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
L._(
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
},
|
|
1040
|
-
]
|
|
1041
|
-
if (this.options.urls.map_send_edit_link) {
|
|
1042
|
-
alert.actions.push({
|
|
1043
|
-
label: L._('Send me the link'),
|
|
1044
|
-
input: L._('Email'),
|
|
1045
|
-
callback: this.sendEditLink,
|
|
1046
|
-
callbackContext: this,
|
|
1047
|
-
})
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
} else if (!this.permissions.isDirty) {
|
|
1057
|
+
if (error) {
|
|
1058
|
+
return
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
if (!this.options.umap_id) {
|
|
1062
|
+
this.options.umap_id = data.id
|
|
1063
|
+
this.permissions.setOptions(data.permissions)
|
|
1064
|
+
this.permissions.commit()
|
|
1065
|
+
if (data?.permissions?.anonymous_edit_url) {
|
|
1066
|
+
this.once('saved', () => {
|
|
1067
|
+
U.AlertCreation.info(
|
|
1068
|
+
L._('Your map has been created with an anonymous account!'),
|
|
1069
|
+
Number.Infinity,
|
|
1070
|
+
data.permissions.anonymous_edit_url,
|
|
1071
|
+
this.options.urls.map_send_edit_link
|
|
1072
|
+
? this.sendEditLinkEmail.bind(this)
|
|
1073
|
+
: null
|
|
1074
|
+
)
|
|
1075
|
+
})
|
|
1076
|
+
} else {
|
|
1077
|
+
this.once('saved', () => {
|
|
1078
|
+
U.Alert.success(L._('Congratulations, your map has been created!'))
|
|
1079
|
+
})
|
|
1080
|
+
}
|
|
1081
|
+
} else {
|
|
1082
|
+
if (!this.permissions.isDirty) {
|
|
1051
1083
|
// Do not override local changes to permissions,
|
|
1052
1084
|
// but update in case some other editors changed them in the meantime.
|
|
1053
1085
|
this.permissions.setOptions(data.permissions)
|
|
1054
1086
|
this.permissions.commit()
|
|
1055
1087
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
this.
|
|
1088
|
+
this.once('saved', () => {
|
|
1089
|
+
U.Alert.success(data.info || L._('Map has been saved!'))
|
|
1090
|
+
})
|
|
1091
|
+
}
|
|
1092
|
+
// Update URL in case the name has changed.
|
|
1093
|
+
if (history?.pushState) {
|
|
1094
|
+
history.pushState({}, this.options.name, data.url)
|
|
1095
|
+
} else {
|
|
1096
|
+
window.location = data.url
|
|
1063
1097
|
}
|
|
1098
|
+
this.permissions.save()
|
|
1064
1099
|
},
|
|
1065
1100
|
|
|
1066
1101
|
save: function () {
|
|
1067
1102
|
if (!this.isDirty) return
|
|
1068
|
-
if (this._default_extent) this.
|
|
1103
|
+
if (this._default_extent) this._setCenterAndZoom()
|
|
1069
1104
|
this.backup()
|
|
1070
1105
|
this.once('saved', () => {
|
|
1071
1106
|
this.isDirty = false
|
|
@@ -1078,33 +1113,20 @@ U.Map = L.Map.extend({
|
|
|
1078
1113
|
}
|
|
1079
1114
|
},
|
|
1080
1115
|
|
|
1081
|
-
sendEditLink: async function () {
|
|
1082
|
-
const input = this.ui._alert.querySelector('input')
|
|
1083
|
-
const email = input.value
|
|
1084
|
-
|
|
1085
|
-
const formData = new FormData()
|
|
1086
|
-
formData.append('email', email)
|
|
1087
|
-
|
|
1088
|
-
const url = this.urls.get('map_send_edit_link', { map_id: this.options.umap_id })
|
|
1089
|
-
await this.server.post(url, {}, formData)
|
|
1090
|
-
},
|
|
1091
|
-
|
|
1092
1116
|
star: async function () {
|
|
1093
|
-
if (!this.options.umap_id)
|
|
1094
|
-
return
|
|
1095
|
-
|
|
1096
|
-
level: 'error',
|
|
1097
|
-
})
|
|
1117
|
+
if (!this.options.umap_id) {
|
|
1118
|
+
return U.Alert.error(L._('Please save the map first'))
|
|
1119
|
+
}
|
|
1098
1120
|
const url = this.urls.get('map_star', { map_id: this.options.umap_id })
|
|
1099
1121
|
const [data, response, error] = await this.server.post(url)
|
|
1100
|
-
if (
|
|
1101
|
-
|
|
1102
|
-
let msg = data.starred
|
|
1103
|
-
? L._('Map has been starred')
|
|
1104
|
-
: L._('Map has been unstarred')
|
|
1105
|
-
this.ui.alert({ content: msg, level: 'info' })
|
|
1106
|
-
this.renderControls()
|
|
1122
|
+
if (error) {
|
|
1123
|
+
return
|
|
1107
1124
|
}
|
|
1125
|
+
this.options.starred = data.starred
|
|
1126
|
+
U.Alert.success(
|
|
1127
|
+
data.starred ? L._('Map has been starred') : L._('Map has been unstarred')
|
|
1128
|
+
)
|
|
1129
|
+
this.renderControls()
|
|
1108
1130
|
},
|
|
1109
1131
|
|
|
1110
1132
|
geometry: function () {
|
|
@@ -1274,9 +1296,6 @@ U.Map = L.Map.extend({
|
|
|
1274
1296
|
},
|
|
1275
1297
|
|
|
1276
1298
|
_editTilelayer: function (container) {
|
|
1277
|
-
if (!U.Utils.isObject(this.options.tilelayer)) {
|
|
1278
|
-
this.options.tilelayer = {}
|
|
1279
|
-
}
|
|
1280
1299
|
const tilelayerFields = [
|
|
1281
1300
|
[
|
|
1282
1301
|
'options.tilelayer.name',
|
|
@@ -1324,9 +1343,6 @@ U.Map = L.Map.extend({
|
|
|
1324
1343
|
},
|
|
1325
1344
|
|
|
1326
1345
|
_editOverlay: function (container) {
|
|
1327
|
-
if (!U.Utils.isObject(this.options.overlay)) {
|
|
1328
|
-
this.options.overlay = {}
|
|
1329
|
-
}
|
|
1330
1346
|
const overlayFields = [
|
|
1331
1347
|
[
|
|
1332
1348
|
'options.overlay.url_template',
|
|
@@ -1408,6 +1424,8 @@ U.Map = L.Map.extend({
|
|
|
1408
1424
|
this.options.limitBounds.north = L.Util.formatNum(bounds.getNorth())
|
|
1409
1425
|
this.options.limitBounds.east = L.Util.formatNum(bounds.getEast())
|
|
1410
1426
|
boundsBuilder.fetchAll()
|
|
1427
|
+
|
|
1428
|
+
this.sync.update(this, 'options.limitBounds', this.options.limitBounds)
|
|
1411
1429
|
this.isDirty = true
|
|
1412
1430
|
this.handleLimitBounds()
|
|
1413
1431
|
},
|
|
@@ -1463,6 +1481,12 @@ U.Map = L.Map.extend({
|
|
|
1463
1481
|
slideshow.appendChild(slideshowBuilder.build())
|
|
1464
1482
|
},
|
|
1465
1483
|
|
|
1484
|
+
_editSync: function (container) {
|
|
1485
|
+
const sync = L.DomUtil.createFieldset(container, L._('Real-time collaboration'))
|
|
1486
|
+
const builder = new U.FormBuilder(this, ['options.syncEnabled'])
|
|
1487
|
+
sync.appendChild(builder.build())
|
|
1488
|
+
},
|
|
1489
|
+
|
|
1466
1490
|
_advancedActions: function (container) {
|
|
1467
1491
|
const advancedActions = L.DomUtil.createFieldset(container, L._('Advanced actions'))
|
|
1468
1492
|
const advancedButtons = L.DomUtil.create('div', 'button-bar half', advancedActions)
|
|
@@ -1508,9 +1532,10 @@ U.Map = L.Map.extend({
|
|
|
1508
1532
|
editCaption: function () {
|
|
1509
1533
|
if (!this.editEnabled) return
|
|
1510
1534
|
if (this.options.editMode !== 'advanced') return
|
|
1511
|
-
const container = L.DomUtil.create('div', 'umap-edit-container')
|
|
1512
|
-
|
|
1513
|
-
|
|
1535
|
+
const container = L.DomUtil.create('div', 'umap-edit-container')
|
|
1536
|
+
const metadataFields = ['options.name', 'options.description']
|
|
1537
|
+
|
|
1538
|
+
const title = L.DomUtil.create('h3', '', container)
|
|
1514
1539
|
title.textContent = L._('Edit map details')
|
|
1515
1540
|
const builder = new U.FormBuilder(this, metadataFields, {
|
|
1516
1541
|
className: 'map-metadata',
|
|
@@ -1540,10 +1565,14 @@ U.Map = L.Map.extend({
|
|
|
1540
1565
|
this._editShapeProperties(container)
|
|
1541
1566
|
this._editDefaultProperties(container)
|
|
1542
1567
|
this._editInteractionsProperties(container)
|
|
1568
|
+
this.rules.edit(container)
|
|
1543
1569
|
this._editTilelayer(container)
|
|
1544
1570
|
this._editOverlay(container)
|
|
1545
1571
|
this._editBounds(container)
|
|
1546
1572
|
this._editSlideshow(container)
|
|
1573
|
+
if (this.options.websocketEnabled) {
|
|
1574
|
+
this._editSync(container)
|
|
1575
|
+
}
|
|
1547
1576
|
this._advancedActions(container)
|
|
1548
1577
|
|
|
1549
1578
|
this.editPanel.open({ content: container, className: 'dark' })
|
|
@@ -1554,6 +1583,7 @@ U.Map = L.Map.extend({
|
|
|
1554
1583
|
this.editEnabled = true
|
|
1555
1584
|
this.drop.enable()
|
|
1556
1585
|
this.fire('edit:enabled')
|
|
1586
|
+
this.initSyncEngine()
|
|
1557
1587
|
},
|
|
1558
1588
|
|
|
1559
1589
|
disableEdit: function () {
|
|
@@ -1565,6 +1595,7 @@ U.Map = L.Map.extend({
|
|
|
1565
1595
|
this.fire('edit:disabled')
|
|
1566
1596
|
this.editPanel.close()
|
|
1567
1597
|
this.fullPanel.close()
|
|
1598
|
+
this.sync.stop()
|
|
1568
1599
|
},
|
|
1569
1600
|
|
|
1570
1601
|
hasEditMode: function () {
|
|
@@ -1588,7 +1619,7 @@ U.Map = L.Map.extend({
|
|
|
1588
1619
|
L.DomUtil.createButton(
|
|
1589
1620
|
'umap-about-link flat',
|
|
1590
1621
|
container,
|
|
1591
|
-
L._('
|
|
1622
|
+
L._('Open caption'),
|
|
1592
1623
|
this.openCaption,
|
|
1593
1624
|
this
|
|
1594
1625
|
)
|
|
@@ -1739,7 +1770,7 @@ U.Map = L.Map.extend({
|
|
|
1739
1770
|
items.push(
|
|
1740
1771
|
'-',
|
|
1741
1772
|
{
|
|
1742
|
-
text: L._('
|
|
1773
|
+
text: L._('Open browser'),
|
|
1743
1774
|
callback: () => this.openBrowser('layers'),
|
|
1744
1775
|
},
|
|
1745
1776
|
{
|
|
@@ -1755,7 +1786,7 @@ U.Map = L.Map.extend({
|
|
|
1755
1786
|
}
|
|
1756
1787
|
items.push(
|
|
1757
1788
|
{
|
|
1758
|
-
text: L._('
|
|
1789
|
+
text: L._('Open caption'),
|
|
1759
1790
|
callback: this.openCaption,
|
|
1760
1791
|
},
|
|
1761
1792
|
{
|
|
@@ -1853,4 +1884,13 @@ U.Map = L.Map.extend({
|
|
|
1853
1884
|
})
|
|
1854
1885
|
return bounds
|
|
1855
1886
|
},
|
|
1887
|
+
|
|
1888
|
+
sendEditLinkEmail: async function (formData) {
|
|
1889
|
+
const sendLink =
|
|
1890
|
+
this.options.urls.map_send_edit_link &&
|
|
1891
|
+
this.urls.get('map_send_edit_link', {
|
|
1892
|
+
map_id: this.options.umap_id,
|
|
1893
|
+
})
|
|
1894
|
+
await this.server.post(sendLink, {}, formData)
|
|
1895
|
+
},
|
|
1856
1896
|
})
|