aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fietsboek/actions.py12
-rw-r--r--fietsboek/data.py29
-rw-r--r--fietsboek/views/detail.py22
-rw-r--r--fietsboek/views/upload.py2
-rw-r--r--tests/playwright/conftest.py2
5 files changed, 61 insertions, 6 deletions
diff --git a/fietsboek/actions.py b/fietsboek/actions.py
index a20ca2e..0457648 100644
--- a/fietsboek/actions.py
+++ b/fietsboek/actions.py
@@ -7,6 +7,7 @@ the test functions.
"""
import datetime
+import io
import logging
import re
from typing import Optional
@@ -18,12 +19,12 @@ from pyramid.request import Request
from sqlalchemy import select
from sqlalchemy.orm.session import Session
-from . import email, models
+from . import email, models, trackmap, util
from . import transformers as mod_transformers
-from . import util
from .data import DataManager, TrackDataDir
from .models.track import TrackType, Visibility
from .models.user import TokenType
+from .views.tileproxy import TileRequester
LOGGER = logging.getLogger(__name__)
@@ -31,6 +32,7 @@ LOGGER = logging.getLogger(__name__)
def add_track(
dbsession: Session,
data_manager: DataManager,
+ tile_requester: TileRequester,
owner: models.User,
title: str,
date: datetime.datetime,
@@ -105,6 +107,12 @@ def add_track(
track.ensure_cache(gpx)
dbsession.add(track.cache)
+ LOGGER.debug("Building preview image for %s", track.id)
+ preview_image = trackmap.render(gpx, tile_requester)
+ image_io = io.BytesIO()
+ preview_image.save(image_io, "PNG")
+ manager.set_preview(image_io.getvalue())
+
manager.engrave_metadata(
title=track.title,
description=track.description,
diff --git a/fietsboek/data.py b/fietsboek/data.py
index a7e9b19..d1268bf 100644
--- a/fietsboek/data.py
+++ b/fietsboek/data.py
@@ -191,6 +191,12 @@ class TrackDataDir:
elif action == "delete_image":
path, data = rest
path.write_bytes(data)
+ elif action == "set_preview":
+ old_data = rest
+ if old_data is None:
+ self.preview_path().unlink()
+ else:
+ self.preview_path().write_bytes(old_data)
self.journal = None
@@ -218,6 +224,9 @@ class TrackDataDir:
elif action == "delete_image":
# Again, nothing to do here, we simply discard the in-memory image data
pass
+ elif action == "set_preview":
+ # Still nothing to do here
+ pass
self.journal = None
@@ -406,6 +415,26 @@ class TrackDataDir:
path.unlink()
+ def preview_path(self) -> Path:
+ """Gets the path to the "preview image".
+
+ :return: The path to the preview image.
+ """
+ return self.path / "preview.png"
+
+ def set_preview(self, data: bytes):
+ """Sets the preview image to the given data.
+
+ :param data: The data of the preview image.
+ """
+ if self.journal is not None:
+ try:
+ previous_preview = self.preview_path().read_bytes()
+ except FileNotFoundError:
+ previous_preview = None
+ self.journal.append(("set_preview", previous_preview))
+ self.preview_path().write_bytes(data)
+
class UserDataDir:
"""Manager for a single user's data."""
diff --git a/fietsboek/views/detail.py b/fietsboek/views/detail.py
index 332e107..0b42cdc 100644
--- a/fietsboek/views/detail.py
+++ b/fietsboek/views/detail.py
@@ -229,14 +229,28 @@ def add_comment(request):
@view_config(route_name="track-map", http_cache=3600, permission="track.view")
def track_map(request: Request):
track = request.context
+ manager = request.data_manager.open(track.id)
+ preview_path = manager.preview_path()
+ try:
+ response = Response(preview_path.read_bytes(), content_type="image/png")
+ response.md5_etag()
+ return response
+ except FileNotFoundError:
+ pass
+
loader: ITileRequester = request.registry.getUtility(ITileRequester)
- gpx = gpxpy.parse(request.data_manager.open(track.id).decompress_gpx())
+ gpx = gpxpy.parse(manager.decompress_gpx())
image = trackmap.render(gpx, loader)
- imagebytes = io.BytesIO()
- image.save(imagebytes, "png")
- response = Response(imagebytes.getvalue(), content_type="image/png")
+ imageio = io.BytesIO()
+ image.save(imageio, "png")
+ tile_data = imageio.getvalue()
+
+ with manager.lock():
+ manager.set_preview(tile_data)
+
+ response = Response(tile_data, content_type="image/png")
response.md5_etag()
return response
diff --git a/fietsboek/views/upload.py b/fietsboek/views/upload.py
index c40319c..42dc59f 100644
--- a/fietsboek/views/upload.py
+++ b/fietsboek/views/upload.py
@@ -12,6 +12,7 @@ from sqlalchemy import select
from .. import actions, convert, models, transformers, util
from ..models.track import TrackType, Visibility
+from ..views.tileproxy import ITileRequester
LOGGER = logging.getLogger(__name__)
@@ -165,6 +166,7 @@ def do_finish_upload(request):
track = actions.add_track(
request.dbsession,
request.data_manager,
+ request.registry.getUtility(ITileRequester),
owner=request.identity,
title=request.params["title"],
visibility=Visibility[request.params["visibility"]],
diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py
index 4e7f5a4..205626d 100644
--- a/tests/playwright/conftest.py
+++ b/tests/playwright/conftest.py
@@ -11,6 +11,7 @@ from testutils import load_gpx_asset
from fietsboek import models, util, actions
from fietsboek.models.track import Visibility, TrackType
from fietsboek.config import Config
+from fietsboek.views.tileproxy import TileRequester
import pytest
@@ -117,6 +118,7 @@ class Helper:
track = actions.add_track(
self.dbaccess,
self.data_manager,
+ TileRequester(None),
owner=user,
title="Another awesome track",
visibility=Visibility.PRIVATE,