umap-project 2.7.3__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/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 +32 -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 +22 -2
- 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 +617 -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 +101 -74
- umap/static/umap/js/modules/data/layer.js +157 -137
- 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 +71 -39
- 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/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 +10 -9
- umap/static/umap/js/modules/rendering/template.js +35 -12
- umap/static/umap/js/modules/rendering/ui.js +57 -12
- 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 +5 -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/panel.js +10 -9
- umap/static/umap/js/modules/umap.js +1668 -0
- umap/static/umap/js/modules/urls.js +2 -2
- umap/static/umap/js/modules/utils.js +20 -6
- umap/static/umap/js/umap.controls.js +74 -301
- umap/static/umap/js/umap.core.js +29 -50
- umap/static/umap/js/umap.forms.js +34 -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 +12 -9
- umap/static/umap/locale/en.json +12 -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 +12 -9
- umap/static/umap/locale/fr.json +12 -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 +5 -364
- umap/static/umap/unittests/URLs.js +15 -15
- umap/static/umap/unittests/utils.js +23 -1
- umap/static/umap/vars.css +2 -0
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +5 -1
- umap/storage.py +152 -0
- umap/templates/registration/login.html +7 -6
- umap/templates/umap/css.html +3 -0
- umap/templates/umap/js.html +1 -2
- umap/templates/umap/map_init.html +4 -5
- umap/templates/umap/user_dashboard.html +18 -19
- umap/tests/base.py +5 -1
- umap/tests/integration/conftest.py +2 -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 +18 -7
- umap/tests/integration/test_import.py +8 -5
- 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_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_views.py +53 -0
- umap/urls.py +3 -3
- umap/views.py +107 -76
- {umap_project-2.7.3.dist-info → umap_project-2.8.0a0.dist-info}/METADATA +16 -13
- {umap_project-2.7.3.dist-info → umap_project-2.8.0a0.dist-info}/RECORD +276 -262
- 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_project-2.7.3.dist-info → umap_project-2.8.0a0.dist-info}/WHEEL +0 -0
- {umap_project-2.7.3.dist-info → umap_project-2.8.0a0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.7.3.dist-info → umap_project-2.8.0a0.dist-info}/licenses/LICENSE +0 -0
umap/models.py
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import operator
|
|
3
|
-
import os
|
|
4
|
-
import shutil
|
|
5
|
-
import time
|
|
6
2
|
import uuid
|
|
7
|
-
from pathlib import Path
|
|
8
3
|
|
|
9
4
|
from django.conf import settings
|
|
10
5
|
from django.contrib.auth.models import User
|
|
11
6
|
from django.contrib.gis.db import models
|
|
12
7
|
from django.core.files.base import File
|
|
8
|
+
from django.core.files.storage import storages
|
|
13
9
|
from django.core.signing import Signer
|
|
14
|
-
from django.template.defaultfilters import slugify
|
|
15
10
|
from django.urls import reverse
|
|
16
11
|
from django.utils.functional import classproperty
|
|
17
12
|
from django.utils.translation import gettext_lazy as _
|
|
@@ -38,13 +33,22 @@ def get_user_stars_url(self):
|
|
|
38
33
|
return reverse("user_stars", kwargs={"identifier": identifier})
|
|
39
34
|
|
|
40
35
|
|
|
36
|
+
def get_user_metadata(self):
|
|
37
|
+
return {
|
|
38
|
+
"id": self.pk,
|
|
39
|
+
"name": str(self),
|
|
40
|
+
"url": self.get_url(),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
41
44
|
User.add_to_class("__str__", display_name)
|
|
42
45
|
User.add_to_class("get_url", get_user_url)
|
|
43
46
|
User.add_to_class("get_stars_url", get_user_stars_url)
|
|
47
|
+
User.add_to_class("get_metadata", get_user_metadata)
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
def get_default_share_status():
|
|
47
|
-
return settings.UMAP_DEFAULT_SHARE_STATUS or Map.
|
|
51
|
+
return settings.UMAP_DEFAULT_SHARE_STATUS or Map.DRAFT
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
def get_default_edit_status():
|
|
@@ -161,20 +165,30 @@ class Map(NamedModel):
|
|
|
161
165
|
ANONYMOUS = 1
|
|
162
166
|
COLLABORATORS = 2
|
|
163
167
|
OWNER = 3
|
|
168
|
+
DRAFT = 0
|
|
164
169
|
PUBLIC = 1
|
|
165
170
|
OPEN = 2
|
|
166
171
|
PRIVATE = 3
|
|
167
172
|
BLOCKED = 9
|
|
173
|
+
DELETED = 99
|
|
174
|
+
ANONYMOUS_EDIT_STATUS = (
|
|
175
|
+
(OWNER, _("Only editable with secret edit link")),
|
|
176
|
+
(ANONYMOUS, _("Everyone can edit")),
|
|
177
|
+
)
|
|
168
178
|
EDIT_STATUS = (
|
|
169
179
|
(ANONYMOUS, _("Everyone")),
|
|
170
180
|
(COLLABORATORS, _("Editors and team only")),
|
|
171
181
|
(OWNER, _("Owner only")),
|
|
172
182
|
)
|
|
173
|
-
|
|
183
|
+
ANONYMOUS_SHARE_STATUS = (
|
|
184
|
+
(DRAFT, _("Draft (private)")),
|
|
174
185
|
(PUBLIC, _("Everyone (public)")),
|
|
186
|
+
)
|
|
187
|
+
SHARE_STATUS = ANONYMOUS_SHARE_STATUS + (
|
|
175
188
|
(OPEN, _("Anyone with link")),
|
|
176
189
|
(PRIVATE, _("Editors and team only")),
|
|
177
190
|
(BLOCKED, _("Blocked")),
|
|
191
|
+
(DELETED, _("Deleted")),
|
|
178
192
|
)
|
|
179
193
|
slug = models.SlugField(db_index=True)
|
|
180
194
|
center = models.PointField(geography=True, verbose_name=_("center"))
|
|
@@ -250,13 +264,17 @@ class Map(NamedModel):
|
|
|
250
264
|
"hash": False,
|
|
251
265
|
"scrollWheelZoom": False,
|
|
252
266
|
"noControl": True,
|
|
253
|
-
"
|
|
267
|
+
"id": self.pk,
|
|
254
268
|
"schema": self.extra_schema,
|
|
255
269
|
"slideshow": {},
|
|
256
270
|
}
|
|
257
271
|
)
|
|
258
272
|
return map_settings
|
|
259
273
|
|
|
274
|
+
def move_to_trash(self):
|
|
275
|
+
self.share_status = Map.DELETED
|
|
276
|
+
self.save()
|
|
277
|
+
|
|
260
278
|
def delete(self, **kwargs):
|
|
261
279
|
# Explicitely call datalayers.delete, so we can deal with removing files
|
|
262
280
|
# (the cascade delete would not call the model delete method)
|
|
@@ -270,7 +288,7 @@ class Map(NamedModel):
|
|
|
270
288
|
umapjson["uri"] = request.build_absolute_uri(self.get_absolute_url())
|
|
271
289
|
datalayers = []
|
|
272
290
|
for datalayer in self.datalayer_set.all():
|
|
273
|
-
with
|
|
291
|
+
with datalayer.geojson.open("rb") as f:
|
|
274
292
|
layer = json.loads(f.read())
|
|
275
293
|
if datalayer.settings:
|
|
276
294
|
layer["_umap_options"] = datalayer.settings
|
|
@@ -352,19 +370,20 @@ class Map(NamedModel):
|
|
|
352
370
|
return can
|
|
353
371
|
|
|
354
372
|
def can_view(self, request):
|
|
355
|
-
if self.share_status
|
|
373
|
+
if self.share_status in [Map.BLOCKED, Map.DELETED]:
|
|
356
374
|
can = False
|
|
357
|
-
elif self.
|
|
358
|
-
can = True
|
|
359
|
-
elif self.share_status in [self.PUBLIC, self.OPEN]:
|
|
375
|
+
elif self.share_status in [Map.PUBLIC, Map.OPEN]:
|
|
360
376
|
can = True
|
|
377
|
+
elif self.owner is None:
|
|
378
|
+
can = settings.UMAP_ALLOW_ANONYMOUS and self.is_anonymous_owner(request)
|
|
361
379
|
elif not request.user.is_authenticated:
|
|
362
380
|
can = False
|
|
363
381
|
elif request.user == self.owner:
|
|
364
382
|
can = True
|
|
365
383
|
else:
|
|
384
|
+
restricted = self.share_status in [Map.PRIVATE, Map.DRAFT]
|
|
366
385
|
can = not (
|
|
367
|
-
|
|
386
|
+
restricted
|
|
368
387
|
and request.user not in self.editors.all()
|
|
369
388
|
and self.team not in request.user.teams.all()
|
|
370
389
|
)
|
|
@@ -423,10 +442,11 @@ class Pictogram(NamedModel):
|
|
|
423
442
|
# Must be out of Datalayer for Django migration to run, because of python 2
|
|
424
443
|
# serialize limitations.
|
|
425
444
|
def upload_to(instance, filename):
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
445
|
+
return instance.geojson.storage.make_filename(instance)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def set_storage():
|
|
449
|
+
return storages["data"]
|
|
430
450
|
|
|
431
451
|
|
|
432
452
|
class DataLayer(NamedModel):
|
|
@@ -444,13 +464,18 @@ class DataLayer(NamedModel):
|
|
|
444
464
|
(COLLABORATORS, _("Editors and team only")),
|
|
445
465
|
(OWNER, _("Owner only")),
|
|
446
466
|
)
|
|
447
|
-
|
|
448
|
-
|
|
467
|
+
ANONYMOUS_EDIT_STATUS = (
|
|
468
|
+
(INHERIT, _("Inherit")),
|
|
469
|
+
(OWNER, _("Only editable with secret edit link")),
|
|
470
|
+
(ANONYMOUS, _("Everyone can edit")),
|
|
449
471
|
)
|
|
472
|
+
uuid = models.UUIDField(unique=True, primary_key=True, editable=False)
|
|
450
473
|
old_id = models.IntegerField(null=True, blank=True)
|
|
451
474
|
map = models.ForeignKey(Map, on_delete=models.CASCADE)
|
|
452
475
|
description = models.TextField(blank=True, null=True, verbose_name=_("description"))
|
|
453
|
-
geojson = models.FileField(
|
|
476
|
+
geojson = models.FileField(
|
|
477
|
+
upload_to=upload_to, blank=True, null=True, storage=set_storage
|
|
478
|
+
)
|
|
454
479
|
display_on_load = models.BooleanField(
|
|
455
480
|
default=False,
|
|
456
481
|
verbose_name=_("display on load"),
|
|
@@ -469,50 +494,16 @@ class DataLayer(NamedModel):
|
|
|
469
494
|
class Meta:
|
|
470
495
|
ordering = ("rank",)
|
|
471
496
|
|
|
472
|
-
def save(self,
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if is_new:
|
|
479
|
-
force_insert, force_update = False, True
|
|
480
|
-
filename = self.upload_to()
|
|
481
|
-
old_name = self.geojson.name
|
|
482
|
-
new_name = self.geojson.storage.save(filename, self.geojson)
|
|
483
|
-
self.geojson.storage.delete(old_name)
|
|
484
|
-
self.geojson.name = new_name
|
|
485
|
-
super(DataLayer, self).save(
|
|
486
|
-
force_insert=force_insert, force_update=force_update, **kwargs
|
|
487
|
-
)
|
|
488
|
-
self.purge_gzip()
|
|
489
|
-
self.purge_old_versions()
|
|
497
|
+
def save(self, **kwargs):
|
|
498
|
+
super(DataLayer, self).save(**kwargs)
|
|
499
|
+
self.geojson.storage.onDatalayerSave(self)
|
|
500
|
+
if hasattr(self, "_reference_version"):
|
|
501
|
+
del self._reference_version
|
|
490
502
|
|
|
491
503
|
def delete(self, **kwargs):
|
|
492
|
-
self.
|
|
493
|
-
self.to_purgatory()
|
|
504
|
+
self.geojson.storage.onDatalayerDelete(self)
|
|
494
505
|
return super().delete(**kwargs)
|
|
495
506
|
|
|
496
|
-
def to_purgatory(self):
|
|
497
|
-
dest = Path(settings.UMAP_PURGATORY_ROOT)
|
|
498
|
-
dest.mkdir(parents=True, exist_ok=True)
|
|
499
|
-
src = Path(self.geojson.storage.location) / self.storage_root()
|
|
500
|
-
for version in self.versions:
|
|
501
|
-
name = version["name"]
|
|
502
|
-
shutil.move(src / name, dest / f"{self.map.pk}_{name}")
|
|
503
|
-
|
|
504
|
-
def upload_to(self):
|
|
505
|
-
root = self.storage_root()
|
|
506
|
-
name = "%s_%s.geojson" % (self.pk, int(time.time() * 1000))
|
|
507
|
-
return os.path.join(root, name)
|
|
508
|
-
|
|
509
|
-
def storage_root(self):
|
|
510
|
-
path = ["datalayer", str(self.map.pk)[-1]]
|
|
511
|
-
if len(str(self.map.pk)) > 1:
|
|
512
|
-
path.append(str(self.map.pk)[-2])
|
|
513
|
-
path.append(str(self.map.pk))
|
|
514
|
-
return os.path.join(*path)
|
|
515
|
-
|
|
516
507
|
def metadata(self, request=None):
|
|
517
508
|
# Retrocompat: minimal settings for maps not saved after settings property
|
|
518
509
|
# has been introduced
|
|
@@ -525,73 +516,34 @@ class DataLayer(NamedModel):
|
|
|
525
516
|
obj["id"] = self.pk
|
|
526
517
|
obj["permissions"] = {"edit_status": self.edit_status}
|
|
527
518
|
obj["editMode"] = "advanced" if self.can_edit(request) else "disabled"
|
|
519
|
+
obj["_referenceVersion"] = self.reference_version
|
|
528
520
|
return obj
|
|
529
521
|
|
|
530
522
|
def clone(self, map_inst=None):
|
|
531
523
|
new = self.__class__.objects.get(pk=self.pk)
|
|
532
524
|
new._state.adding = True
|
|
533
|
-
new.pk =
|
|
525
|
+
new.pk = uuid.uuid4()
|
|
534
526
|
if map_inst:
|
|
535
527
|
new.map = map_inst
|
|
536
|
-
new.geojson = File(new.geojson.file.file)
|
|
528
|
+
new.geojson = File(new.geojson.file.file, name="tmpname")
|
|
537
529
|
new.save()
|
|
538
530
|
return new
|
|
539
531
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
if self
|
|
543
|
-
|
|
544
|
-
return
|
|
545
|
-
|
|
546
|
-
def version_metadata(self, name):
|
|
547
|
-
els = name.split(".")[0].split("_")
|
|
548
|
-
return {
|
|
549
|
-
"name": name,
|
|
550
|
-
"at": els[1],
|
|
551
|
-
"size": self.geojson.storage.size(self.get_version_path(name)),
|
|
552
|
-
}
|
|
532
|
+
@property
|
|
533
|
+
def reference_version(self):
|
|
534
|
+
if not hasattr(self, "_reference_version"):
|
|
535
|
+
self._reference_version = self.geojson.storage.get_reference_version(self)
|
|
536
|
+
return self._reference_version
|
|
553
537
|
|
|
554
538
|
@property
|
|
555
539
|
def versions(self):
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
def get_version(self, name):
|
|
564
|
-
path = self.get_version_path(name)
|
|
565
|
-
with self.geojson.storage.open(path, "r") as f:
|
|
566
|
-
return f.read()
|
|
567
|
-
|
|
568
|
-
def get_version_path(self, name):
|
|
569
|
-
return "{root}/{name}".format(root=self.storage_root(), name=name)
|
|
570
|
-
|
|
571
|
-
def purge_old_versions(self):
|
|
572
|
-
root = self.storage_root()
|
|
573
|
-
versions = self.versions[settings.UMAP_KEEP_VERSIONS :]
|
|
574
|
-
for version in versions:
|
|
575
|
-
name = version["name"]
|
|
576
|
-
# Should not be in the list, but ensure to not delete the file
|
|
577
|
-
# currently used in database
|
|
578
|
-
if self.geojson.name.endswith(name):
|
|
579
|
-
continue
|
|
580
|
-
try:
|
|
581
|
-
self.geojson.storage.delete(os.path.join(root, name))
|
|
582
|
-
except FileNotFoundError:
|
|
583
|
-
pass
|
|
584
|
-
|
|
585
|
-
def purge_gzip(self):
|
|
586
|
-
root = self.storage_root()
|
|
587
|
-
names = self.geojson.storage.listdir(root)[1]
|
|
588
|
-
prefixes = [f"{self.pk}_"]
|
|
589
|
-
if self.old_id:
|
|
590
|
-
prefixes.append(f"{self.old_id}_")
|
|
591
|
-
prefixes = tuple(prefixes)
|
|
592
|
-
for name in names:
|
|
593
|
-
if name.startswith(prefixes) and name.endswith(".gz"):
|
|
594
|
-
self.geojson.storage.delete(os.path.join(root, name))
|
|
540
|
+
return self.geojson.storage.list_versions(self)
|
|
541
|
+
|
|
542
|
+
def get_version(self, ref):
|
|
543
|
+
return self.geojson.storage.get_version(ref, self)
|
|
544
|
+
|
|
545
|
+
def get_version_path(self, ref):
|
|
546
|
+
return self.geojson.storage.get_version_path(ref, self)
|
|
595
547
|
|
|
596
548
|
def can_edit(self, request=None):
|
|
597
549
|
"""
|
umap/settings/base.py
CHANGED
|
@@ -175,10 +175,25 @@ STORAGES = {
|
|
|
175
175
|
"default": {
|
|
176
176
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
|
177
177
|
},
|
|
178
|
+
"data": {
|
|
179
|
+
"BACKEND": "umap.storage.UmapFileSystem",
|
|
180
|
+
},
|
|
178
181
|
"staticfiles": {
|
|
179
182
|
"BACKEND": "umap.storage.UmapManifestStaticFilesStorage",
|
|
180
183
|
},
|
|
181
184
|
}
|
|
185
|
+
# Add application/json and application/geo+json to default django-storages setting
|
|
186
|
+
# in order to gzip our datalayers geojson files.
|
|
187
|
+
GZIP_CONTENT_TYPES = [
|
|
188
|
+
"text/css",
|
|
189
|
+
"text/javascript",
|
|
190
|
+
"application/javascript",
|
|
191
|
+
"application/x-javascript",
|
|
192
|
+
"image/svg+xml",
|
|
193
|
+
"application/json",
|
|
194
|
+
"application/geo+json",
|
|
195
|
+
]
|
|
196
|
+
|
|
182
197
|
|
|
183
198
|
# =============================================================================
|
|
184
199
|
# Templates
|
|
@@ -260,14 +275,19 @@ UMAP_MAPS_PER_PAGE_OWNER = 10
|
|
|
260
275
|
UMAP_SEARCH_CONFIGURATION = "simple"
|
|
261
276
|
UMAP_HELP_URL = "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help"
|
|
262
277
|
USER_MAPS_URL = "user_maps"
|
|
263
|
-
DATABASES = {
|
|
278
|
+
DATABASES = {
|
|
279
|
+
"default": env.db(
|
|
280
|
+
default="postgis://localhost:5432/umap",
|
|
281
|
+
engine="django.contrib.gis.db.backends.postgis",
|
|
282
|
+
)
|
|
283
|
+
}
|
|
264
284
|
UMAP_DEFAULT_SHARE_STATUS = None
|
|
265
285
|
UMAP_DEFAULT_EDIT_STATUS = None
|
|
266
286
|
UMAP_DEFAULT_FEATURES_HAVE_OWNERS = False
|
|
267
287
|
UMAP_HOME_FEED = "latest"
|
|
268
288
|
UMAP_IMPORTERS = {}
|
|
269
289
|
UMAP_HOST_INFOS = {}
|
|
270
|
-
|
|
290
|
+
UMAP_LABEL_KEYS = ["name", "title"]
|
|
271
291
|
|
|
272
292
|
UMAP_READONLY = env("UMAP_READONLY", default=False)
|
|
273
293
|
UMAP_GZIP = True
|