umap-project 2.8.0__py3-none-any.whl → 2.8.0a0__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/en/LC_MESSAGES/django.po +13 -13
- umap/management/commands/empty_trash.py +2 -5
- umap/management/commands/migrate_to_S3.py +3 -3
- umap/settings/base.py +2 -2
- umap/static/umap/css/form.css +0 -3
- umap/static/umap/js/modules/data/features.js +4 -19
- umap/static/umap/js/modules/data/layer.js +19 -41
- umap/static/umap/js/modules/importer.js +20 -65
- umap/static/umap/js/modules/rendering/icon.js +1 -2
- umap/static/umap/js/modules/rendering/map.js +7 -7
- umap/static/umap/js/modules/rendering/popup.js +10 -9
- umap/static/umap/js/modules/rendering/template.js +9 -53
- umap/static/umap/js/modules/rendering/ui.js +2 -6
- umap/static/umap/js/modules/request.js +2 -2
- umap/static/umap/js/modules/schema.js +0 -1
- umap/static/umap/js/modules/ui/dialog.js +0 -5
- umap/static/umap/js/modules/umap.js +10 -33
- umap/static/umap/js/modules/utils.js +0 -2
- umap/static/umap/js/umap.controls.js +4 -7
- umap/static/umap/js/umap.forms.js +0 -44
- umap/static/umap/locale/en.js +1 -3
- umap/static/umap/locale/en.json +1 -3
- umap/static/umap/locale/fr.js +1 -3
- umap/static/umap/locale/fr.json +1 -3
- umap/static/umap/map.css +166 -34
- umap/static/umap/vars.css +1 -0
- umap/storage.py +216 -0
- umap/templates/base.html +0 -2
- umap/templates/umap/components/alerts/alert.html +0 -4
- umap/templates/umap/css.html +0 -3
- umap/templates/umap/js.html +0 -2
- umap/templates/umap/map_init.html +0 -2
- umap/templates/umap/user_dashboard.html +0 -2
- umap/tests/integration/test_edit_datalayer.py +0 -11
- umap/tests/integration/test_import.py +1 -20
- umap/tests/test_datalayer_s3.py +1 -1
- umap/tests/test_statics.py +1 -1
- umap/tests/test_team_views.py +1 -35
- umap/tests/test_views.py +74 -0
- umap/views.py +15 -20
- {umap_project-2.8.0.dist-info → umap_project-2.8.0a0.dist-info}/METADATA +1 -1
- {umap_project-2.8.0.dist-info → umap_project-2.8.0a0.dist-info}/RECORD +46 -52
- umap/settings/local_s3.py +0 -45
- umap/storage/__init__.py +0 -3
- umap/storage/fs.py +0 -101
- umap/storage/s3.py +0 -61
- umap/storage/staticfiles.py +0 -64
- umap/tests/fixtures/test_upload_simple_marker.json +0 -19
- umap/tests/test_dashboard.py +0 -82
- {umap_project-2.8.0.dist-info → umap_project-2.8.0a0.dist-info}/WHEEL +0 -0
- {umap_project-2.8.0.dist-info → umap_project-2.8.0a0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.8.0.dist-info → umap_project-2.8.0a0.dist-info}/licenses/LICENSE +0 -0
umap/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
VERSION = "2.8.
|
|
1
|
+
VERSION = "2.8.0a0"
|
|
@@ -8,7 +8,7 @@ msgid ""
|
|
|
8
8
|
msgstr ""
|
|
9
9
|
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
10
|
"Report-Msgid-Bugs-To: \n"
|
|
11
|
-
"POT-Creation-Date: 2024-12-
|
|
11
|
+
"POT-Creation-Date: 2024-12-11 17:05+0000\n"
|
|
12
12
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
13
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
14
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
@@ -617,57 +617,57 @@ msgstr ""
|
|
|
617
617
|
msgid "View the map"
|
|
618
618
|
msgstr ""
|
|
619
619
|
|
|
620
|
-
#: views.py:
|
|
620
|
+
#: views.py:820
|
|
621
621
|
msgid "See full screen"
|
|
622
622
|
msgstr ""
|
|
623
623
|
|
|
624
|
-
#: views.py:
|
|
624
|
+
#: views.py:963
|
|
625
625
|
msgid "Map editors updated with success!"
|
|
626
626
|
msgstr ""
|
|
627
627
|
|
|
628
|
-
#: views.py:
|
|
628
|
+
#: views.py:999
|
|
629
629
|
#, python-format
|
|
630
630
|
msgid "The uMap edit link for your map: %(map_name)s"
|
|
631
631
|
msgstr ""
|
|
632
632
|
|
|
633
|
-
#: views.py:
|
|
633
|
+
#: views.py:1002
|
|
634
634
|
#, python-format
|
|
635
635
|
msgid "Here is your secret edit link: %(link)s"
|
|
636
636
|
msgstr ""
|
|
637
637
|
|
|
638
|
-
#: views.py:
|
|
638
|
+
#: views.py:1009
|
|
639
639
|
#, python-format
|
|
640
640
|
msgid "Can't send email to %(email)s"
|
|
641
641
|
msgstr ""
|
|
642
642
|
|
|
643
|
-
#: views.py:
|
|
643
|
+
#: views.py:1012
|
|
644
644
|
#, python-format
|
|
645
645
|
msgid "Email sent to %(email)s"
|
|
646
646
|
msgstr ""
|
|
647
647
|
|
|
648
|
-
#: views.py:
|
|
648
|
+
#: views.py:1023
|
|
649
649
|
msgid "Only its owner can delete the map."
|
|
650
650
|
msgstr ""
|
|
651
651
|
|
|
652
|
-
#: views.py:
|
|
652
|
+
#: views.py:1026
|
|
653
653
|
msgid "Map successfully deleted."
|
|
654
654
|
msgstr ""
|
|
655
655
|
|
|
656
|
-
#: views.py:
|
|
656
|
+
#: views.py:1052
|
|
657
657
|
#, python-format
|
|
658
658
|
msgid ""
|
|
659
659
|
"Your map has been cloned! If you want to edit this map from another "
|
|
660
660
|
"computer, please use this link: %(anonymous_url)s"
|
|
661
661
|
msgstr ""
|
|
662
662
|
|
|
663
|
-
#: views.py:
|
|
663
|
+
#: views.py:1057
|
|
664
664
|
msgid "Congratulations, your map has been cloned!"
|
|
665
665
|
msgstr ""
|
|
666
666
|
|
|
667
|
-
#: views.py:
|
|
667
|
+
#: views.py:1308
|
|
668
668
|
msgid "Layer successfully deleted."
|
|
669
669
|
msgstr ""
|
|
670
670
|
|
|
671
|
-
#: views.py:
|
|
671
|
+
#: views.py:1330
|
|
672
672
|
msgid "Permissions updated with success!"
|
|
673
673
|
msgstr ""
|
|
@@ -23,13 +23,10 @@ class Command(BaseCommand):
|
|
|
23
23
|
|
|
24
24
|
def handle(self, *args, **options):
|
|
25
25
|
days = options["days"]
|
|
26
|
-
since =
|
|
26
|
+
since = datetime.utcnow() - timedelta(days=days)
|
|
27
27
|
print(f"Deleting map in trash since {since}")
|
|
28
28
|
maps = Map.objects.filter(share_status=Map.DELETED, modified_at__lt=since)
|
|
29
29
|
for map in maps:
|
|
30
|
-
map_id = map.id
|
|
31
|
-
map_name = map.name
|
|
32
|
-
trashed_at = map.modified_at.date()
|
|
33
30
|
if not options["dry_run"]:
|
|
34
31
|
map.delete()
|
|
35
|
-
print(f"Deleted map {
|
|
32
|
+
print(f"Deleted map {map.name} ({map.id}), trashed on {map.modified_at}")
|
|
@@ -2,7 +2,7 @@ from django.conf import settings
|
|
|
2
2
|
from django.core.management.base import BaseCommand
|
|
3
3
|
|
|
4
4
|
from umap.models import DataLayer
|
|
5
|
-
from umap.storage
|
|
5
|
+
from umap.storage import UmapFileSystem
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Command(BaseCommand):
|
|
@@ -11,9 +11,9 @@ class Command(BaseCommand):
|
|
|
11
11
|
def handle(self, *args, **options):
|
|
12
12
|
assert settings.UMAP_READONLY, "You must run that script with a read-only uMap."
|
|
13
13
|
assert (
|
|
14
|
-
settings.STORAGES["data"]["BACKEND"] == "umap.storage.
|
|
14
|
+
settings.STORAGES["data"]["BACKEND"] == "umap.storage.UmapS3"
|
|
15
15
|
), "You must configure your storages to point to S3"
|
|
16
|
-
fs_storage =
|
|
16
|
+
fs_storage = UmapFileSystem()
|
|
17
17
|
for datalayer in DataLayer.objects.all():
|
|
18
18
|
geojson_fs_path = str(datalayer.geojson)
|
|
19
19
|
try:
|
umap/settings/base.py
CHANGED
|
@@ -176,10 +176,10 @@ STORAGES = {
|
|
|
176
176
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
177
177
|
},
|
|
178
178
|
"data": {
|
|
179
|
-
"BACKEND": "umap.storage.
|
|
179
|
+
"BACKEND": "umap.storage.UmapFileSystem",
|
|
180
180
|
},
|
|
181
181
|
"staticfiles": {
|
|
182
|
-
"BACKEND": "umap.storage.
|
|
182
|
+
"BACKEND": "umap.storage.UmapManifestStaticFilesStorage",
|
|
183
183
|
},
|
|
184
184
|
}
|
|
185
185
|
# Add application/json and application/geo+json to default django-storages setting
|
umap/static/umap/css/form.css
CHANGED
|
@@ -199,9 +199,8 @@ class Feature {
|
|
|
199
199
|
this._umap.slideshow.current = this
|
|
200
200
|
}
|
|
201
201
|
this._umap.currentFeature = this
|
|
202
|
-
this.attachPopup()
|
|
203
|
-
|
|
204
|
-
})
|
|
202
|
+
this.attachPopup()
|
|
203
|
+
this.ui.openPopup(latlng || this.center)
|
|
205
204
|
}
|
|
206
205
|
|
|
207
206
|
render(fields) {
|
|
@@ -356,11 +355,9 @@ class Feature {
|
|
|
356
355
|
return loadPopup(this.getOption('popupShape') || old)
|
|
357
356
|
}
|
|
358
357
|
|
|
359
|
-
|
|
358
|
+
attachPopup() {
|
|
360
359
|
const Class = this.getPopupClass()
|
|
361
|
-
|
|
362
|
-
this.ui.bindPopup(popup)
|
|
363
|
-
return popup.loadContent()
|
|
360
|
+
this.ui.bindPopup(new Class(this))
|
|
364
361
|
}
|
|
365
362
|
|
|
366
363
|
async confirmDelete() {
|
|
@@ -661,18 +658,6 @@ class Feature {
|
|
|
661
658
|
)
|
|
662
659
|
return items
|
|
663
660
|
}
|
|
664
|
-
|
|
665
|
-
isActive() {
|
|
666
|
-
return this._umap.activeFeature === this
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
activate() {
|
|
670
|
-
this._umap.activeFeature = this
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
deactivate() {
|
|
674
|
-
if (this._umap.activeFeature === this) this._umap.activeFeature = undefined
|
|
675
|
-
}
|
|
676
661
|
}
|
|
677
662
|
|
|
678
663
|
export class Point extends Feature {
|
|
@@ -252,11 +252,10 @@ export class DataLayer extends ServerStored {
|
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
fromGeoJSON(geojson, sync = true) {
|
|
255
|
-
|
|
255
|
+
this.addData(geojson, sync)
|
|
256
256
|
this._geojson = geojson
|
|
257
257
|
this.onDataLoaded()
|
|
258
258
|
this.dataChanged()
|
|
259
|
-
return features
|
|
260
259
|
}
|
|
261
260
|
|
|
262
261
|
onDataLoaded() {
|
|
@@ -316,7 +315,7 @@ export class DataLayer extends ServerStored {
|
|
|
316
315
|
const response = await this._umap.request.get(url)
|
|
317
316
|
if (response?.ok) {
|
|
318
317
|
this.clear()
|
|
319
|
-
|
|
318
|
+
this._umap.formatter
|
|
320
319
|
.parse(await response.text(), this.options.remoteData.format)
|
|
321
320
|
.then((geojson) => this.fromGeoJSON(geojson))
|
|
322
321
|
}
|
|
@@ -444,11 +443,10 @@ export class DataLayer extends ServerStored {
|
|
|
444
443
|
try {
|
|
445
444
|
// Do not fail if remote data is somehow invalid,
|
|
446
445
|
// otherwise the layer becomes uneditable.
|
|
447
|
-
|
|
446
|
+
this.makeFeatures(geojson, sync)
|
|
448
447
|
} catch (err) {
|
|
449
448
|
console.log('Error with DataLayer', this.id)
|
|
450
449
|
console.error(err)
|
|
451
|
-
return []
|
|
452
450
|
}
|
|
453
451
|
}
|
|
454
452
|
|
|
@@ -465,13 +463,10 @@ export class DataLayer extends ServerStored {
|
|
|
465
463
|
? geojson
|
|
466
464
|
: geojson.features || geojson.geometries
|
|
467
465
|
if (!collection) return
|
|
468
|
-
const features = []
|
|
469
466
|
this.sortFeatures(collection)
|
|
470
|
-
for (const
|
|
471
|
-
|
|
472
|
-
if (feature) features.push(feature)
|
|
467
|
+
for (const feature of collection) {
|
|
468
|
+
this.makeFeature(feature, sync)
|
|
473
469
|
}
|
|
474
|
-
return features
|
|
475
470
|
}
|
|
476
471
|
|
|
477
472
|
makeFeature(geojson = {}, sync = true, id = null) {
|
|
@@ -508,45 +503,31 @@ export class DataLayer extends ServerStored {
|
|
|
508
503
|
}
|
|
509
504
|
|
|
510
505
|
async importRaw(raw, format) {
|
|
511
|
-
|
|
506
|
+
this._umap.formatter
|
|
512
507
|
.parse(raw, format)
|
|
513
508
|
.then((geojson) => this.addData(geojson))
|
|
514
|
-
.then((
|
|
515
|
-
|
|
516
|
-
return data
|
|
517
|
-
})
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
readFile(f) {
|
|
521
|
-
return new Promise((resolve) => {
|
|
522
|
-
const reader = new FileReader()
|
|
523
|
-
reader.onloadend = () => resolve(reader.result)
|
|
524
|
-
reader.readAsText(f)
|
|
525
|
-
})
|
|
509
|
+
.then(() => this.zoomTo())
|
|
510
|
+
this.isDirty = true
|
|
526
511
|
}
|
|
527
512
|
|
|
528
|
-
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
toLoad.push(this.importFromFile(file, type))
|
|
513
|
+
importFromFiles(files, type) {
|
|
514
|
+
for (const f of files) {
|
|
515
|
+
this.importFromFile(f, type)
|
|
532
516
|
}
|
|
533
|
-
const features = await Promise.all(toLoad)
|
|
534
|
-
return new Promise((resolve) => {
|
|
535
|
-
resolve([].concat(...features))
|
|
536
|
-
})
|
|
537
517
|
}
|
|
538
518
|
|
|
539
|
-
|
|
519
|
+
importFromFile(f, type) {
|
|
520
|
+
const reader = new FileReader()
|
|
540
521
|
type = type || Utils.detectFileType(f)
|
|
541
|
-
|
|
542
|
-
|
|
522
|
+
reader.readAsText(f)
|
|
523
|
+
reader.onload = (e) => this.importRaw(e.target.result, type)
|
|
543
524
|
}
|
|
544
525
|
|
|
545
526
|
async importFromUrl(uri, type) {
|
|
546
527
|
uri = this._umap.renderUrl(uri)
|
|
547
528
|
const response = await this._umap.request.get(uri)
|
|
548
529
|
if (response?.ok) {
|
|
549
|
-
|
|
530
|
+
this.importRaw(await response.text(), type)
|
|
550
531
|
}
|
|
551
532
|
}
|
|
552
533
|
|
|
@@ -611,10 +592,7 @@ export class DataLayer extends ServerStored {
|
|
|
611
592
|
}
|
|
612
593
|
|
|
613
594
|
reset() {
|
|
614
|
-
if (!this.createdOnServer)
|
|
615
|
-
this.erase()
|
|
616
|
-
return
|
|
617
|
-
}
|
|
595
|
+
if (!this.createdOnServer) this.erase()
|
|
618
596
|
|
|
619
597
|
this.resetOptions()
|
|
620
598
|
this.parentPane.appendChild(this.pane)
|
|
@@ -952,9 +930,9 @@ export class DataLayer extends ServerStored {
|
|
|
952
930
|
else this.hide()
|
|
953
931
|
}
|
|
954
932
|
|
|
955
|
-
zoomTo(
|
|
933
|
+
zoomTo() {
|
|
956
934
|
if (!this.isVisible()) return
|
|
957
|
-
bounds =
|
|
935
|
+
const bounds = this.layer.getBounds()
|
|
958
936
|
if (bounds.isValid()) {
|
|
959
937
|
const options = { maxZoom: this.getOption('zoomTo') }
|
|
960
938
|
this._leafletMap.fitBounds(bounds, options)
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DomEvent,
|
|
3
|
-
DomUtil,
|
|
4
|
-
LatLngBounds,
|
|
5
|
-
} from '../../vendors/leaflet/leaflet-src.esm.js'
|
|
1
|
+
import { DomEvent, DomUtil } 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'
|
|
@@ -64,10 +60,7 @@ export default class Importer extends Utils.WithTemplate {
|
|
|
64
60
|
this.TYPES = ['geojson', 'csv', 'gpx', 'kml', 'osm', 'georss', 'umap']
|
|
65
61
|
this.IMPORTERS = []
|
|
66
62
|
this.loadImporters()
|
|
67
|
-
this.dialog = new Dialog({
|
|
68
|
-
className: 'importers dark',
|
|
69
|
-
back: () => this.showImporters(),
|
|
70
|
-
})
|
|
63
|
+
this.dialog = new Dialog({ className: 'importers dark' })
|
|
71
64
|
}
|
|
72
65
|
|
|
73
66
|
loadImporters() {
|
|
@@ -175,7 +168,7 @@ export default class Importer extends Utils.WithTemplate {
|
|
|
175
168
|
button.addEventListener('click', () => plugin.open(this))
|
|
176
169
|
grid.appendChild(button)
|
|
177
170
|
}
|
|
178
|
-
this.dialog.open({ template: element, cancel: false, accept: false
|
|
171
|
+
this.dialog.open({ template: element, cancel: false, accept: false })
|
|
179
172
|
}
|
|
180
173
|
|
|
181
174
|
build() {
|
|
@@ -277,12 +270,16 @@ export default class Importer extends Utils.WithTemplate {
|
|
|
277
270
|
}
|
|
278
271
|
|
|
279
272
|
submit() {
|
|
273
|
+
let hasErrors
|
|
280
274
|
if (this.format === 'umap') {
|
|
281
|
-
this.full()
|
|
275
|
+
hasErrors = !this.full()
|
|
282
276
|
} else if (!this.url) {
|
|
283
|
-
this.copy()
|
|
277
|
+
hasErrors = !this.copy()
|
|
284
278
|
} else if (this.action) {
|
|
285
|
-
this[this.action]()
|
|
279
|
+
hasErrors = !this[this.action]()
|
|
280
|
+
}
|
|
281
|
+
if (hasErrors === false) {
|
|
282
|
+
Alert.info(translate('Data successfully imported!'))
|
|
286
283
|
}
|
|
287
284
|
}
|
|
288
285
|
|
|
@@ -297,9 +294,8 @@ export default class Importer extends Utils.WithTemplate {
|
|
|
297
294
|
} else if (this.url) {
|
|
298
295
|
this._umap.importFromUrl(this.url, this.format)
|
|
299
296
|
}
|
|
300
|
-
this.onSuccess()
|
|
301
297
|
} catch (e) {
|
|
302
|
-
|
|
298
|
+
Alert.error(translate('Invalid umap data'))
|
|
303
299
|
console.error(e)
|
|
304
300
|
return false
|
|
305
301
|
}
|
|
@@ -310,7 +306,7 @@ export default class Importer extends Utils.WithTemplate {
|
|
|
310
306
|
return false
|
|
311
307
|
}
|
|
312
308
|
if (!this.format) {
|
|
313
|
-
|
|
309
|
+
Alert.error(translate('Please choose a format'))
|
|
314
310
|
return false
|
|
315
311
|
}
|
|
316
312
|
const layer = this.layer
|
|
@@ -322,67 +318,26 @@ export default class Importer extends Utils.WithTemplate {
|
|
|
322
318
|
layer.options.remoteData.proxy = true
|
|
323
319
|
layer.options.remoteData.ttl = SCHEMA.ttl.default
|
|
324
320
|
}
|
|
325
|
-
layer.fetchRemoteData(true)
|
|
326
|
-
if (features?.length) {
|
|
327
|
-
layer.zoomTo()
|
|
328
|
-
this.onSuccess()
|
|
329
|
-
} else {
|
|
330
|
-
this.onError()
|
|
331
|
-
}
|
|
332
|
-
})
|
|
321
|
+
layer.fetchRemoteData(true)
|
|
333
322
|
}
|
|
334
323
|
|
|
335
|
-
|
|
324
|
+
copy() {
|
|
336
325
|
// Format may be guessed from file later.
|
|
337
326
|
// Usefull in case of multiple files with different formats.
|
|
338
327
|
if (!this.format && !this.files.length) {
|
|
339
|
-
|
|
328
|
+
Alert.error(translate('Please choose a format'))
|
|
340
329
|
return false
|
|
341
330
|
}
|
|
342
|
-
let promise
|
|
343
331
|
const layer = this.layer
|
|
344
332
|
if (this.clear) layer.empty()
|
|
345
333
|
if (this.files.length) {
|
|
346
|
-
|
|
334
|
+
for (const file of this.files) {
|
|
335
|
+
this._umap.processFileToImport(file, layer, this.format)
|
|
336
|
+
}
|
|
347
337
|
} else if (this.raw) {
|
|
348
|
-
|
|
338
|
+
layer.importRaw(this.raw, this.format)
|
|
349
339
|
} else if (this.url) {
|
|
350
|
-
|
|
351
|
-
}
|
|
352
|
-
if (promise) promise.then((data) => this.onCopyFinished(layer, data))
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
onError(message = translate('No data has been found for import')) {
|
|
356
|
-
Alert.error(message)
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
onSuccess(count) {
|
|
360
|
-
if (count) {
|
|
361
|
-
Alert.success(
|
|
362
|
-
translate('Successfully imported {count} feature(s)', {
|
|
363
|
-
count: count,
|
|
364
|
-
})
|
|
365
|
-
)
|
|
366
|
-
} else {
|
|
367
|
-
Alert.success(translate('Data successfully imported!'))
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
onCopyFinished(layer, features) {
|
|
372
|
-
// undefined features means error, let original error message pop
|
|
373
|
-
if (!features) return
|
|
374
|
-
if (!features.length) {
|
|
375
|
-
this.onError()
|
|
376
|
-
} else {
|
|
377
|
-
const bounds = new LatLngBounds()
|
|
378
|
-
for (const feature of features) {
|
|
379
|
-
const featureBounds = feature.ui.getBounds
|
|
380
|
-
? feature.ui.getBounds()
|
|
381
|
-
: feature.ui.getCenter()
|
|
382
|
-
bounds.extend(featureBounds)
|
|
383
|
-
}
|
|
384
|
-
this.onSuccess(features.length)
|
|
385
|
-
layer.zoomTo(bounds)
|
|
340
|
+
layer.importFromUrl(this.url, this.format)
|
|
386
341
|
}
|
|
387
342
|
}
|
|
388
343
|
}
|
|
@@ -22,7 +22,7 @@ export function getClass(name) {
|
|
|
22
22
|
|
|
23
23
|
export const RECENT = []
|
|
24
24
|
|
|
25
|
-
const BaseIcon = DivIcon.extend({
|
|
25
|
+
const BaseIcon = L.DivIcon.extend({
|
|
26
26
|
initialize: function (options) {
|
|
27
27
|
const default_options = {
|
|
28
28
|
iconSize: null, // Made in css
|
|
@@ -86,7 +86,6 @@ const DefaultIcon = BaseIcon.extend({
|
|
|
86
86
|
},
|
|
87
87
|
|
|
88
88
|
_setIconStyles: function (img, name) {
|
|
89
|
-
if (this.feature.isActive()) this.options.className += ' umap-icon-active'
|
|
90
89
|
BaseIcon.prototype._setIconStyles.call(this, img, name)
|
|
91
90
|
const color = this._getColor()
|
|
92
91
|
const opacity = this._getOpacity()
|
|
@@ -233,8 +233,12 @@ const ManageTilelayerMixin = {
|
|
|
233
233
|
},
|
|
234
234
|
|
|
235
235
|
updateTileLayers: function () {
|
|
236
|
+
const callback = (tilelayer) => {
|
|
237
|
+
this.options.tilelayer = tilelayer.toJSON()
|
|
238
|
+
this._umap.isDirty = true
|
|
239
|
+
}
|
|
236
240
|
if (this._controls.tilelayersChooser) {
|
|
237
|
-
this._controls.tilelayersChooser.openSwitcher({ edit: true })
|
|
241
|
+
this._controls.tilelayersChooser.openSwitcher({ callback, edit: true })
|
|
238
242
|
}
|
|
239
243
|
},
|
|
240
244
|
}
|
|
@@ -259,12 +263,8 @@ export const LeafletMap = BaseMap.extend({
|
|
|
259
263
|
this.loader.onAdd(this)
|
|
260
264
|
|
|
261
265
|
if (!this.options.noControl) {
|
|
262
|
-
DomEvent.on(document.body, 'dataloading', (
|
|
263
|
-
|
|
264
|
-
)
|
|
265
|
-
DomEvent.on(document.body, 'dataload', (event) =>
|
|
266
|
-
this.fire('dataload', event.detail)
|
|
267
|
-
)
|
|
266
|
+
DomEvent.on(document.body, 'dataloading', (e) => this.fire('dataloading', e))
|
|
267
|
+
DomEvent.on(document.body, 'dataload', (e) => this.fire('dataload', e))
|
|
268
268
|
this.on('click', this.closeInplaceToolbar)
|
|
269
269
|
}
|
|
270
270
|
|
|
@@ -21,22 +21,23 @@ export default function loadPopup(name) {
|
|
|
21
21
|
const Popup = BasePopup.extend({
|
|
22
22
|
initialize: function (feature) {
|
|
23
23
|
this.feature = feature
|
|
24
|
-
|
|
24
|
+
this.container = DomUtil.create('div', 'umap-popup')
|
|
25
|
+
this.format()
|
|
26
|
+
BasePopup.prototype.initialize.call(this, {}, feature)
|
|
27
|
+
this.setContent(this.container)
|
|
25
28
|
},
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
const container = DomUtil.create('div', 'umap-popup')
|
|
30
|
+
format: function () {
|
|
29
31
|
const name = this.feature.getOption('popupTemplate')
|
|
30
|
-
this.content =
|
|
31
|
-
const elements = container.querySelectorAll('img,iframe')
|
|
32
|
+
this.content = loadTemplate(name, this.feature, this.container)
|
|
33
|
+
const elements = this.container.querySelectorAll('img,iframe')
|
|
32
34
|
for (const element of elements) {
|
|
33
35
|
this.onElementLoaded(element)
|
|
34
36
|
}
|
|
35
|
-
if (!elements.length && container.textContent.replace('\n', '') === '') {
|
|
36
|
-
container.innerHTML = ''
|
|
37
|
-
DomUtil.add('h3', '', container, this.feature.getDisplayName())
|
|
37
|
+
if (!elements.length && this.container.textContent.replace('\n', '') === '') {
|
|
38
|
+
this.container.innerHTML = ''
|
|
39
|
+
DomUtil.add('h3', '', this.container, this.feature.getDisplayName())
|
|
38
40
|
}
|
|
39
|
-
this.setContent(container)
|
|
40
41
|
},
|
|
41
42
|
|
|
42
43
|
onElementLoaded: function (el) {
|
|
@@ -2,9 +2,8 @@ import { DomUtil, DomEvent } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
|
2
2
|
import { translate, getLocale } from '../i18n.js'
|
|
3
3
|
import * as Utils from '../utils.js'
|
|
4
4
|
import * as Icon from './icon.js'
|
|
5
|
-
import { Request } from '../request.js'
|
|
6
5
|
|
|
7
|
-
export default
|
|
6
|
+
export default function loadTemplate(name, feature, container) {
|
|
8
7
|
let klass = PopupTemplate
|
|
9
8
|
switch (name) {
|
|
10
9
|
case 'GeoRSSLink':
|
|
@@ -19,12 +18,9 @@ export default async function loadTemplate(name, feature, container) {
|
|
|
19
18
|
case 'OSM':
|
|
20
19
|
klass = OSM
|
|
21
20
|
break
|
|
22
|
-
case 'Wikipedia':
|
|
23
|
-
klass = Wikipedia
|
|
24
|
-
break
|
|
25
21
|
}
|
|
26
22
|
const content = new klass()
|
|
27
|
-
return
|
|
23
|
+
return content.render(feature, container)
|
|
28
24
|
}
|
|
29
25
|
|
|
30
26
|
class PopupTemplate {
|
|
@@ -80,10 +76,10 @@ class PopupTemplate {
|
|
|
80
76
|
}
|
|
81
77
|
}
|
|
82
78
|
|
|
83
|
-
|
|
79
|
+
render(feature, container) {
|
|
84
80
|
const title = this.renderTitle(feature)
|
|
85
81
|
if (title) container.appendChild(title)
|
|
86
|
-
const body =
|
|
82
|
+
const body = this.renderBody(feature)
|
|
87
83
|
if (body) DomUtil.add('div', 'umap-popup-content', container, body)
|
|
88
84
|
const footer = this.renderFooter(feature)
|
|
89
85
|
if (footer) container.appendChild(footer)
|
|
@@ -115,7 +111,7 @@ class Table extends TitleMixin(PopupTemplate) {
|
|
|
115
111
|
)
|
|
116
112
|
}
|
|
117
113
|
|
|
118
|
-
|
|
114
|
+
renderBody(feature) {
|
|
119
115
|
const table = document.createElement('table')
|
|
120
116
|
|
|
121
117
|
for (const key in feature.properties) {
|
|
@@ -129,7 +125,7 @@ class Table extends TitleMixin(PopupTemplate) {
|
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
class GeoRSSImage extends TitleMixin(PopupTemplate) {
|
|
132
|
-
|
|
128
|
+
renderBody(feature) {
|
|
133
129
|
const body = DomUtil.create('a')
|
|
134
130
|
body.href = feature.properties.link
|
|
135
131
|
body.target = '_blank'
|
|
@@ -146,7 +142,7 @@ class GeoRSSImage extends TitleMixin(PopupTemplate) {
|
|
|
146
142
|
}
|
|
147
143
|
|
|
148
144
|
class GeoRSSLink extends PopupTemplate {
|
|
149
|
-
|
|
145
|
+
renderBody(feature) {
|
|
150
146
|
if (feature.properties.link) {
|
|
151
147
|
return Utils.loadTemplate(
|
|
152
148
|
`<a href="${feature.properties.link}" target="_blank"><h3>${feature.getDisplayName()}</h3></a>`
|
|
@@ -155,7 +151,7 @@ class GeoRSSLink extends PopupTemplate {
|
|
|
155
151
|
}
|
|
156
152
|
}
|
|
157
153
|
|
|
158
|
-
class OSM extends PopupTemplate {
|
|
154
|
+
class OSM extends TitleMixin(PopupTemplate) {
|
|
159
155
|
renderTitle(feature) {
|
|
160
156
|
const title = DomUtil.add('h3', 'popup-title')
|
|
161
157
|
const color = feature.getPreviewColor()
|
|
@@ -176,7 +172,7 @@ class OSM extends PopupTemplate {
|
|
|
176
172
|
return props.name
|
|
177
173
|
}
|
|
178
174
|
|
|
179
|
-
|
|
175
|
+
renderBody(feature) {
|
|
180
176
|
const props = feature.properties
|
|
181
177
|
const body = document.createElement('div')
|
|
182
178
|
const locale = getLocale()
|
|
@@ -242,43 +238,3 @@ class OSM extends PopupTemplate {
|
|
|
242
238
|
return body
|
|
243
239
|
}
|
|
244
240
|
}
|
|
245
|
-
|
|
246
|
-
const _WIKIPEDIA_CACHE = {}
|
|
247
|
-
|
|
248
|
-
class Wikipedia extends PopupTemplate {
|
|
249
|
-
async callWikipedia(wikipedia) {
|
|
250
|
-
if (wikipedia && _WIKIPEDIA_CACHE[wikipedia]) return _WIKIPEDIA_CACHE[wikipedia]
|
|
251
|
-
// Wikipedia value should be in form of "{locale}:{title}", according to https://wiki.openstreetmap.org/wiki/Key:wikipedia
|
|
252
|
-
const [locale, page] = wikipedia.split(':')
|
|
253
|
-
const url = `https://${locale}.wikipedia.org/w/api.php?action=query&format=json&origin=*&pithumbsize=500&prop=extracts|pageimages&titles=${page}`
|
|
254
|
-
const request = new Request()
|
|
255
|
-
const response = await request.get(url)
|
|
256
|
-
if (response?.ok) {
|
|
257
|
-
const data = await response.json()
|
|
258
|
-
_WIKIPEDIA_CACHE[wikipedia] = data
|
|
259
|
-
return data
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
async renderBody(feature) {
|
|
264
|
-
const body = document.createElement('div')
|
|
265
|
-
const wikipedia = feature.properties.wikipedia
|
|
266
|
-
if (!wikipedia) return ''
|
|
267
|
-
const data = await this.callWikipedia(wikipedia)
|
|
268
|
-
if (data) {
|
|
269
|
-
const page = Object.values(data.query.pages)[0]
|
|
270
|
-
const title = page.title || feature.getDisplayName()
|
|
271
|
-
const extract = page.extract || ''
|
|
272
|
-
const thumbnail = page.thumbnail?.source
|
|
273
|
-
const [content, { image }] = Utils.loadTemplateWithRefs(
|
|
274
|
-
`<div><h3>${Utils.escapeHTML(title)}</h3><img data-ref="image" hidden src="" />${Utils.escapeHTML(extract)}</div>`
|
|
275
|
-
)
|
|
276
|
-
if (thumbnail) {
|
|
277
|
-
image.src = thumbnail
|
|
278
|
-
image.hidden = false
|
|
279
|
-
}
|
|
280
|
-
body.appendChild(content)
|
|
281
|
-
}
|
|
282
|
-
return body
|
|
283
|
-
}
|
|
284
|
-
}
|