diff options
-rw-r--r-- | fietsboek/routes.py | 1 | ||||
-rw-r--r-- | fietsboek/templates/browse.jinja2 | 52 | ||||
-rw-r--r-- | fietsboek/templates/layout.jinja2 | 3 | ||||
-rw-r--r-- | fietsboek/views/browse.py | 45 |
4 files changed, 101 insertions, 0 deletions
diff --git a/fietsboek/routes.py b/fietsboek/routes.py index b0ee3c4..018c1d3 100644 --- a/fietsboek/routes.py +++ b/fietsboek/routes.py @@ -5,6 +5,7 @@ def includeme(config): config.add_route('home', '/') config.add_route('login', '/login') config.add_route('logout', '/logout') + config.add_route('browse', '/track/') config.add_route('password-reset', '/password-reset') config.add_route('use-token', '/token/{uuid}') diff --git a/fietsboek/templates/browse.jinja2 b/fietsboek/templates/browse.jinja2 new file mode 100644 index 0000000..174694a --- /dev/null +++ b/fietsboek/templates/browse.jinja2 @@ -0,0 +1,52 @@ +{% extends "layout.jinja2" %} +{% block content %} +<div class="container"> + <h1>{{ _("page.browse.title") }}</h1> + {% for track in tracks %} + <div class="card mb-3"> + <h5 class="card-header"> + <a href="{{ request.route_url('details', id=track.id) }}">{{ track.title | default(track.date, true) }}</a> + {% if track.text_tags() %} + {% for tag in track.tags %}<span class="badge bg-info text-dark">{{ tag.tag }}</span> {% endfor %} + {% endif %} + </h5> + <div class="card-body"> + <table class="table table-hover table-sm"> + <tbody> + <tr> + <th scope="row">{{ _("page.details.date") }}</th> + <td>{{ track.date | format_datetime }}</td> + <th scope="row">{{ _("page.details.length") }}</th> + <td>{{ (track.length / 1000) | round(2) | format_decimal }} km</td> + </tr> + <tr> + <th scope="row">{{ _("page.details.start_time") }}</th> + <td>{{ track.start_time | format_datetime }}</td> + <th scope="row">{{ _("page.details.end_time") }}</th> + <td>{{ track.end_time | format_datetime }}</td> + </tr> + <tr> + <th scope="row">{{ _("page.details.uphill") }}</th> + <td>{{ track.uphill | round(2) | format_decimal }} m</td> + <th scope="row">{{ _("page.details.downhill") }}</th> + <td>{{ track.downhill | round(2) | format_decimal }} m</td> + </tr> + <tr> + <th scope="row">{{ _("page.details.moving_time") }}</th> + <td>{{ track.moving_time }}</td> + <th scope="row">{{ _("page.details.stopped_time") }}</th> + <td>{{ track.stopped_time }}</td> + </tr> + <tr> + <th scope="row">{{ _("page.details.max_speed") }}</th> + <td>{{ mps_to_kph(track.max_speed) | round(2) | format_decimal }} km/h</td> + <th scope="row">{{ _("page.details.avg_speed") }}</th> + <td>{{ mps_to_kph(track.avg_speed) | round(2) | format_decimal }} km/h</td> + </tr> + </tbody> + </table> + </div> + </div> + {% endfor %} +</div> +{% endblock %} diff --git a/fietsboek/templates/layout.jinja2 b/fietsboek/templates/layout.jinja2 index 6caf666..4bbb9c0 100644 --- a/fietsboek/templates/layout.jinja2 +++ b/fietsboek/templates/layout.jinja2 @@ -38,6 +38,9 @@ <li class="nav-item"> <a class="nav-link" href="{{ request.route_url('home') }}">{{ _("page.navbar.home") }}</a> </li> + <li class="nav-item"> + <a class="nav-link" href="{{ request.route_url('browse') }}">{{ _("page.navbar.browse") }}</a> + </li> {% if request.identity is none %} <li class="nav-item"> <a class="nav-link" href="{{ request.route_url('login') }}">{{ _("page.navbar.login") }}</a> diff --git a/fietsboek/views/browse.py b/fietsboek/views/browse.py new file mode 100644 index 0000000..3739061 --- /dev/null +++ b/fietsboek/views/browse.py @@ -0,0 +1,45 @@ +"""Views for browsing all tracks.""" +from pyramid.view import view_config + +from sqlalchemy import select + +from .. import models, util + + +def visible_tracks(dbsession, user): + """Returns all visible tracks for the given user. + + The user might be ``None``, in which case all public tracks are returned. + + :param dbsession: The database session. + :type dbsession: sqlalchemy.orm.session.Session + :param user: The user to get the tracks for. + :type user: fietsboek.models.user.User + :return: The list of visible tracks. + :rtype: ~collections.abc.Iterable[fietsboek.models.track.Track] + """ + # This is fine for now, but we should try and do most of this work right in + # SQL in the future. + tracks = dbsession.execute(select(models.Track)).scalars() + return sorted( + (track for track in tracks if track.is_visible_to(user)), + key=lambda t: t.date, + reverse=True, + ) + + +@view_config(route_name="browse", renderer="fietsboek:templates/browse.jinja2", + request_method="GET") +def browse(request): + """Returns the page that lets a user browse all visible tracks. + + :param request: The Pyramid request. + :type request: pyramid.request.Request + :return: The HTTP response. + :rtype: pyramid.response.Response + """ + tracks = visible_tracks(request.dbsession, request.identity) + return { + 'tracks': tracks, + 'mps_to_kph': util.mps_to_kph, + } |