umap-project 2.7.2__py3-none-any.whl → 2.8.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/forms.py +4 -14
- umap/locale/am_ET/LC_MESSAGES/django.mo +0 -0
- umap/locale/am_ET/LC_MESSAGES/django.po +278 -151
- umap/locale/ar/LC_MESSAGES/django.mo +0 -0
- umap/locale/ar/LC_MESSAGES/django.po +335 -141
- umap/locale/bg/LC_MESSAGES/django.mo +0 -0
- umap/locale/bg/LC_MESSAGES/django.po +279 -152
- umap/locale/br/LC_MESSAGES/django.mo +0 -0
- umap/locale/br/LC_MESSAGES/django.po +95 -79
- umap/locale/ca/LC_MESSAGES/django.mo +0 -0
- umap/locale/ca/LC_MESSAGES/django.po +85 -68
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +78 -66
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +280 -153
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +80 -64
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +82 -66
- umap/locale/en/LC_MESSAGES/django.po +73 -61
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +75 -63
- umap/locale/et/LC_MESSAGES/django.mo +0 -0
- umap/locale/et/LC_MESSAGES/django.po +280 -153
- umap/locale/eu/LC_MESSAGES/django.mo +0 -0
- umap/locale/eu/LC_MESSAGES/django.po +82 -66
- umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
- umap/locale/fa_IR/LC_MESSAGES/django.po +80 -64
- umap/locale/fi/LC_MESSAGES/django.mo +0 -0
- umap/locale/fi/LC_MESSAGES/django.po +278 -151
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +75 -63
- umap/locale/gl/LC_MESSAGES/django.mo +0 -0
- umap/locale/gl/LC_MESSAGES/django.po +280 -153
- umap/locale/he/LC_MESSAGES/django.mo +0 -0
- umap/locale/he/LC_MESSAGES/django.po +281 -154
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +80 -64
- umap/locale/is/LC_MESSAGES/django.mo +0 -0
- umap/locale/is/LC_MESSAGES/django.po +280 -153
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +82 -66
- umap/locale/ja/LC_MESSAGES/django.mo +0 -0
- umap/locale/ja/LC_MESSAGES/django.po +280 -153
- umap/locale/ko/LC_MESSAGES/django.mo +0 -0
- umap/locale/ko/LC_MESSAGES/django.po +280 -153
- umap/locale/lt/LC_MESSAGES/django.mo +0 -0
- umap/locale/lt/LC_MESSAGES/django.po +280 -153
- umap/locale/ms/LC_MESSAGES/django.mo +0 -0
- umap/locale/ms/LC_MESSAGES/django.po +82 -66
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +280 -153
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +82 -66
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +75 -63
- umap/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt_BR/LC_MESSAGES/django.po +280 -153
- umap/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt_PT/LC_MESSAGES/django.po +280 -153
- umap/locale/ru/LC_MESSAGES/django.mo +0 -0
- umap/locale/ru/LC_MESSAGES/django.po +280 -153
- umap/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- umap/locale/sk_SK/LC_MESSAGES/django.po +280 -153
- umap/locale/sl/LC_MESSAGES/django.mo +0 -0
- umap/locale/sl/LC_MESSAGES/django.po +280 -153
- umap/locale/sr/LC_MESSAGES/django.mo +0 -0
- umap/locale/sr/LC_MESSAGES/django.po +280 -153
- umap/locale/sv/LC_MESSAGES/django.mo +0 -0
- umap/locale/sv/LC_MESSAGES/django.po +81 -65
- umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
- umap/locale/th_TH/LC_MESSAGES/django.po +257 -185
- umap/locale/tr/LC_MESSAGES/django.mo +0 -0
- umap/locale/tr/LC_MESSAGES/django.po +280 -153
- umap/locale/uk_UA/LC_MESSAGES/django.mo +0 -0
- umap/locale/uk_UA/LC_MESSAGES/django.po +280 -153
- umap/locale/vi/LC_MESSAGES/django.mo +0 -0
- umap/locale/vi/LC_MESSAGES/django.po +278 -151
- umap/locale/zh/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh/LC_MESSAGES/django.po +278 -151
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +97 -81
- umap/management/commands/empty_trash.py +35 -0
- umap/management/commands/migrate_to_S3.py +29 -0
- umap/migrations/0023_alter_datalayer_uuid.py +19 -0
- umap/migrations/0024_alter_map_share_status.py +30 -0
- umap/migrations/0025_alter_datalayer_geojson.py +24 -0
- umap/models.py +68 -116
- umap/settings/base.py +23 -3
- umap/settings/local_s3.py +45 -0
- umap/static/umap/base.css +3 -603
- umap/static/umap/content.css +5 -3
- umap/static/umap/css/bar.css +202 -0
- umap/static/umap/css/form.css +620 -0
- umap/static/umap/css/icon.css +21 -1
- umap/static/umap/css/popup.css +125 -0
- umap/static/umap/img/16-white.svg +16 -4
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/source/16-white.svg +46 -45
- umap/static/umap/img/source/16.svg +1 -753
- umap/static/umap/js/components/fragment.js +3 -1
- umap/static/umap/js/modules/browser.js +20 -19
- umap/static/umap/js/modules/caption.js +21 -22
- umap/static/umap/js/modules/data/features.js +120 -78
- umap/static/umap/js/modules/data/layer.js +195 -153
- umap/static/umap/js/modules/facets.js +9 -9
- umap/static/umap/js/modules/formatter.js +5 -5
- umap/static/umap/js/modules/global.js +4 -52
- umap/static/umap/js/modules/help.js +18 -21
- umap/static/umap/js/modules/importer.js +133 -56
- umap/static/umap/js/modules/importers/cadastrefr.js +4 -0
- umap/static/umap/js/modules/importers/geodatamine.js +3 -3
- umap/static/umap/js/modules/importers/overpass.js +5 -0
- umap/static/umap/js/modules/permissions.js +85 -87
- umap/static/umap/js/modules/rendering/icon.js +2 -1
- umap/static/umap/js/modules/rendering/layers/base.js +15 -15
- umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
- umap/static/umap/js/modules/rendering/layers/cluster.js +1 -1
- umap/static/umap/js/modules/rendering/layers/heat.js +1 -1
- umap/static/umap/js/modules/rendering/map.js +390 -0
- umap/static/umap/js/modules/rendering/popup.js +19 -19
- umap/static/umap/js/modules/rendering/template.js +88 -21
- umap/static/umap/js/modules/rendering/ui.js +63 -14
- umap/static/umap/js/modules/request.js +2 -2
- umap/static/umap/js/modules/rules.js +22 -25
- umap/static/umap/js/modules/saving.js +47 -0
- umap/static/umap/js/modules/schema.js +6 -0
- umap/static/umap/js/modules/share.js +21 -24
- umap/static/umap/js/modules/slideshow.js +24 -20
- umap/static/umap/js/modules/sync/updaters.js +7 -9
- umap/static/umap/js/modules/tableeditor.js +20 -19
- umap/static/umap/js/modules/ui/bar.js +196 -0
- umap/static/umap/js/modules/ui/dialog.js +6 -1
- umap/static/umap/js/modules/ui/panel.js +10 -9
- umap/static/umap/js/modules/umap.js +1691 -0
- umap/static/umap/js/modules/urls.js +2 -2
- umap/static/umap/js/modules/utils.js +22 -6
- umap/static/umap/js/umap.controls.js +81 -305
- umap/static/umap/js/umap.core.js +29 -50
- umap/static/umap/js/umap.forms.js +78 -27
- umap/static/umap/keycloak.png +0 -0
- umap/static/umap/locale/am_ET.js +26 -10
- umap/static/umap/locale/am_ET.json +26 -10
- umap/static/umap/locale/ar.js +26 -10
- umap/static/umap/locale/ar.json +26 -10
- umap/static/umap/locale/ast.js +26 -10
- umap/static/umap/locale/ast.json +26 -10
- umap/static/umap/locale/bg.js +26 -10
- umap/static/umap/locale/bg.json +26 -10
- umap/static/umap/locale/br.js +27 -20
- umap/static/umap/locale/br.json +27 -20
- umap/static/umap/locale/ca.js +32 -29
- umap/static/umap/locale/ca.json +32 -29
- umap/static/umap/locale/cs_CZ.js +24 -17
- umap/static/umap/locale/cs_CZ.json +24 -17
- umap/static/umap/locale/da.js +26 -10
- umap/static/umap/locale/da.json +26 -10
- umap/static/umap/locale/de.js +21 -14
- umap/static/umap/locale/de.json +21 -14
- umap/static/umap/locale/el.js +28 -12
- umap/static/umap/locale/el.json +28 -12
- umap/static/umap/locale/en.js +14 -9
- umap/static/umap/locale/en.json +14 -9
- umap/static/umap/locale/en_US.json +26 -10
- umap/static/umap/locale/es.js +16 -13
- umap/static/umap/locale/es.json +16 -13
- umap/static/umap/locale/et.js +26 -10
- umap/static/umap/locale/et.json +26 -10
- umap/static/umap/locale/eu.js +16 -9
- umap/static/umap/locale/eu.json +16 -9
- umap/static/umap/locale/fa_IR.js +16 -9
- umap/static/umap/locale/fa_IR.json +16 -9
- umap/static/umap/locale/fi.js +26 -10
- umap/static/umap/locale/fi.json +26 -10
- umap/static/umap/locale/fr.js +14 -9
- umap/static/umap/locale/fr.json +14 -9
- umap/static/umap/locale/gl.js +26 -10
- umap/static/umap/locale/gl.json +26 -10
- umap/static/umap/locale/he.js +26 -10
- umap/static/umap/locale/he.json +26 -10
- umap/static/umap/locale/hr.js +26 -10
- umap/static/umap/locale/hr.json +26 -10
- umap/static/umap/locale/hu.js +16 -9
- umap/static/umap/locale/hu.json +16 -9
- umap/static/umap/locale/id.js +26 -10
- umap/static/umap/locale/id.json +26 -10
- umap/static/umap/locale/is.js +26 -10
- umap/static/umap/locale/is.json +26 -10
- umap/static/umap/locale/it.js +26 -10
- umap/static/umap/locale/it.json +26 -10
- umap/static/umap/locale/ja.js +26 -10
- umap/static/umap/locale/ja.json +26 -10
- umap/static/umap/locale/ko.js +26 -10
- umap/static/umap/locale/ko.json +26 -10
- umap/static/umap/locale/lt.js +26 -10
- umap/static/umap/locale/lt.json +26 -10
- umap/static/umap/locale/ms.js +28 -12
- umap/static/umap/locale/ms.json +28 -12
- umap/static/umap/locale/nl.js +28 -12
- umap/static/umap/locale/nl.json +28 -12
- umap/static/umap/locale/no.js +26 -10
- umap/static/umap/locale/no.json +26 -10
- umap/static/umap/locale/pl.js +28 -12
- umap/static/umap/locale/pl.json +28 -12
- umap/static/umap/locale/pl_PL.json +26 -10
- umap/static/umap/locale/pt.js +16 -9
- umap/static/umap/locale/pt.json +16 -9
- umap/static/umap/locale/pt_BR.js +26 -10
- umap/static/umap/locale/pt_BR.json +26 -10
- umap/static/umap/locale/pt_PT.js +16 -9
- umap/static/umap/locale/pt_PT.json +16 -9
- umap/static/umap/locale/ro.js +26 -10
- umap/static/umap/locale/ro.json +26 -10
- umap/static/umap/locale/ru.js +26 -10
- umap/static/umap/locale/ru.json +26 -10
- umap/static/umap/locale/si.js +7 -7
- umap/static/umap/locale/si.json +7 -7
- umap/static/umap/locale/sk_SK.js +26 -10
- umap/static/umap/locale/sk_SK.json +26 -10
- umap/static/umap/locale/sl.js +26 -10
- umap/static/umap/locale/sl.json +26 -10
- umap/static/umap/locale/sr.js +26 -10
- umap/static/umap/locale/sr.json +26 -10
- umap/static/umap/locale/sv.js +27 -11
- umap/static/umap/locale/sv.json +27 -11
- umap/static/umap/locale/th_TH.js +28 -12
- umap/static/umap/locale/th_TH.json +28 -12
- umap/static/umap/locale/tr.js +26 -10
- umap/static/umap/locale/tr.json +26 -10
- umap/static/umap/locale/uk_UA.js +26 -10
- umap/static/umap/locale/uk_UA.json +26 -10
- umap/static/umap/locale/vi.js +26 -10
- umap/static/umap/locale/vi.json +26 -10
- umap/static/umap/locale/vi_VN.json +26 -10
- umap/static/umap/locale/zh.js +26 -10
- umap/static/umap/locale/zh.json +26 -10
- umap/static/umap/locale/zh_CN.json +26 -10
- umap/static/umap/locale/zh_TW.Big5.json +26 -10
- umap/static/umap/locale/zh_TW.js +34 -27
- umap/static/umap/locale/zh_TW.json +34 -27
- umap/static/umap/map.css +39 -530
- umap/static/umap/unittests/URLs.js +15 -15
- umap/static/umap/unittests/utils.js +23 -1
- umap/static/umap/vars.css +2 -1
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +5 -1
- umap/storage/__init__.py +3 -0
- umap/storage/fs.py +101 -0
- umap/storage/s3.py +61 -0
- umap/templates/base.html +2 -0
- umap/templates/registration/login.html +7 -6
- umap/templates/umap/components/alerts/alert.html +4 -0
- umap/templates/umap/css.html +6 -0
- umap/templates/umap/js.html +3 -2
- umap/templates/umap/map_init.html +6 -5
- umap/templates/umap/user_dashboard.html +20 -19
- umap/tests/base.py +11 -1
- umap/tests/fixtures/empty_tile.png +0 -0
- umap/tests/fixtures/test_upload_simple_marker.json +19 -0
- umap/tests/integration/conftest.py +4 -1
- umap/tests/integration/test_anonymous_owned_map.py +18 -10
- umap/tests/integration/test_browser.py +16 -1
- umap/tests/integration/test_dashboard.py +1 -1
- umap/tests/integration/test_edit_datalayer.py +29 -7
- umap/tests/integration/test_import.py +28 -4
- umap/tests/integration/test_optimistic_merge.py +31 -8
- umap/tests/integration/test_owned_map.py +22 -16
- umap/tests/integration/test_popup.py +44 -0
- umap/tests/integration/test_save.py +35 -0
- umap/tests/integration/test_view_marker.py +12 -0
- umap/tests/integration/test_view_polyline.py +257 -0
- umap/tests/integration/test_websocket_sync.py +81 -9
- umap/tests/test_dashboard.py +82 -0
- umap/tests/test_datalayer.py +6 -7
- umap/tests/test_datalayer_s3.py +135 -0
- umap/tests/test_datalayer_views.py +28 -10
- umap/tests/test_empty_trash.py +34 -0
- umap/tests/test_map.py +12 -3
- umap/tests/test_map_views.py +69 -37
- umap/tests/test_statics.py +1 -1
- umap/tests/test_team_views.py +35 -1
- umap/tests/test_views.py +31 -52
- umap/urls.py +3 -3
- umap/views.py +126 -90
- {umap_project-2.7.2.dist-info → umap_project-2.8.0.dist-info}/METADATA +16 -14
- {umap_project-2.7.2.dist-info → umap_project-2.8.0.dist-info}/RECORD +290 -269
- {umap_project-2.7.2.dist-info → umap_project-2.8.0.dist-info}/WHEEL +1 -1
- umap/management/commands/purge_purgatory.py +0 -28
- umap/static/umap/js/umap.js +0 -1903
- umap/tests/test_purge_purgatory.py +0 -25
- /umap/{storage.py → storage/staticfiles.py} +0 -0
- {umap_project-2.7.2.dist-info → umap_project-2.8.0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.7.2.dist-info → umap_project-2.8.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -147,7 +147,7 @@ describe('Utils', () => {
|
|
|
147
147
|
)
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
it('should handle iframe
|
|
150
|
+
it('should handle double iframe', () => {
|
|
151
151
|
assert.equal(
|
|
152
152
|
Utils.toHTML(
|
|
153
153
|
'A double iframe: {{{https://osm.org/pouet}}}{{{https://osm.org/boudin}}}'
|
|
@@ -156,6 +156,15 @@ describe('Utils', () => {
|
|
|
156
156
|
)
|
|
157
157
|
})
|
|
158
158
|
|
|
159
|
+
it('should handle iframe with query string and space', () => {
|
|
160
|
+
assert.equal(
|
|
161
|
+
Utils.toHTML(
|
|
162
|
+
'An iframe with query string: {{{https://osm.org/pouet.html?name=foobar&description=baz baz}}}'
|
|
163
|
+
),
|
|
164
|
+
'An iframe with query string: <div><iframe height="300px" width="100%" src="https://osm.org/pouet.html?name=foobar&description=baz baz" frameborder="0"></iframe></div>'
|
|
165
|
+
)
|
|
166
|
+
})
|
|
167
|
+
|
|
159
168
|
it('http link with http link as parameter as variable', () => {
|
|
160
169
|
assert.equal(
|
|
161
170
|
Utils.toHTML('A phrase with a [[http://iframeurl.com?to=http://another.com]].'),
|
|
@@ -263,6 +272,19 @@ describe('Utils', () => {
|
|
|
263
272
|
)
|
|
264
273
|
})
|
|
265
274
|
|
|
275
|
+
it('should process variables in http links', () => {
|
|
276
|
+
assert.equal(
|
|
277
|
+
Utils.greedyTemplate(
|
|
278
|
+
'A phrase with a {{{https://osm.org/pouet?name={name}&description={description}}}}.',
|
|
279
|
+
{
|
|
280
|
+
name: 'foobar',
|
|
281
|
+
description: 'bazbaz',
|
|
282
|
+
}
|
|
283
|
+
),
|
|
284
|
+
'A phrase with a {{{https://osm.org/pouet?name=foobar&description=bazbaz}}}.'
|
|
285
|
+
)
|
|
286
|
+
})
|
|
287
|
+
|
|
266
288
|
it('should not accept dash', () => {
|
|
267
289
|
assert.equal(
|
|
268
290
|
Utils.greedyTemplate('A phrase with a {var-iable}.', { 'var-iable': 'value' }),
|
umap/static/umap/vars.css
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
/* Colors. */
|
|
3
3
|
--color-waterMint: #B9F5D2;
|
|
4
4
|
--color-darkBlue: #263B58;
|
|
5
|
+
--color-lighterGray: #f6f6f6;
|
|
5
6
|
--color-lightGray: #ddd;
|
|
6
7
|
--color-mediumGray: #3e4444;
|
|
7
8
|
--color-darkGray: #323737;
|
|
9
|
+
--color-darkerGray: #2a2e30;
|
|
8
10
|
--color-light: white;
|
|
9
11
|
--color-dark: black;
|
|
10
12
|
--color-limeGreen: #b9f5d2;
|
|
@@ -46,7 +48,6 @@
|
|
|
46
48
|
--zindex-autocomplete: 470;
|
|
47
49
|
--zindex-dialog: 460;
|
|
48
50
|
--zindex-contextmenu: 455;
|
|
49
|
-
--zindex-icon-active: 450;
|
|
50
51
|
--zindex-tooltip: 445;
|
|
51
52
|
--zindex-panels: 440;
|
|
52
53
|
--zindex-controls: 430;
|
umap/storage/__init__.py
ADDED
umap/storage/fs.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import operator
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from django.conf import settings
|
|
7
|
+
from django.core.files.storage import FileSystemStorage
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FSDataStorage(FileSystemStorage):
|
|
11
|
+
def get_reference_version(self, instance):
|
|
12
|
+
return self._extract_version_ref(instance.geojson.name)
|
|
13
|
+
|
|
14
|
+
def make_filename(self, instance):
|
|
15
|
+
root = self._base_path(instance)
|
|
16
|
+
name = "%s_%s.geojson" % (instance.pk, int(time.time() * 1000))
|
|
17
|
+
return root / name
|
|
18
|
+
|
|
19
|
+
def list_versions(self, instance):
|
|
20
|
+
root = self._base_path(instance)
|
|
21
|
+
names = self.listdir(root)[1]
|
|
22
|
+
names = [name for name in names if self._is_valid_version(name, instance)]
|
|
23
|
+
versions = [self._version_metadata(name, instance) for name in names]
|
|
24
|
+
versions.sort(reverse=True, key=operator.itemgetter("at"))
|
|
25
|
+
return versions
|
|
26
|
+
|
|
27
|
+
def get_version(self, ref, instance):
|
|
28
|
+
with self.open(self.get_version_path(ref, instance), "r") as f:
|
|
29
|
+
return f.read()
|
|
30
|
+
|
|
31
|
+
def get_version_path(self, ref, instance):
|
|
32
|
+
base_path = Path(settings.MEDIA_ROOT) / self._base_path(instance)
|
|
33
|
+
fullpath = base_path / f"{instance.pk}_{ref}.geojson"
|
|
34
|
+
if instance.old_id and not fullpath.exists():
|
|
35
|
+
fullpath = base_path / f"{instance.old_id}_{ref}.geojson"
|
|
36
|
+
if not fullpath.exists():
|
|
37
|
+
raise ValueError(f"Invalid version reference: {ref}")
|
|
38
|
+
return fullpath
|
|
39
|
+
|
|
40
|
+
def onDatalayerSave(self, instance):
|
|
41
|
+
self._purge_gzip(instance)
|
|
42
|
+
self._purge_old_versions(instance, keep=settings.UMAP_KEEP_VERSIONS)
|
|
43
|
+
|
|
44
|
+
def onDatalayerDelete(self, instance):
|
|
45
|
+
self._purge_gzip(instance)
|
|
46
|
+
self._purge_old_versions(instance, keep=None)
|
|
47
|
+
|
|
48
|
+
def _extract_version_ref(self, path):
|
|
49
|
+
version = path.split(".")[0]
|
|
50
|
+
if "_" in version:
|
|
51
|
+
return version.split("_")[-1]
|
|
52
|
+
return version
|
|
53
|
+
|
|
54
|
+
def _base_path(self, instance):
|
|
55
|
+
path = ["datalayer", str(instance.map.pk)[-1]]
|
|
56
|
+
if len(str(instance.map.pk)) > 1:
|
|
57
|
+
path.append(str(instance.map.pk)[-2])
|
|
58
|
+
path.append(str(instance.map.pk))
|
|
59
|
+
return Path(os.path.join(*path))
|
|
60
|
+
|
|
61
|
+
def _is_valid_version(self, name, instance):
|
|
62
|
+
valid_prefixes = [name.startswith("%s_" % instance.pk)]
|
|
63
|
+
if instance.old_id:
|
|
64
|
+
valid_prefixes.append(name.startswith("%s_" % instance.old_id))
|
|
65
|
+
return any(valid_prefixes) and name.endswith(".geojson")
|
|
66
|
+
|
|
67
|
+
def _version_metadata(self, name, instance):
|
|
68
|
+
ref = self._extract_version_ref(name)
|
|
69
|
+
return {
|
|
70
|
+
"name": name,
|
|
71
|
+
"ref": ref,
|
|
72
|
+
"at": ref,
|
|
73
|
+
"size": self.size(self._base_path(instance) / name),
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
def _purge_old_versions(self, instance, keep=None):
|
|
77
|
+
root = self._base_path(instance)
|
|
78
|
+
versions = self.list_versions(instance)
|
|
79
|
+
if keep is not None:
|
|
80
|
+
versions = versions[keep:]
|
|
81
|
+
for version in versions:
|
|
82
|
+
name = version["name"]
|
|
83
|
+
# Should not be in the list, but ensure to not delete the file
|
|
84
|
+
# currently used in database
|
|
85
|
+
if keep is not None and instance.geojson.name.endswith(name):
|
|
86
|
+
continue
|
|
87
|
+
try:
|
|
88
|
+
self.delete(root / name)
|
|
89
|
+
except FileNotFoundError:
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
def _purge_gzip(self, instance):
|
|
93
|
+
root = self._base_path(instance)
|
|
94
|
+
names = self.listdir(root)[1]
|
|
95
|
+
prefixes = [f"{instance.pk}_"]
|
|
96
|
+
if instance.old_id:
|
|
97
|
+
prefixes.append(f"{instance.old_id}_")
|
|
98
|
+
prefixes = tuple(prefixes)
|
|
99
|
+
for name in names:
|
|
100
|
+
if name.startswith(prefixes) and name.endswith(".gz"):
|
|
101
|
+
self.delete(root / name)
|
umap/storage/s3.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from gzip import GzipFile
|
|
2
|
+
|
|
3
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from botocore.exceptions import ClientError
|
|
7
|
+
from storages.backends.s3 import S3Storage
|
|
8
|
+
except ImportError:
|
|
9
|
+
raise ImproperlyConfigured(
|
|
10
|
+
"You need to install s3 dependencies: pip install umap-project[s3]"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class S3DataStorage(S3Storage):
|
|
15
|
+
gzip = True
|
|
16
|
+
|
|
17
|
+
def get_reference_version(self, instance):
|
|
18
|
+
metadata = self.connection.meta.client.head_object(
|
|
19
|
+
Bucket=self.bucket_name, Key=instance.geojson.name
|
|
20
|
+
)
|
|
21
|
+
# Do not fail if bucket does not handle versioning
|
|
22
|
+
return metadata.get("VersionId", metadata["ETag"])
|
|
23
|
+
|
|
24
|
+
def make_filename(self, instance):
|
|
25
|
+
return f"{str(instance.pk)}.geojson"
|
|
26
|
+
|
|
27
|
+
def list_versions(self, instance):
|
|
28
|
+
response = self.connection.meta.client.list_object_versions(
|
|
29
|
+
Bucket=self.bucket_name, Prefix=instance.geojson.name
|
|
30
|
+
)
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
"ref": version["VersionId"],
|
|
34
|
+
"at": version["LastModified"].timestamp() * 1000,
|
|
35
|
+
"size": version["Size"],
|
|
36
|
+
}
|
|
37
|
+
for version in response["Versions"]
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
def get_version(self, ref, instance):
|
|
41
|
+
try:
|
|
42
|
+
data = self.connection.meta.client.get_object(
|
|
43
|
+
Bucket=self.bucket_name,
|
|
44
|
+
Key=instance.geojson.name,
|
|
45
|
+
VersionId=ref,
|
|
46
|
+
)
|
|
47
|
+
except ClientError:
|
|
48
|
+
raise ValueError(f"Invalid version reference: {ref}")
|
|
49
|
+
return GzipFile(mode="r", fileobj=data["Body"]).read()
|
|
50
|
+
|
|
51
|
+
def get_version_path(self, ref, instance):
|
|
52
|
+
return self.url(instance.geojson.name, parameters={"VersionId": ref})
|
|
53
|
+
|
|
54
|
+
def onDatalayerSave(self, instance):
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
def onDatalayerDelete(self, instance):
|
|
58
|
+
return self.connection.meta.client.delete_object(
|
|
59
|
+
Bucket=self.bucket_name,
|
|
60
|
+
Key=instance.geojson.name,
|
|
61
|
+
)
|
umap/templates/base.html
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
<meta name="viewport"
|
|
19
19
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
20
20
|
{# See https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs #}
|
|
21
|
+
{% autoescape off %}
|
|
21
22
|
<link rel="icon"
|
|
22
23
|
href="{% static 'umap/favicons/favicon.ico' %}"
|
|
23
24
|
sizes="32x32">
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
href="{% static 'umap/favicons/apple-touch-icon.png' %}">
|
|
29
30
|
<!-- 180×180 -->
|
|
30
31
|
<link rel="manifest" href="/manifest.webmanifest">
|
|
32
|
+
{% endautoescape %}
|
|
31
33
|
</head>
|
|
32
34
|
<body class="{% block body_class %}{% endblock body_class %}">
|
|
33
35
|
{% block header %}
|
|
@@ -19,10 +19,11 @@
|
|
|
19
19
|
<header class="umap-nav">
|
|
20
20
|
{% include "umap/branding.html" %}
|
|
21
21
|
</header>
|
|
22
|
+
<h2>{% trans "To save and easily find your maps, identify yourself." %}</h2>
|
|
22
23
|
{% if ENABLE_ACCOUNT_LOGIN %}
|
|
23
|
-
<
|
|
24
|
-
{% trans "Please log in with your account" %}
|
|
25
|
-
</
|
|
24
|
+
<h3>
|
|
25
|
+
{% trans "Please log in with your account:" %}
|
|
26
|
+
</h3>
|
|
26
27
|
<div>
|
|
27
28
|
{% if form.non_field_errors %}
|
|
28
29
|
<ul class="form-errors">
|
|
@@ -47,9 +48,9 @@
|
|
|
47
48
|
</div>
|
|
48
49
|
{% endif %}
|
|
49
50
|
{% if backends.backends|length %}
|
|
50
|
-
<
|
|
51
|
-
{% trans "Please choose a provider" %}
|
|
52
|
-
</
|
|
51
|
+
<h3>
|
|
52
|
+
{% trans "Please choose a provider:" %}
|
|
53
|
+
</h3>
|
|
53
54
|
<div>
|
|
54
55
|
<ul class="login-grid block-grid">
|
|
55
56
|
{% for name in backends.backends %}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{% load i18n static %}
|
|
2
2
|
|
|
3
|
+
{% autoescape off %}
|
|
3
4
|
<style type="text/css">
|
|
4
5
|
@import "{% static 'umap/js/components/alerts/alert.css' %}";
|
|
5
6
|
</style>
|
|
7
|
+
{% endautoescape %}
|
|
6
8
|
<template id="umap-alert-template">
|
|
7
9
|
<div role="dialog" class="dark window umap-alert">
|
|
8
10
|
<div>
|
|
@@ -97,6 +99,7 @@
|
|
|
97
99
|
</div>
|
|
98
100
|
</template>
|
|
99
101
|
<umap-alert-conflict></umap-alert-conflict>
|
|
102
|
+
{% autoescape off %}
|
|
100
103
|
<script type="module">
|
|
101
104
|
import { register } from '{% static 'umap/js/components/base.js' %}'
|
|
102
105
|
import {
|
|
@@ -108,3 +111,4 @@
|
|
|
108
111
|
register(uMapAlertCreation, 'umap-alert-creation')
|
|
109
112
|
register(uMapAlertConflict, 'umap-alert-conflict')
|
|
110
113
|
</script>
|
|
114
|
+
{% endautoescape %}
|
umap/templates/umap/css.html
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
{% load static %}
|
|
2
2
|
|
|
3
|
+
{% autoescape off %}
|
|
4
|
+
|
|
3
5
|
<link rel="stylesheet"
|
|
4
6
|
href="{% static 'umap/vendors/leaflet/leaflet.css' %}" />
|
|
5
7
|
<link rel="stylesheet"
|
|
@@ -24,6 +26,8 @@
|
|
|
24
26
|
<link rel="stylesheet" href="{% static 'umap/font.css' %}" />
|
|
25
27
|
<link rel="stylesheet" href="{% static 'umap/css/icon.css' %}" />
|
|
26
28
|
<link rel="stylesheet" href="{% static 'umap/base.css' %}" />
|
|
29
|
+
<link rel="stylesheet" href="{% static 'umap/css/popup.css' %}" />
|
|
30
|
+
<link rel="stylesheet" href="{% static 'umap/css/form.css' %}" />
|
|
27
31
|
<link rel="stylesheet" href="{% static 'umap/content.css' %}" />
|
|
28
32
|
<link rel="stylesheet" href="{% static 'umap/nav.css' %}" />
|
|
29
33
|
<link rel="stylesheet" href="{% static 'umap/map.css' %}" />
|
|
@@ -35,4 +39,6 @@
|
|
|
35
39
|
<link rel="stylesheet" href="{% static 'umap/css/dialog.css' %}" />
|
|
36
40
|
<link rel="stylesheet" href="{% static 'umap/css/importers.css' %}" />
|
|
37
41
|
<link rel="stylesheet" href="{% static 'umap/css/tableeditor.css' %}" />
|
|
42
|
+
<link rel="stylesheet" href="{% static 'umap/css/bar.css' %}" />
|
|
38
43
|
<link rel="stylesheet" href="{% static 'umap/theme.css' %}" />
|
|
44
|
+
{% endautoescape %}
|
umap/templates/umap/js.html
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{% load static %}
|
|
2
2
|
|
|
3
|
+
{% autoescape off %}
|
|
3
4
|
<script type="module"
|
|
4
5
|
src="{% static 'umap/vendors/leaflet/leaflet-src.esm.js' %}"
|
|
5
6
|
defer></script>
|
|
@@ -41,5 +42,5 @@
|
|
|
41
42
|
<script src="{% static 'umap/js/umap.core.js' %}" defer></script>
|
|
42
43
|
<script src="{% static 'umap/js/umap.forms.js' %}" defer></script>
|
|
43
44
|
<script src="{% static 'umap/js/umap.controls.js' %}" defer></script>
|
|
44
|
-
<script src="{% static 'umap/js/
|
|
45
|
-
|
|
45
|
+
<script type="module" src="{% static 'umap/js/components/fragment.js' %}" defer></script>
|
|
46
|
+
{% endautoescape %}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
{% load umap_tags %}
|
|
1
|
+
{% load umap_tags static %}
|
|
2
2
|
|
|
3
3
|
{% include "umap/messages.html" %}
|
|
4
4
|
<div id="map">
|
|
5
5
|
</div>
|
|
6
6
|
<!-- djlint:off -->
|
|
7
|
-
<script defer type="
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
<script defer type="module">
|
|
8
|
+
{% autoescape off %}
|
|
9
|
+
import Umap from '{% static "umap/js/modules/umap.js" %}'
|
|
10
|
+
{% endautoescape %}
|
|
11
|
+
U.MAP = new Umap("map", {{ map_settings|notag|safe }})
|
|
11
12
|
</script>
|
|
12
13
|
<!-- djlint:on -->
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{% extends "umap/content.html" %}
|
|
2
2
|
|
|
3
|
-
{% load i18n %}
|
|
3
|
+
{% load i18n static %}
|
|
4
4
|
|
|
5
5
|
{% block head_title %}
|
|
6
6
|
{{ SITE_NAME }} - {% trans "My Dashboard" %}
|
|
@@ -45,23 +45,24 @@
|
|
|
45
45
|
{% endblock maincontent %}
|
|
46
46
|
{% block bottom_js %}
|
|
47
47
|
{{ block.super }}
|
|
48
|
-
<script type="
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
<script type="module">
|
|
49
|
+
{% autoescape off %}
|
|
50
|
+
import Umap from '{% static "umap/js/modules/umap.js" %}'
|
|
51
|
+
{% endautoescape %}
|
|
52
|
+
const CACHE = {}
|
|
53
|
+
for (const mapOpener of document.querySelectorAll("button.map-opener")) {
|
|
54
|
+
mapOpener.addEventListener('click', (event) => {
|
|
55
|
+
const button = event.target.closest('button')
|
|
56
|
+
button.nextElementSibling.showModal()
|
|
57
|
+
const mapId = button.dataset.mapId
|
|
58
|
+
if (!document.querySelector(`#${mapId}_target`).children.length) {
|
|
59
|
+
const previewSettings = JSON.parse(document.getElementById(mapId).textContent)
|
|
60
|
+
const map = new Umap(`${mapId}_target`, previewSettings)
|
|
61
|
+
CACHE[mapId] = map
|
|
62
|
+
} else {
|
|
63
|
+
CACHE[mapId].invalidateSize()
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
}
|
|
66
67
|
</script>
|
|
67
68
|
{% endblock bottom_js %}
|
umap/tests/base.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import json
|
|
3
|
+
import uuid
|
|
4
|
+
from pathlib import Path
|
|
3
5
|
|
|
4
6
|
import factory
|
|
5
7
|
from django.contrib.auth import get_user_model
|
|
@@ -40,7 +42,7 @@ class LicenceFactory(factory.django.DjangoModelFactory):
|
|
|
40
42
|
|
|
41
43
|
class TileLayerFactory(factory.django.DjangoModelFactory):
|
|
42
44
|
name = "Test zoom layer"
|
|
43
|
-
url_template = "
|
|
45
|
+
url_template = "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
44
46
|
attribution = "Test layer attribution"
|
|
45
47
|
|
|
46
48
|
class Meta:
|
|
@@ -100,6 +102,7 @@ class MapFactory(factory.django.DjangoModelFactory):
|
|
|
100
102
|
|
|
101
103
|
licence = factory.SubFactory(LicenceFactory)
|
|
102
104
|
owner = factory.SubFactory(UserFactory)
|
|
105
|
+
share_status = Map.PUBLIC
|
|
103
106
|
|
|
104
107
|
@classmethod
|
|
105
108
|
def _adjust_kwargs(cls, **kwargs):
|
|
@@ -113,6 +116,7 @@ class MapFactory(factory.django.DjangoModelFactory):
|
|
|
113
116
|
|
|
114
117
|
|
|
115
118
|
class DataLayerFactory(factory.django.DjangoModelFactory):
|
|
119
|
+
uuid = factory.LazyFunction(lambda: uuid.uuid4())
|
|
116
120
|
map = factory.SubFactory(MapFactory)
|
|
117
121
|
name = "test datalayer"
|
|
118
122
|
description = "test description"
|
|
@@ -150,3 +154,9 @@ def login_required(response):
|
|
|
150
154
|
redirect_url = reverse("login")
|
|
151
155
|
assert j["login_required"] == redirect_url
|
|
152
156
|
return True
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def mock_tiles(route):
|
|
160
|
+
print("Intercepted route", route.request.url)
|
|
161
|
+
path = Path(__file__).parent / "fixtures/empty_tile.png"
|
|
162
|
+
route.fulfill(path=path)
|
|
Binary file
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
import subprocess
|
|
3
4
|
import time
|
|
4
5
|
from pathlib import Path
|
|
@@ -6,6 +7,8 @@ from pathlib import Path
|
|
|
6
7
|
import pytest
|
|
7
8
|
from playwright.sync_api import expect
|
|
8
9
|
|
|
10
|
+
from ..base import mock_tiles
|
|
11
|
+
|
|
9
12
|
|
|
10
13
|
@pytest.fixture(scope="session")
|
|
11
14
|
def browser_context_args(browser_context_args):
|
|
@@ -23,7 +26,7 @@ def set_timeout(context):
|
|
|
23
26
|
@pytest.fixture(autouse=True)
|
|
24
27
|
def mock_osm_tiles(page):
|
|
25
28
|
if not bool(os.environ.get("PWDEBUG", False)):
|
|
26
|
-
page.route("
|
|
29
|
+
page.route(re.compile(r".*tile\..*"), mock_tiles)
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
@pytest.fixture
|
|
@@ -76,8 +76,6 @@ def test_owner_permissions_form(map, datalayer, live_server, owner_session):
|
|
|
76
76
|
edit_permissions = owner_session.get_by_title("Update permissions and editors")
|
|
77
77
|
expect(edit_permissions).to_be_visible()
|
|
78
78
|
edit_permissions.click()
|
|
79
|
-
select = owner_session.locator(".umap-field-share_status select")
|
|
80
|
-
expect(select).to_be_hidden()
|
|
81
79
|
owner_field = owner_session.locator(".umap-field-owner")
|
|
82
80
|
expect(owner_field).to_be_hidden()
|
|
83
81
|
editors_field = owner_session.locator(".umap-field-editors input")
|
|
@@ -92,8 +90,15 @@ def test_owner_permissions_form(map, datalayer, live_server, owner_session):
|
|
|
92
90
|
".datalayer-permissions select[name='edit_status'] option:checked"
|
|
93
91
|
)
|
|
94
92
|
expect(option).to_have_text("Inherit")
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
expect(owner_session.locator(".umap-field-share_status select")).to_be_visible()
|
|
94
|
+
options = [
|
|
95
|
+
int(option.get_attribute("value"))
|
|
96
|
+
for option in owner_session.locator(
|
|
97
|
+
".umap-field-share_status select option"
|
|
98
|
+
).all()
|
|
99
|
+
]
|
|
100
|
+
assert options == [Map.DRAFT, Map.PUBLIC]
|
|
101
|
+
# This field should not be present in anonymous maps
|
|
97
102
|
expect(owner_session.locator(".umap-field-owner")).to_be_hidden()
|
|
98
103
|
|
|
99
104
|
|
|
@@ -135,15 +140,15 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
|
|
|
135
140
|
page.get_by_title("Manage layers").click()
|
|
136
141
|
page.get_by_title("Add a layer").click()
|
|
137
142
|
page.locator("input[name=name]").fill("Layer 1")
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
expect(
|
|
144
|
+
page.get_by_role("button", name="Visibility: Draft (private)")
|
|
145
|
+
).to_be_visible()
|
|
146
|
+
expect(page.get_by_role("button", name="Save", exact=True)).to_be_hidden()
|
|
140
147
|
with page.expect_response(re.compile(r".*/datalayer/create/.*")):
|
|
141
|
-
|
|
148
|
+
page.get_by_role("button", name="Save draft", exact=True).click()
|
|
142
149
|
edit_permissions = page.get_by_title("Update permissions and editors")
|
|
143
150
|
expect(edit_permissions).to_be_visible()
|
|
144
151
|
edit_permissions.click()
|
|
145
|
-
select = page.locator(".umap-field-share_status select")
|
|
146
|
-
expect(select).to_be_hidden()
|
|
147
152
|
owner_field = page.locator(".umap-field-owner")
|
|
148
153
|
expect(owner_field).to_be_hidden()
|
|
149
154
|
editors_field = page.locator(".umap-field-editors input")
|
|
@@ -157,6 +162,9 @@ def test_can_change_perms_after_create(tilelayer, live_server, page):
|
|
|
157
162
|
)
|
|
158
163
|
expect(option).to_have_text("Inherit")
|
|
159
164
|
expect(page.get_by_label("Secret edit link:")).to_be_visible()
|
|
165
|
+
page.locator('select[name="share_status"]').select_option("1")
|
|
166
|
+
expect(page.get_by_role("button", name="Save draft", exact=True)).to_be_hidden()
|
|
167
|
+
expect(page.get_by_role("button", name="Save", exact=True)).to_be_visible()
|
|
160
168
|
|
|
161
169
|
|
|
162
170
|
def test_alert_message_after_create(
|
|
@@ -232,7 +240,7 @@ def test_anonymous_owner_can_delete_the_map(anonymap, live_server, owner_session
|
|
|
232
240
|
owner_session.get_by_role("button", name="Delete").click()
|
|
233
241
|
with owner_session.expect_response(re.compile(r".*/update/delete/.*")):
|
|
234
242
|
owner_session.get_by_role("button", name="OK").click()
|
|
235
|
-
assert
|
|
243
|
+
assert Map.objects.get(pk=anonymap.pk).share_status == Map.DELETED
|
|
236
244
|
|
|
237
245
|
|
|
238
246
|
def test_non_owner_cannot_see_delete_button(anonymap, live_server, page):
|
|
@@ -15,7 +15,12 @@ DATALAYER_DATA = {
|
|
|
15
15
|
"features": [
|
|
16
16
|
{
|
|
17
17
|
"type": "Feature",
|
|
18
|
-
"properties": {
|
|
18
|
+
"properties": {
|
|
19
|
+
"name": "one point in france",
|
|
20
|
+
"foo": "point",
|
|
21
|
+
"bar": "one",
|
|
22
|
+
"label": "this is label one",
|
|
23
|
+
},
|
|
19
24
|
"geometry": {"type": "Point", "coordinates": [3.339844, 46.920255]},
|
|
20
25
|
},
|
|
21
26
|
{
|
|
@@ -24,6 +29,7 @@ DATALAYER_DATA = {
|
|
|
24
29
|
"name": "one polygon in greenland",
|
|
25
30
|
"foo": "polygon",
|
|
26
31
|
"bar": "two",
|
|
32
|
+
"label": "this is label two",
|
|
27
33
|
},
|
|
28
34
|
"geometry": {
|
|
29
35
|
"type": "Polygon",
|
|
@@ -44,6 +50,7 @@ DATALAYER_DATA = {
|
|
|
44
50
|
"name": "one line in new zeland",
|
|
45
51
|
"foo": "line",
|
|
46
52
|
"bar": "three",
|
|
53
|
+
"label": "this is label three",
|
|
47
54
|
},
|
|
48
55
|
"geometry": {
|
|
49
56
|
"type": "LineString",
|
|
@@ -476,3 +483,11 @@ def test_main_toolbox_toggle_all_layers(live_server, map, page):
|
|
|
476
483
|
# Should hidden again all layers
|
|
477
484
|
expect(page.locator(".datalayer.off")).to_have_count(3)
|
|
478
485
|
expect(markers).to_have_count(0)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
def test_honour_the_label_fields_settings(live_server, map, page, bootstrap, settings):
|
|
489
|
+
settings.UMAP_LABEL_KEYS = ["label", "name"]
|
|
490
|
+
page.goto(f"{live_server.url}{map.get_absolute_url()}")
|
|
491
|
+
expect(page.locator(".panel").get_by_text("this is label one")).to_be_visible()
|
|
492
|
+
expect(page.locator(".panel").get_by_text("this is label two")).to_be_visible()
|
|
493
|
+
expect(page.locator(".panel").get_by_text("this is label three")).to_be_visible()
|
|
@@ -22,7 +22,7 @@ def test_owner_can_delete_map_after_confirmation(map, live_server, login):
|
|
|
22
22
|
with page.expect_navigation():
|
|
23
23
|
delete_button.click()
|
|
24
24
|
assert dialog_shown
|
|
25
|
-
assert Map.objects.
|
|
25
|
+
assert Map.objects.get(pk=map.pk).share_status == Map.DELETED
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def test_dashboard_map_preview(map, live_server, datalayer, login):
|