Ability to download all maps from user’s dashboard
This commit is contained in:
parent
77b35d079a
commit
5476cbee0f
4 changed files with 59 additions and 21 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -222,6 +223,20 @@ class Map(NamedModel):
|
||||||
)
|
)
|
||||||
return map_settings
|
return map_settings
|
||||||
|
|
||||||
|
def generate_geojson(self, request):
|
||||||
|
geojson = self.settings
|
||||||
|
geojson["type"] = "umap"
|
||||||
|
geojson["uri"] = request.build_absolute_uri(self.get_absolute_url())
|
||||||
|
datalayers = []
|
||||||
|
for datalayer in self.datalayer_set.all():
|
||||||
|
with open(datalayer.geojson.path, "rb") as f:
|
||||||
|
layer = json.loads(f.read())
|
||||||
|
if datalayer.settings:
|
||||||
|
layer["_umap_options"] = datalayer.settings
|
||||||
|
datalayers.append(layer)
|
||||||
|
geojson["layers"] = datalayers
|
||||||
|
return geojson
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("map", kwargs={"slug": self.slug or "map", "map_id": self.pk})
|
return reverse("map", kwargs={"slug": self.slug or "map", "map_id": self.pk})
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,14 @@
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="5"></td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'user_download' %}" class="button">{% translate "Download all maps" %}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
{% if maps.has_previous %}
|
{% if maps.has_previous %}
|
||||||
|
|
13
umap/urls.py
13
umap/urls.py
|
@ -109,16 +109,9 @@ i18n_urls += decorated_patterns(
|
||||||
views.ToggleMapStarStatus.as_view(),
|
views.ToggleMapStarStatus.as_view(),
|
||||||
name="map_star",
|
name="map_star",
|
||||||
),
|
),
|
||||||
re_path(
|
re_path(r"^me$", views.user_dashboard, name="user_dashboard"),
|
||||||
r"^me$",
|
re_path(r"^me/profile$", views.user_profile, name="user_profile"),
|
||||||
views.user_dashboard,
|
re_path(r"^me/download$", views.user_download, name="user_download"),
|
||||||
name="user_dashboard",
|
|
||||||
),
|
|
||||||
re_path(
|
|
||||||
r"^me/profile$",
|
|
||||||
views.user_profile,
|
|
||||||
name="user_profile",
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
map_urls = [
|
map_urls = [
|
||||||
re_path(
|
re_path(
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
import io
|
||||||
import json
|
import json
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
import zipfile
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from http.client import InvalidURL
|
from http.client import InvalidURL
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
@ -302,6 +304,36 @@ class UserDashboard(PaginatorMixin, DetailView, SearchMixin):
|
||||||
user_dashboard = UserDashboard.as_view()
|
user_dashboard = UserDashboard.as_view()
|
||||||
|
|
||||||
|
|
||||||
|
class UserDownload(PaginatorMixin, DetailView, SearchMixin):
|
||||||
|
model = User
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
return self.get_queryset().get(pk=self.request.user.pk)
|
||||||
|
|
||||||
|
def get_maps(self):
|
||||||
|
qs = self.get_search_queryset() or Map.objects.all()
|
||||||
|
qs = qs.filter(owner=self.object).union(qs.filter(editors=self.object))
|
||||||
|
return qs.order_by("-modified_at")
|
||||||
|
|
||||||
|
def render_to_response(self, context, *args, **kwargs):
|
||||||
|
zip_buffer = io.BytesIO()
|
||||||
|
with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
|
||||||
|
for map_ in self.get_maps():
|
||||||
|
map_geojson = map_.generate_geojson(self.request)
|
||||||
|
geojson_file = io.StringIO(json.dumps(map_geojson))
|
||||||
|
file_name = f"umap_backup_{map_.slug}.umap"
|
||||||
|
zip_file.writestr(file_name, geojson_file.getvalue())
|
||||||
|
|
||||||
|
response = HttpResponse(zip_buffer.getvalue(), content_type="application/zip")
|
||||||
|
response[
|
||||||
|
"Content-Disposition"
|
||||||
|
] = 'attachment; filename="umap_backup_complete.zip"'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
user_download = UserDownload.as_view()
|
||||||
|
|
||||||
|
|
||||||
class MapsShowCase(View):
|
class MapsShowCase(View):
|
||||||
def get(self, *args, **kwargs):
|
def get(self, *args, **kwargs):
|
||||||
maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1)))
|
maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1)))
|
||||||
|
@ -633,17 +665,7 @@ class MapDownload(DetailView):
|
||||||
return reverse("map_download", args=(self.object.pk,))
|
return reverse("map_download", args=(self.object.pk,))
|
||||||
|
|
||||||
def render_to_response(self, context, *args, **kwargs):
|
def render_to_response(self, context, *args, **kwargs):
|
||||||
geojson = self.object.settings
|
geojson = self.object.generate_geojson(self.request)
|
||||||
geojson["type"] = "umap"
|
|
||||||
geojson["uri"] = self.request.build_absolute_uri(self.object.get_absolute_url())
|
|
||||||
datalayers = []
|
|
||||||
for datalayer in self.object.datalayer_set.all():
|
|
||||||
with open(datalayer.geojson.path, "rb") as f:
|
|
||||||
layer = json.loads(f.read())
|
|
||||||
if datalayer.settings:
|
|
||||||
layer["_umap_options"] = datalayer.settings
|
|
||||||
datalayers.append(layer)
|
|
||||||
geojson["layers"] = datalayers
|
|
||||||
response = simple_json_response(**geojson)
|
response = simple_json_response(**geojson)
|
||||||
response[
|
response[
|
||||||
"Content-Disposition"
|
"Content-Disposition"
|
||||||
|
|
Loading…
Reference in a new issue