Ability to download all maps from user’s dashboard

This commit is contained in:
David Larlet 2023-11-24 17:04:47 -05:00
parent 77b35d079a
commit 5476cbee0f
No known key found for this signature in database
GPG key ID: 3E2953A359E7E7BD
4 changed files with 59 additions and 21 deletions

View file

@ -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})

View file

@ -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 %}

View file

@ -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(

View file

@ -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"