umap-project 1.14.0a5__py3-none-any.whl → 2.0.0a1__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.

Potentially problematic release.


This version of umap-project might be problematic. Click here for more details.

Files changed (216) hide show
  1. umap/__init__.py +1 -1
  2. umap/decorators.py +0 -14
  3. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/br/LC_MESSAGES/django.po +137 -85
  5. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/cs_CZ/LC_MESSAGES/django.po +136 -84
  7. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/el/LC_MESSAGES/django.po +136 -84
  9. umap/locale/en/LC_MESSAGES/django.po +128 -88
  10. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/es/LC_MESSAGES/django.po +136 -84
  12. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/fr/LC_MESSAGES/django.po +131 -91
  14. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/hu/LC_MESSAGES/django.po +137 -85
  16. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  17. umap/locale/it/LC_MESSAGES/django.po +136 -84
  18. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  19. umap/locale/ms/LC_MESSAGES/django.po +136 -84
  20. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  21. umap/locale/pl/LC_MESSAGES/django.po +136 -84
  22. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/sv/LC_MESSAGES/django.po +135 -83
  24. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  25. umap/locale/zh_TW/LC_MESSAGES/django.po +143 -91
  26. umap/models.py +23 -1
  27. umap/settings/__init__.py +1 -4
  28. umap/settings/base.py +1 -0
  29. umap/static/umap/base.css +5 -0
  30. umap/static/umap/content.css +185 -13
  31. umap/static/umap/favicons/icon.svg +2 -2
  32. umap/static/umap/img/edit.svg +3 -3
  33. umap/static/umap/img/icon-delete.svg +4 -0
  34. umap/static/umap/img/icon-download.svg +13 -0
  35. umap/static/umap/img/icon-duplicate.svg +5 -0
  36. umap/static/umap/img/icon-edit.svg +12 -0
  37. umap/static/umap/img/icon-share.svg +11 -0
  38. umap/static/umap/img/icon-view.svg +12 -0
  39. umap/static/umap/img/logo.svg +2 -2
  40. umap/static/umap/img/logo_small.svg +2 -2
  41. umap/static/umap/img/marker.svg +4 -0
  42. umap/static/umap/img/opensource.svg +2 -2
  43. umap/static/umap/img/osm.svg +2 -2
  44. umap/static/umap/js/components/fragment.js +1 -1
  45. umap/static/umap/js/modules/browser.js +159 -0
  46. umap/static/umap/js/modules/global.js +3 -1
  47. umap/static/umap/js/modules/request.js +155 -0
  48. umap/static/umap/js/umap.autocomplete.js +28 -38
  49. umap/static/umap/js/umap.controls.js +73 -58
  50. umap/static/umap/js/umap.core.js +4 -9
  51. umap/static/umap/js/umap.datalayer.permissions.js +13 -12
  52. umap/static/umap/js/umap.features.js +51 -49
  53. umap/static/umap/js/umap.forms.js +19 -19
  54. umap/static/umap/js/umap.icon.js +17 -17
  55. umap/static/umap/js/umap.importer.js +2 -1
  56. umap/static/umap/js/umap.js +242 -291
  57. umap/static/umap/js/umap.layer.js +173 -141
  58. umap/static/umap/js/umap.permissions.js +24 -25
  59. umap/static/umap/js/umap.popup.js +14 -14
  60. umap/static/umap/js/umap.share.js +4 -4
  61. umap/static/umap/js/umap.slideshow.js +4 -4
  62. umap/static/umap/js/umap.tableeditor.js +2 -2
  63. umap/static/umap/js/umap.ui.js +1 -1
  64. umap/static/umap/locale/am_ET.js +1 -11
  65. umap/static/umap/locale/am_ET.json +1 -11
  66. umap/static/umap/locale/ar.js +1 -11
  67. umap/static/umap/locale/ar.json +1 -11
  68. umap/static/umap/locale/ast.js +1 -11
  69. umap/static/umap/locale/ast.json +1 -11
  70. umap/static/umap/locale/bg.js +1 -11
  71. umap/static/umap/locale/bg.json +1 -11
  72. umap/static/umap/locale/br.js +1 -11
  73. umap/static/umap/locale/br.json +1 -11
  74. umap/static/umap/locale/ca.js +1 -11
  75. umap/static/umap/locale/ca.json +1 -11
  76. umap/static/umap/locale/cs_CZ.js +1 -11
  77. umap/static/umap/locale/cs_CZ.json +1 -11
  78. umap/static/umap/locale/da.js +1 -11
  79. umap/static/umap/locale/da.json +1 -11
  80. umap/static/umap/locale/de.js +1 -11
  81. umap/static/umap/locale/de.json +1 -11
  82. umap/static/umap/locale/el.js +1 -11
  83. umap/static/umap/locale/el.json +1 -11
  84. umap/static/umap/locale/en.js +1 -11
  85. umap/static/umap/locale/en.json +1 -11
  86. umap/static/umap/locale/en_US.json +1 -11
  87. umap/static/umap/locale/es.js +1 -11
  88. umap/static/umap/locale/es.json +1 -11
  89. umap/static/umap/locale/et.js +1 -11
  90. umap/static/umap/locale/et.json +1 -11
  91. umap/static/umap/locale/fa_IR.js +6 -16
  92. umap/static/umap/locale/fa_IR.json +6 -16
  93. umap/static/umap/locale/fi.js +1 -11
  94. umap/static/umap/locale/fi.json +1 -11
  95. umap/static/umap/locale/fr.js +1 -11
  96. umap/static/umap/locale/fr.json +1 -11
  97. umap/static/umap/locale/gl.js +1 -11
  98. umap/static/umap/locale/gl.json +1 -11
  99. umap/static/umap/locale/he.js +1 -11
  100. umap/static/umap/locale/he.json +1 -11
  101. umap/static/umap/locale/hr.js +1 -11
  102. umap/static/umap/locale/hr.json +1 -11
  103. umap/static/umap/locale/hu.js +1 -11
  104. umap/static/umap/locale/hu.json +1 -11
  105. umap/static/umap/locale/id.js +1 -11
  106. umap/static/umap/locale/id.json +1 -11
  107. umap/static/umap/locale/is.js +1 -11
  108. umap/static/umap/locale/is.json +1 -11
  109. umap/static/umap/locale/it.js +1 -11
  110. umap/static/umap/locale/it.json +1 -11
  111. umap/static/umap/locale/ja.js +1 -11
  112. umap/static/umap/locale/ja.json +1 -11
  113. umap/static/umap/locale/ko.js +1 -11
  114. umap/static/umap/locale/ko.json +1 -11
  115. umap/static/umap/locale/lt.js +1 -11
  116. umap/static/umap/locale/lt.json +1 -11
  117. umap/static/umap/locale/ms.js +1 -11
  118. umap/static/umap/locale/ms.json +1 -11
  119. umap/static/umap/locale/nl.js +1 -11
  120. umap/static/umap/locale/nl.json +1 -11
  121. umap/static/umap/locale/no.js +1 -11
  122. umap/static/umap/locale/no.json +1 -11
  123. umap/static/umap/locale/pl.js +1 -11
  124. umap/static/umap/locale/pl.json +1 -11
  125. umap/static/umap/locale/pl_PL.json +1 -11
  126. umap/static/umap/locale/pt.js +1 -11
  127. umap/static/umap/locale/pt.json +1 -11
  128. umap/static/umap/locale/pt_BR.js +1 -11
  129. umap/static/umap/locale/pt_BR.json +1 -11
  130. umap/static/umap/locale/pt_PT.js +1 -11
  131. umap/static/umap/locale/pt_PT.json +1 -11
  132. umap/static/umap/locale/ro.js +1 -11
  133. umap/static/umap/locale/ro.json +1 -11
  134. umap/static/umap/locale/ru.js +1 -11
  135. umap/static/umap/locale/ru.json +1 -11
  136. umap/static/umap/locale/sk_SK.js +1 -11
  137. umap/static/umap/locale/sk_SK.json +1 -11
  138. umap/static/umap/locale/sl.js +1 -11
  139. umap/static/umap/locale/sl.json +1 -11
  140. umap/static/umap/locale/sr.js +1 -11
  141. umap/static/umap/locale/sr.json +1 -11
  142. umap/static/umap/locale/sv.js +1 -11
  143. umap/static/umap/locale/sv.json +1 -11
  144. umap/static/umap/locale/th_TH.js +1 -11
  145. umap/static/umap/locale/th_TH.json +1 -11
  146. umap/static/umap/locale/tr.js +1 -11
  147. umap/static/umap/locale/tr.json +1 -11
  148. umap/static/umap/locale/uk_UA.js +1 -11
  149. umap/static/umap/locale/uk_UA.json +1 -11
  150. umap/static/umap/locale/vi.js +1 -11
  151. umap/static/umap/locale/vi.json +1 -11
  152. umap/static/umap/locale/vi_VN.json +1 -11
  153. umap/static/umap/locale/zh.js +1 -11
  154. umap/static/umap/locale/zh.json +1 -11
  155. umap/static/umap/locale/zh_CN.json +1 -11
  156. umap/static/umap/locale/zh_TW.Big5.json +1 -11
  157. umap/static/umap/locale/zh_TW.js +17 -27
  158. umap/static/umap/locale/zh_TW.json +17 -27
  159. umap/static/umap/map.css +2 -2
  160. umap/static/umap/nav.css +2 -1
  161. umap/static/umap/test/.eslintrc +0 -1
  162. umap/static/umap/test/Choropleth.js +29 -27
  163. umap/static/umap/test/DataLayer.js +207 -239
  164. umap/static/umap/test/Feature.js +33 -58
  165. umap/static/umap/test/Map.Export.js +11 -11
  166. umap/static/umap/test/Map.js +66 -67
  167. umap/static/umap/test/Marker.js +36 -32
  168. umap/static/umap/test/Polygon.js +95 -95
  169. umap/static/umap/test/Polyline.js +31 -31
  170. umap/static/umap/test/TableEditor.js +29 -25
  171. umap/static/umap/test/_pre.js +2 -7
  172. umap/static/umap/test/index.html +4 -4
  173. umap/storage.py +2 -0
  174. umap/templates/auth/user_form.html +3 -2
  175. umap/templates/base.html +1 -0
  176. umap/templates/registration/login.html +51 -36
  177. umap/templates/umap/about_summary.html +1 -1
  178. umap/templates/umap/branding.html +3 -0
  179. umap/templates/umap/content.html +15 -39
  180. umap/templates/umap/header.html +0 -0
  181. umap/templates/umap/home.html +4 -2
  182. umap/templates/umap/js.html +0 -2
  183. umap/templates/umap/map_detail.html +9 -0
  184. umap/templates/umap/map_init.html +1 -1
  185. umap/templates/umap/map_messages.html +4 -2
  186. umap/templates/umap/map_table.html +130 -69
  187. umap/templates/umap/navigation.html +2 -4
  188. umap/templates/umap/user_dashboard.html +29 -6
  189. umap/tests/base.py +1 -1
  190. umap/tests/integration/conftest.py +18 -0
  191. umap/tests/integration/test_anonymous_owned_map.py +6 -3
  192. umap/tests/integration/test_browser.py +166 -6
  193. umap/tests/integration/test_collaborative_editing.py +23 -5
  194. umap/tests/integration/test_dashboard.py +17 -0
  195. umap/tests/integration/test_edit_datalayer.py +4 -3
  196. umap/tests/integration/test_export_map.py +1 -1
  197. umap/tests/integration/test_import.py +9 -4
  198. umap/tests/integration/test_map.py +64 -0
  199. umap/tests/integration/test_map_preview.py +75 -0
  200. umap/tests/integration/test_owned_map.py +11 -25
  201. umap/tests/integration/test_picto.py +3 -3
  202. umap/tests/integration/test_querystring.py +52 -0
  203. umap/tests/integration/test_share.py +22 -0
  204. umap/tests/test_map_views.py +157 -14
  205. umap/tests/test_views.py +50 -11
  206. umap/urls.py +6 -12
  207. umap/views.py +170 -47
  208. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a1.dist-info}/METADATA +13 -15
  209. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a1.dist-info}/RECORD +212 -200
  210. umap/static/umap/js/umap.browser.js +0 -148
  211. umap/static/umap/js/umap.xhr.js +0 -304
  212. umap/static/umap/test/Controls.js +0 -100
  213. umap/static/umap/test/Map.Init.js +0 -46
  214. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a1.dist-info}/WHEEL +0 -0
  215. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a1.dist-info}/entry_points.txt +0 -0
  216. {umap_project-1.14.0a5.dist-info → umap_project-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
umap/views.py CHANGED
@@ -1,8 +1,10 @@
1
+ import io
1
2
  import json
2
3
  import mimetypes
3
4
  import os
4
5
  import re
5
6
  import socket
7
+ import zipfile
6
8
  from datetime import datetime, timedelta
7
9
  from http.client import InvalidURL
8
10
  from io import BytesIO
@@ -18,20 +20,23 @@ from django.contrib.auth import logout as do_logout
18
20
  from django.contrib.gis.measure import D
19
21
  from django.contrib.postgres.search import SearchQuery, SearchVector
20
22
  from django.contrib.staticfiles.storage import staticfiles_storage
23
+ from django.core.exceptions import PermissionDenied
21
24
  from django.core.mail import send_mail
22
25
  from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
23
26
  from django.core.signing import BadSignature, Signer
24
27
  from django.core.validators import URLValidator, ValidationError
25
28
  from django.http import (
29
+ Http404,
26
30
  HttpResponse,
27
31
  HttpResponseBadRequest,
28
32
  HttpResponseForbidden,
29
33
  HttpResponsePermanentRedirect,
30
34
  HttpResponseRedirect,
35
+ HttpResponseServerError,
31
36
  )
32
37
  from django.middleware.gzip import re_accepts_gzip
33
38
  from django.shortcuts import get_object_or_404
34
- from django.urls import reverse, reverse_lazy
39
+ from django.urls import resolve, reverse, reverse_lazy
35
40
  from django.utils.encoding import smart_bytes
36
41
  from django.utils.http import http_date
37
42
  from django.utils.timezone import make_aware
@@ -105,6 +110,12 @@ class PaginatorMixin:
105
110
  return [self.list_template_name]
106
111
  return super().get_template_names()
107
112
 
113
+ def get(self, *args, **kwargs):
114
+ response = super().get(*args, **kwargs)
115
+ if is_ajax(self.request):
116
+ return simple_json_response(html=response.rendered_content)
117
+ return response
118
+
108
119
 
109
120
  class PublicMapsMixin(object):
110
121
  def get_public_maps(self):
@@ -118,13 +129,26 @@ class PublicMapsMixin(object):
118
129
  maps = qs.order_by("-modified_at")
119
130
  return maps
120
131
 
132
+ def get_highlighted_maps(self):
133
+ staff = User.objects.filter(is_staff=True)
134
+ stars = Star.objects.filter(by__in=staff).values("map")
135
+ qs = Map.public.filter(pk__in=stars)
136
+ maps = qs.order_by("-modified_at")
137
+ return maps
138
+
121
139
 
122
140
  class Home(PaginatorMixin, TemplateView, PublicMapsMixin):
123
141
  template_name = "umap/home.html"
124
142
  list_template_name = "umap/map_list.html"
125
143
 
126
144
  def get_context_data(self, **kwargs):
127
- maps = self.get_public_maps()
145
+ if settings.UMAP_HOME_FEED is None:
146
+ maps = []
147
+ elif settings.UMAP_HOME_FEED == "highlighted":
148
+ maps = self.get_highlighted_maps()
149
+ else:
150
+ maps = self.get_public_maps()
151
+ maps = self.paginate(maps, settings.UMAP_MAPS_PER_PAGE)
128
152
 
129
153
  demo_map = None
130
154
  if hasattr(settings, "UMAP_DEMO_PK"):
@@ -140,8 +164,6 @@ class Home(PaginatorMixin, TemplateView, PublicMapsMixin):
140
164
  except Map.DoesNotExist:
141
165
  pass
142
166
 
143
- maps = self.paginate(maps, settings.UMAP_MAPS_PER_PAGE)
144
-
145
167
  return {
146
168
  "maps": maps,
147
169
  "demo_map": demo_map,
@@ -268,20 +290,44 @@ class UserDashboard(PaginatorMixin, DetailView, SearchMixin):
268
290
  return qs.order_by("-modified_at")
269
291
 
270
292
  def get_context_data(self, **kwargs):
271
- kwargs.update(
272
- {
273
- "q": self.request.GET.get("q"),
274
- "maps": self.paginate(
275
- self.get_maps(), settings.UMAP_MAPS_PER_PAGE_OWNER
276
- ),
277
- }
278
- )
293
+ page = self.paginate(self.get_maps(), settings.UMAP_MAPS_PER_PAGE_OWNER)
294
+ kwargs.update({"q": self.request.GET.get("q"), "maps": page})
279
295
  return super().get_context_data(**kwargs)
280
296
 
281
297
 
282
298
  user_dashboard = UserDashboard.as_view()
283
299
 
284
300
 
301
+ class UserDownload(DetailView, SearchMixin):
302
+ model = User
303
+
304
+ def get_object(self):
305
+ return self.get_queryset().get(pk=self.request.user.pk)
306
+
307
+ def get_maps(self):
308
+ qs = Map.objects.filter(id__in=self.request.GET.getlist("map_id"))
309
+ qs = qs.filter(owner=self.object).union(qs.filter(editors=self.object))
310
+ return qs.order_by("-modified_at")
311
+
312
+ def render_to_response(self, context, *args, **kwargs):
313
+ zip_buffer = io.BytesIO()
314
+ with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
315
+ for map_ in self.get_maps():
316
+ umapjson = map_.generate_umapjson(self.request)
317
+ geojson_file = io.StringIO(json.dumps(umapjson))
318
+ file_name = f"umap_backup_{map_.slug}_{map_.pk}.umap"
319
+ zip_file.writestr(file_name, geojson_file.getvalue())
320
+
321
+ response = HttpResponse(zip_buffer.getvalue(), content_type="application/zip")
322
+ response[
323
+ "Content-Disposition"
324
+ ] = 'attachment; filename="umap_backup_complete.zip"'
325
+ return response
326
+
327
+
328
+ user_download = UserDownload.as_view()
329
+
330
+
285
331
  class MapsShowCase(View):
286
332
  def get(self, *args, **kwargs):
287
333
  maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1)))
@@ -315,7 +361,6 @@ showcase = MapsShowCase.as_view()
315
361
 
316
362
  def validate_url(request):
317
363
  assert request.method == "GET"
318
- assert is_ajax(request)
319
364
  url = request.GET.get("url")
320
365
  assert url
321
366
  try:
@@ -421,14 +466,28 @@ class MapDetailMixin:
421
466
  model = Map
422
467
  pk_url_kwarg = "map_id"
423
468
 
424
- def get_context_data(self, **kwargs):
425
- context = super().get_context_data(**kwargs)
469
+ def set_preconnect(self, properties, context):
470
+ # Try to extract the tilelayer domain, in order to but a preconnect meta.
471
+ url_template = properties.get("tilelayer", {}).get("url_template")
472
+ # Not explicit tilelayer set, take the first of the list, which will be
473
+ # used by frontend too.
474
+ if not url_template:
475
+ tilelayers = properties.get("tilelayers")
476
+ if tilelayers:
477
+ url_template = tilelayers[0].get("url_template")
478
+ if url_template:
479
+ domain = urlparse(url_template).netloc
480
+ # Do not try to preconnect on domains with variables
481
+ if domain and "{" not in domain:
482
+ context["preconnect_domains"] = [f"//{domain}"]
483
+
484
+ def get_map_properties(self):
426
485
  user = self.request.user
427
486
  properties = {
428
487
  "urls": _urls_for_js(),
429
488
  "tilelayers": TileLayer.get_list(),
430
489
  "editMode": self.edit_mode,
431
- "default_iconUrl": "%sumap/img/marker.png" % settings.STATIC_URL, # noqa
490
+ "default_iconUrl": "%sumap/img/marker.svg" % settings.STATIC_URL, # noqa
432
491
  "umap_id": self.get_umap_id(),
433
492
  "starred": self.is_starred(),
434
493
  "licences": dict((l.name, l.json) for l in Licence.objects.all()),
@@ -452,6 +511,17 @@ class MapDetailMixin:
452
511
  if self.get_short_url():
453
512
  properties["shortUrl"] = self.get_short_url()
454
513
 
514
+ if not user.is_anonymous:
515
+ properties["user"] = {
516
+ "id": user.pk,
517
+ "name": str(user),
518
+ "url": reverse("user_dashboard"),
519
+ }
520
+ return properties
521
+
522
+ def get_context_data(self, **kwargs):
523
+ context = super().get_context_data(**kwargs)
524
+ properties = self.get_map_properties()
455
525
  if settings.USE_I18N:
456
526
  lang = settings.LANGUAGE_CODE
457
527
  # Check attr in case the middleware is not active
@@ -461,18 +531,13 @@ class MapDetailMixin:
461
531
  locale = to_locale(lang)
462
532
  properties["locale"] = locale
463
533
  context["locale"] = locale
464
- if not user.is_anonymous:
465
- properties["user"] = {
466
- "id": user.pk,
467
- "name": str(user),
468
- "url": reverse("user_dashboard"),
469
- }
470
- map_settings = self.get_geojson()
471
- if "properties" not in map_settings:
472
- map_settings["properties"] = {}
473
- map_settings["properties"].update(properties)
474
- map_settings["properties"]["datalayers"] = self.get_datalayers()
475
- context["map_settings"] = json.dumps(map_settings, indent=settings.DEBUG)
534
+ geojson = self.get_geojson()
535
+ if "properties" not in geojson:
536
+ geojson["properties"] = {}
537
+ geojson["properties"].update(properties)
538
+ geojson["properties"]["datalayers"] = self.get_datalayers()
539
+ context["map_settings"] = json.dumps(geojson, indent=settings.DEBUG)
540
+ self.set_preconnect(geojson["properties"], context)
476
541
  return context
477
542
 
478
543
  def get_datalayers(self):
@@ -525,6 +590,16 @@ class PermissionsMixin:
525
590
 
526
591
 
527
592
  class MapView(MapDetailMixin, PermissionsMixin, DetailView):
593
+ def get_context_data(self, **kwargs):
594
+ context = super().get_context_data(**kwargs)
595
+ context["oembed_absolute_uri"] = self.request.build_absolute_uri(
596
+ reverse("map_oembed")
597
+ )
598
+ context["absolute_uri"] = self.request.build_absolute_uri(
599
+ self.object.get_absolute_url()
600
+ )
601
+ return context
602
+
528
603
  def get(self, request, *args, **kwargs):
529
604
  self.object = self.get_object()
530
605
  canonical = self.get_canonical_url()
@@ -588,24 +663,60 @@ class MapDownload(DetailView):
588
663
  return reverse("map_download", args=(self.object.pk,))
589
664
 
590
665
  def render_to_response(self, context, *args, **kwargs):
591
- geojson = self.object.settings
592
- geojson["type"] = "umap"
593
- geojson["uri"] = self.request.build_absolute_uri(self.object.get_absolute_url())
594
- datalayers = []
595
- for datalayer in self.object.datalayer_set.all():
596
- with open(datalayer.geojson.path, "rb") as f:
597
- layer = json.loads(f.read())
598
- if datalayer.settings:
599
- layer["_umap_options"] = datalayer.settings
600
- datalayers.append(layer)
601
- geojson["layers"] = datalayers
602
- response = simple_json_response(**geojson)
666
+ umapjson = self.object.generate_umapjson(self.request)
667
+ response = simple_json_response(**umapjson)
603
668
  response[
604
669
  "Content-Disposition"
605
670
  ] = f'attachment; filename="umap_backup_{self.object.slug}.umap"'
606
671
  return response
607
672
 
608
673
 
674
+ class MapOEmbed(View):
675
+ def get(self, request, *args, **kwargs):
676
+ data = {"type": "rich", "version": "1.0"}
677
+ format_ = request.GET.get("format", "json")
678
+ if format_ != "json":
679
+ response = HttpResponseServerError("Only `json` format is implemented.")
680
+ response.status_code = 501
681
+ return response
682
+
683
+ url = request.GET.get("url")
684
+ if not url:
685
+ raise Http404("Missing `url` parameter.")
686
+
687
+ parsed_url = urlparse(url)
688
+ netloc = parsed_url.netloc
689
+ allowed_hosts = settings.ALLOWED_HOSTS
690
+ if parsed_url.hostname not in allowed_hosts and allowed_hosts != ["*"]:
691
+ raise Http404("Host not allowed.")
692
+
693
+ url_path = parsed_url.path
694
+ view, args, kwargs = resolve(url_path)
695
+ if "slug" not in kwargs or "map_id" not in kwargs:
696
+ raise Http404("Invalid URL path.")
697
+
698
+ map_ = Map.objects.get(id=kwargs["map_id"], slug=kwargs["slug"])
699
+
700
+ if map_.share_status != Map.PUBLIC:
701
+ raise PermissionDenied("This map is not public.")
702
+
703
+ map_url = map_.get_absolute_url()
704
+ label = _("See full screen")
705
+ height = 300
706
+ data["height"] = height
707
+ width = 800
708
+ data["width"] = width
709
+ # TODISCUSS: do we keep width=100% by default for the iframe?
710
+ html = (
711
+ f'<iframe width="100%" height="{height}px" '
712
+ f'frameborder="0" allowfullscreen allow="geolocation" '
713
+ f'src="//{netloc}{map_url}"></iframe>'
714
+ f'<p><a href="//{netloc}{map_url}">{label}</a></p>'
715
+ )
716
+ data["html"] = html
717
+ return simple_json_response(**data)
718
+
719
+
609
720
  class MapViewGeoJSON(MapView):
610
721
  def get_canonical_url(self):
611
722
  return reverse("map_geojson", args=(self.object.pk,))
@@ -618,6 +729,15 @@ class MapNew(MapDetailMixin, TemplateView):
618
729
  template_name = "umap/map_detail.html"
619
730
 
620
731
 
732
+ class MapPreview(MapDetailMixin, TemplateView):
733
+ template_name = "umap/map_detail.html"
734
+
735
+ def get_map_properties(self):
736
+ properties = super().get_map_properties()
737
+ properties["preview"] = True
738
+ return properties
739
+
740
+
621
741
  class MapCreate(FormLessEditMixin, PermissionsMixin, CreateView):
622
742
  model = Map
623
743
  form_class = MapSettingsForm
@@ -738,12 +858,14 @@ class MapDelete(DeleteView):
738
858
 
739
859
  def form_valid(self, form):
740
860
  self.object = self.get_object()
741
- if self.object.owner and self.request.user != self.object.owner:
861
+ if not self.object.can_delete(self.request.user, self.request):
742
862
  return HttpResponseForbidden(_("Only its owner can delete the map."))
743
- if not self.object.owner and not self.object.is_anonymous_owner(self.request):
744
- return HttpResponseForbidden()
745
863
  self.object.delete()
746
- return simple_json_response(redirect="/")
864
+ home_url = reverse("home")
865
+ if is_ajax(self.request):
866
+ return simple_json_response(redirect=home_url)
867
+ else:
868
+ return HttpResponseRedirect(form.data.get("next") or home_url)
747
869
 
748
870
 
749
871
  class MapClone(PermissionsMixin, View):
@@ -755,7 +877,10 @@ class MapClone(PermissionsMixin, View):
755
877
  return HttpResponseForbidden()
756
878
  owner = self.request.user if self.request.user.is_authenticated else None
757
879
  self.object = kwargs["map_inst"].clone(owner=owner)
758
- response = simple_json_response(redirect=self.object.get_absolute_url())
880
+ if is_ajax(self.request):
881
+ response = simple_json_response(redirect=self.object.get_absolute_url())
882
+ else:
883
+ response = HttpResponseRedirect(self.object.get_absolute_url())
759
884
  if not self.request.user.is_authenticated:
760
885
  key, value = self.object.signed_cookie_elements
761
886
  response.set_signed_cookie(
@@ -1086,8 +1211,6 @@ def webmanifest(request):
1086
1211
 
1087
1212
  def logout(request):
1088
1213
  do_logout(request)
1089
- if is_ajax(request):
1090
- return simple_json_response(redirect="/")
1091
1214
  return HttpResponseRedirect("/")
1092
1215
 
1093
1216
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: umap-project
3
- Version: 1.14.0a5
3
+ Version: 2.0.0a1
4
4
  Summary: Create maps with OpenStreetMap layers in a minute and embed them in your site.
5
5
  Author-email: Yohan Boniface <yb@enix.org>
6
6
  Maintainer-email: David Larlet <david@larlet.fr>
@@ -11,33 +11,31 @@ Classifier: Intended Audience :: Developers
11
11
  Classifier: Operating System :: OS Independent
12
12
  Classifier: Programming Language :: Python
13
13
  Classifier: Programming Language :: Python :: 3 :: Only
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
14
  Classifier: Programming Language :: Python :: 3.10
17
15
  Classifier: Programming Language :: Python :: 3.11
18
16
  Classifier: Programming Language :: Python :: 3.12
19
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
- Requires-Python: >=3.8
18
+ Requires-Python: >=3.10
21
19
  Requires-Dist: django-agnocomplete==2.2.0
22
- Requires-Dist: django-environ==0.10.0
20
+ Requires-Dist: django-environ==0.11.2
23
21
  Requires-Dist: django-probes==1.7.0
24
- Requires-Dist: django==4.2
25
- Requires-Dist: pillow==10.0.1
26
- Requires-Dist: psycopg2==2.9.6
22
+ Requires-Dist: django==5.0.2
23
+ Requires-Dist: pillow==10.2.0
24
+ Requires-Dist: psycopg==3.1.18
27
25
  Requires-Dist: rcssmin==1.1.2
28
26
  Requires-Dist: requests==2.31.0
29
27
  Requires-Dist: rjsmin==1.2.2
30
- Requires-Dist: social-auth-app-django==5.2.0
31
- Requires-Dist: social-auth-core==4.4.2
28
+ Requires-Dist: social-auth-app-django==5.4.0
29
+ Requires-Dist: social-auth-core==4.5.2
32
30
  Provides-Extra: dev
33
31
  Requires-Dist: djlint==1.34.1; extra == 'dev'
34
- Requires-Dist: hatch==1.9.1; extra == 'dev'
32
+ Requires-Dist: hatch==1.9.3; extra == 'dev'
35
33
  Requires-Dist: isort==5.12; extra == 'dev'
36
- Requires-Dist: mkdocs-material==9.4.14; extra == 'dev'
34
+ Requires-Dist: mkdocs-material==9.5.7; extra == 'dev'
37
35
  Requires-Dist: mkdocs==1.5.3; extra == 'dev'
38
- Requires-Dist: pymdown-extensions==10.4; extra == 'dev'
39
- Requires-Dist: ruff==0.1.6; extra == 'dev'
40
- Requires-Dist: vermin==1.5.2; extra == 'dev'
36
+ Requires-Dist: pymdown-extensions==10.7; extra == 'dev'
37
+ Requires-Dist: ruff==0.2.0; extra == 'dev'
38
+ Requires-Dist: vermin==1.6.0; extra == 'dev'
41
39
  Provides-Extra: docker
42
40
  Requires-Dist: uwsgi==2.0.23; extra == 'docker'
43
41
  Provides-Extra: test