From 88411c91f83614a3918c2a553e2592862c147175 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Wed, 12 Aug 2026 22:17:31 +0200 Subject: add year-track-activity overview --- asset-sources/theme.scss | 31 +++++++++ babel.cfg | 1 + fietsboek/locale/de/LC_MESSAGES/messages.mo | Bin 20324 -> 20548 bytes fietsboek/locale/de/LC_MESSAGES/messages.po | 26 ++++--- fietsboek/locale/en/LC_MESSAGES/messages.mo | Bin 19139 -> 19355 bytes fietsboek/locale/en/LC_MESSAGES/messages.po | 26 ++++--- fietsboek/locale/fietslog.pot | 26 ++++--- fietsboek/static/theme.css | 41 ++++++++--- fietsboek/static/theme.css.map | 2 +- fietsboek/summaries.py | 101 +++++++++++++++++++++++++++- fietsboek/templates/profile_overview.jinja2 | 29 ++++++++ fietsboek/views/profile.py | 5 +- 12 files changed, 252 insertions(+), 36 deletions(-) diff --git a/asset-sources/theme.scss b/asset-sources/theme.scss index ba05782..cdb4923 100644 --- a/asset-sources/theme.scss +++ b/asset-sources/theme.scss @@ -271,6 +271,37 @@ strong { } } +.contributions { + tbody td.contribs-cell { + div { + border: 2px solid rgba(0, 0, 0, 0.175); + border-radius: calc(0.375rem - (1px)); + + width: 1em; + height: 1em; + } + } + + .contribs-length-0 div { + background-color: #FFFFFF; + } + .contribs-length-1 div { + background-color: #8FF0A4; + } + .contribs-length-2 div { + background-color: #75DD95; + } + .contribs-length-3 div { + background-color: #5BC987; + } + .contribs-length-4 div { + background-color: #40B678; + } + .contribs-length-5 div { + background-color: #26A269; + } +} + .browse-summary { font-variant: lining-nums; } diff --git a/babel.cfg b/babel.cfg index 6de4aaa..650a00a 100644 --- a/babel.cfg +++ b/babel.cfg @@ -4,3 +4,4 @@ jinja2 = jinja2.ext:babel_extract [jinja2: **.jinja2] [python: **.py] +keywords = _ pluralize:1,2 diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.mo b/fietsboek/locale/de/LC_MESSAGES/messages.mo index 356be25..4ffa423 100644 Binary files a/fietsboek/locale/de/LC_MESSAGES/messages.mo and b/fietsboek/locale/de/LC_MESSAGES/messages.mo differ diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.po b/fietsboek/locale/de/LC_MESSAGES/messages.po index 9367d28..8342327 100644 --- a/fietsboek/locale/de/LC_MESSAGES/messages.po +++ b/fietsboek/locale/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-01-03 19:25+0100\n" +"POT-Creation-Date: 2026-08-12 22:13+0200\n" "PO-Revision-Date: 2022-07-02 17:35+0200\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -16,7 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.17.0\n" +"Generated-By: Babel 2.18.0\n" #: fietsboek/actions.py:266 msgid "email.verify_mail.subject" @@ -61,6 +61,12 @@ msgstr "Maximalgeschwindigkeit" msgid "pdf.table.avg_speed" msgstr "Durchschnittsgeschwindigkeit" +#: fietsboek/summaries.py:384 +msgid "page.profile.contribution_card.tooltip" +msgid_plural "page.profile.contribution_card.tooltips" +msgstr[0] "${count} Strecke am ${date}" +msgstr[1] "${count} Strecken am ${date}" + #: fietsboek/util.py:299 msgid "password_constraint.mismatch" msgstr "Passwörter stimmen nicht überein" @@ -1008,27 +1014,31 @@ msgstr "durchschnittliche Geschwindigkeit" msgid "page.profile.number_of_tracks" msgstr "Anzahl der Strecken" -#: fietsboek/templates/profile_overview.jinja2:113 +#: fietsboek/templates/profile_overview.jinja2:112 +msgid "page.profile.contribution_card.title" +msgstr "Streckenaktivität" + +#: fietsboek/templates/profile_overview.jinja2:142 msgid "page.profile.longest_distance_track" msgstr "Weiteste Strecke" -#: fietsboek/templates/profile_overview.jinja2:118 +#: fietsboek/templates/profile_overview.jinja2:147 msgid "page.profile.shortest_distance_track" msgstr "Kürzeste Strecke" -#: fietsboek/templates/profile_overview.jinja2:123 +#: fietsboek/templates/profile_overview.jinja2:152 msgid "page.profile.longest_duration_track" msgstr "Am Längsten Dauernde Strecke" -#: fietsboek/templates/profile_overview.jinja2:128 +#: fietsboek/templates/profile_overview.jinja2:157 msgid "page.profile.shortest_duration_track" msgstr "Am Kürzesten Dauernde Strecke" -#: fietsboek/templates/profile_overview.jinja2:149 +#: fietsboek/templates/profile_overview.jinja2:178 msgid "page.profile.heatmap" msgstr "Heatmap" -#: fietsboek/templates/profile_overview.jinja2:157 +#: fietsboek/templates/profile_overview.jinja2:186 msgid "page.profile.tilehunt" msgstr "Kacheljäger" diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.mo b/fietsboek/locale/en/LC_MESSAGES/messages.mo index f4b7bbf..39eabb5 100644 Binary files a/fietsboek/locale/en/LC_MESSAGES/messages.mo and b/fietsboek/locale/en/LC_MESSAGES/messages.mo differ diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.po b/fietsboek/locale/en/LC_MESSAGES/messages.po index d52960b..a8e6c0c 100644 --- a/fietsboek/locale/en/LC_MESSAGES/messages.po +++ b/fietsboek/locale/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-01-03 19:25+0100\n" +"POT-Creation-Date: 2026-08-12 22:13+0200\n" "PO-Revision-Date: 2023-04-03 20:42+0200\n" "Last-Translator: \n" "Language: en\n" @@ -16,7 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.17.0\n" +"Generated-By: Babel 2.18.0\n" #: fietsboek/actions.py:266 msgid "email.verify_mail.subject" @@ -61,6 +61,12 @@ msgstr "Max Speed" msgid "pdf.table.avg_speed" msgstr "Average Speed" +#: fietsboek/summaries.py:384 +msgid "page.profile.contribution_card.tooltip" +msgid_plural "page.profile.contribution_card.tooltips" +msgstr[0] "${count} track on ${date}" +msgstr[1] "${count} tracks on ${date}" + #: fietsboek/util.py:299 msgid "password_constraint.mismatch" msgstr "Passwords don't match" @@ -1002,27 +1008,31 @@ msgstr "Average Speed" msgid "page.profile.number_of_tracks" msgstr "Number of tracks" -#: fietsboek/templates/profile_overview.jinja2:113 +#: fietsboek/templates/profile_overview.jinja2:112 +msgid "page.profile.contribution_card.title" +msgstr "Track Activity" + +#: fietsboek/templates/profile_overview.jinja2:142 msgid "page.profile.longest_distance_track" msgstr "Longest Track" -#: fietsboek/templates/profile_overview.jinja2:118 +#: fietsboek/templates/profile_overview.jinja2:147 msgid "page.profile.shortest_distance_track" msgstr "Shortest Track" -#: fietsboek/templates/profile_overview.jinja2:123 +#: fietsboek/templates/profile_overview.jinja2:152 msgid "page.profile.longest_duration_track" msgstr "Most Time-Consuming Track" -#: fietsboek/templates/profile_overview.jinja2:128 +#: fietsboek/templates/profile_overview.jinja2:157 msgid "page.profile.shortest_duration_track" msgstr "Quickest Track" -#: fietsboek/templates/profile_overview.jinja2:149 +#: fietsboek/templates/profile_overview.jinja2:178 msgid "page.profile.heatmap" msgstr "Heat Map" -#: fietsboek/templates/profile_overview.jinja2:157 +#: fietsboek/templates/profile_overview.jinja2:186 msgid "page.profile.tilehunt" msgstr "Tilehunt" diff --git a/fietsboek/locale/fietslog.pot b/fietsboek/locale/fietslog.pot index 50a43a0..7f7e325 100644 --- a/fietsboek/locale/fietslog.pot +++ b/fietsboek/locale/fietslog.pot @@ -8,14 +8,14 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-01-03 19:25+0100\n" +"POT-Creation-Date: 2026-08-12 22:13+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 2.17.0\n" +"Generated-By: Babel 2.18.0\n" #: fietsboek/actions.py:266 msgid "email.verify_mail.subject" @@ -57,6 +57,12 @@ msgstr "" msgid "pdf.table.avg_speed" msgstr "" +#: fietsboek/summaries.py:384 +msgid "page.profile.contribution_card.tooltip" +msgid_plural "page.profile.contribution_card.tooltips" +msgstr[0] "" +msgstr[1] "" + #: fietsboek/util.py:299 msgid "password_constraint.mismatch" msgstr "" @@ -994,27 +1000,31 @@ msgstr "" msgid "page.profile.number_of_tracks" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:113 +#: fietsboek/templates/profile_overview.jinja2:112 +msgid "page.profile.contribution_card.title" +msgstr "" + +#: fietsboek/templates/profile_overview.jinja2:142 msgid "page.profile.longest_distance_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:118 +#: fietsboek/templates/profile_overview.jinja2:147 msgid "page.profile.shortest_distance_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:123 +#: fietsboek/templates/profile_overview.jinja2:152 msgid "page.profile.longest_duration_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:128 +#: fietsboek/templates/profile_overview.jinja2:157 msgid "page.profile.shortest_duration_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:149 +#: fietsboek/templates/profile_overview.jinja2:178 msgid "page.profile.heatmap" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:157 +#: fietsboek/templates/profile_overview.jinja2:186 msgid "page.profile.tilehunt" msgstr "" diff --git a/fietsboek/static/theme.css b/fietsboek/static/theme.css index 65e6881..aa9fe1b 100644 --- a/fietsboek/static/theme.css +++ b/fietsboek/static/theme.css @@ -80,14 +80,6 @@ strong { flex-wrap: wrap; } -.track-image-preview { - position: relative; - width: min(317px, 100%); - height: 178.3125px; - border: 1px solid grey; - margin-right: 5px; - margin-bottom: 5px; -} .track-image-preview .delete-image { position: absolute; z-index: 5; @@ -120,6 +112,14 @@ strong { left: 50%; transform: translate(-50%, -50%); } +.track-image-preview { + position: relative; + width: min(317px, 100%); + height: 178.3125px; + border: 1px solid grey; + margin-right: 5px; + margin-bottom: 5px; +} .track-description img { max-width: 100%; @@ -259,6 +259,31 @@ strong { color: inherit; } +.contributions tbody td.contribs-cell div { + border: 2px solid rgba(0, 0, 0, 0.175); + border-radius: calc(0.375rem - 1px); + width: 1em; + height: 1em; +} +.contributions .contribs-length-0 div { + background-color: #FFFFFF; +} +.contributions .contribs-length-1 div { + background-color: #8FF0A4; +} +.contributions .contribs-length-2 div { + background-color: #75DD95; +} +.contributions .contribs-length-3 div { + background-color: #5BC987; +} +.contributions .contribs-length-4 div { + background-color: #40B678; +} +.contributions .contribs-length-5 div { + background-color: #26A269; +} + .browse-summary { font-variant: lining-nums; } diff --git a/fietsboek/static/theme.css.map b/fietsboek/static/theme.css.map index 3ddb9bc..6c87d3e 100644 --- a/fietsboek/static/theme.css.map +++ b/fietsboek/static/theme.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EAqCE;EACA;EACA;EACA;EACA;EACA;;AAzCA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAWJ;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAMA;EACE;EACA;EAEA;EACA;;AAIJ;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;;AAIJ;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index 0bee6ca..aa8a84c 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -2,11 +2,17 @@ import datetime from dataclasses import dataclass -from typing import Optional +from typing import Optional, Iterator + +from babel.dates import format_date +from pyramid.i18n import Localizer +from pyramid.i18n import TranslationString as _ from . import util from .models.track import TrackWithMetadata +ONE_WEEK = datetime.timedelta(days=7) + class Summary: """A summary of a user's tracks. @@ -294,4 +300,95 @@ class CumulativeStats: return util.round_to_seconds((self.moving_time + self.stopped_time) / self.count) -__all__ = ["Summary", "YearSummary", "MonthSummary", "CumulativeStats"] +class YearContributions: + """Github-contributions-tracker-like overview for tracks.""" + + def __init__(self, end_date: datetime.date): + self.end_date = end_date + self.start_date = end_date - 52 * ONE_WEEK + # Make sure the start of the range is on a Monday + self.start_date -= datetime.timedelta(days=end_date.weekday()) + assert (self.start_date - self.end_date).days <= 53 * 7 + + self.tracks = {} + + def add(self, track: TrackWithMetadata): + date = track.date.date() + if date >= self.start_date and date <= self.end_date: + self.tracks.setdefault(date, []).append(track) + + def rows(self) -> Iterator[Iterator[DayContributions]]: + for weekday in range(7): + row = [] + day = self.start_date + datetime.timedelta(days=weekday) + while day <= self.end_date: + row.append(DayContributions(day, self.tracks.get(day, []))) + day += ONE_WEEK + yield row + + def header_row(self, localizer: Localizer) -> Iterator[str | None]: + locale = localizer.locale_name + day = self.start_date + while day <= self.end_date: + diq = day + datetime.timedelta(days=6) + if diq.day <= 7: + yield format_date(diq, "MMM", locale=locale) + day += 3 * ONE_WEEK + else: + yield None + day += ONE_WEEK + + +class DayContributions: + """A single cell (representing one day) for the YearContributions.""" + + def __init__(self, day: datetime.date, tracks: list[TrackWithMetadata]): + self.day = day + self.tracks = tracks + + def total_length(self) -> float: + """The total length of all tracks on this day, in meters.""" + return sum(track.length for track in self.tracks) + + def count(self) -> int: + """The number of tracks in this day.""" + return len(self.tracks) + + def cell_style(self) -> str: + """Returns the CSS style that should be applied to the cell. + + :return: The CSS class. + """ + length = self.total_length() / 1000 + # Arbitrary cutoffs, should maybe be the same as for the calendar + if length == 0: + return "contribs-length-0" + if length <= 25: + return "contribs-length-1" + if length <= 50: + return "contribs-length-2" + if length <= 75: + return "contribs-length-3" + if length <= 100: + return "contribs-length-4" + return "contribs-length-5" + + def tooltip(self, localizer: Localizer) -> str: + """Generates the tooltip for the cell, localized to the given language. + + :param localizer: The localizer to use. + :return: The tooltip text. + """ + formatted_date = format_date(self.day, locale=localizer.locale_name) + return localizer.pluralize( + "page.profile.contribution_card.tooltip", + "page.profile.contribution_card.tooltips", + self.count(), + mapping={ + "count": self.count(), + "date": formatted_date, + }, + ) + + +__all__ = ["Summary", "YearSummary", "MonthSummary", "CumulativeStats", "YearContributions"] diff --git a/fietsboek/templates/profile_overview.jinja2 b/fietsboek/templates/profile_overview.jinja2 index eaa10c6..f563ad9 100644 --- a/fietsboek/templates/profile_overview.jinja2 +++ b/fietsboek/templates/profile_overview.jinja2 @@ -109,6 +109,35 @@ +

{{ _("page.profile.contribution_card.title") }}

+
+ + + + {% for cell in year_contributions.header_row(request.localizer) %} + {% if cell is none %} + + {% else %} + + {% endif %} + {% endfor %} + + + + {% for row in year_contributions.rows() %} + + {% for cell in row %} + + {% endfor %} + + {% endfor %} + +
{{ cell }}
+ +
+
+
+ {% if total.longest_distance_track %}

{{ _("page.profile.longest_distance_track") }}

{{ render_track_card(total.longest_distance_track) }} diff --git a/fietsboek/views/profile.py b/fietsboek/views/profile.py index 6d671b9..414dfae 100644 --- a/fietsboek/views/profile.py +++ b/fietsboek/views/profile.py @@ -16,7 +16,7 @@ from sqlalchemy.orm import aliased from .. import models, util from ..data import UserDataDir from ..models.track import TrackType, TrackWithMetadata -from ..summaries import CumulativeStats, Summary +from ..summaries import CumulativeStats, Summary, YearContributions # A well-made transparent tile is actually pretty small (only 116 bytes), which # is even smaller than our HTTP 404 page. So not only is it more efficient @@ -49,6 +49,7 @@ LOGGER = logging.getLogger(__name__) def profile_data(request: Request) -> dict: """Retrieves the profile data for the given request.""" total = CumulativeStats() + year_contribs = YearContributions(datetime.date.today() - datetime.timedelta(days=365)) query = request.context.all_tracks_query() query = select(aliased(models.Track, query)).where(query.c.type == TrackType.ORGANIC) @@ -56,6 +57,7 @@ def profile_data(request: Request) -> dict: for track in request.dbsession.execute(query).scalars(): meta = TrackWithMetadata(track) total.add(meta) + year_contribs.add(meta) total.moving_time = util.round_to_seconds(total.moving_time) total.stopped_time = util.round_to_seconds(total.stopped_time) @@ -79,6 +81,7 @@ def profile_data(request: Request) -> dict: "mps_to_kph": util.mps_to_kph, "heatmap_url": heatmap_url, "tilehunt_url": tilehunt_url, + "year_contributions": year_contribs, } -- cgit v1.2.3 From 7e08e27973be27f4dd65d00ec1eb70dd5a4467c8 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Wed, 12 Aug 2026 22:18:54 +0200 Subject: actually start year contribs from today Doing the previous year was just for testing purposes, oops --- fietsboek/views/profile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fietsboek/views/profile.py b/fietsboek/views/profile.py index 414dfae..4f9abca 100644 --- a/fietsboek/views/profile.py +++ b/fietsboek/views/profile.py @@ -49,7 +49,7 @@ LOGGER = logging.getLogger(__name__) def profile_data(request: Request) -> dict: """Retrieves the profile data for the given request.""" total = CumulativeStats() - year_contribs = YearContributions(datetime.date.today() - datetime.timedelta(days=365)) + year_contribs = YearContributions(datetime.date.today()) query = request.context.all_tracks_query() query = select(aliased(models.Track, query)).where(query.c.type == TrackType.ORGANIC) -- cgit v1.2.3 From 8492b351bdaa8b4660691d5c38eb3e8e74dca769 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Wed, 12 Aug 2026 23:11:24 +0200 Subject: fix lints --- fietsboek/summaries.py | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index aa8a84c..e3c58e6 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -2,11 +2,10 @@ import datetime from dataclasses import dataclass -from typing import Optional, Iterator +from typing import Iterator, Optional from babel.dates import format_date from pyramid.i18n import Localizer -from pyramid.i18n import TranslationString as _ from . import util from .models.track import TrackWithMetadata @@ -310,23 +309,42 @@ class YearContributions: self.start_date -= datetime.timedelta(days=end_date.weekday()) assert (self.start_date - self.end_date).days <= 53 * 7 - self.tracks = {} + self.tracks: dict[datetime.date, list[TrackWithMetadata]] = {} def add(self, track: TrackWithMetadata): + """Adds a track to this overview. + + :param track: The track to add. + """ + if track.date is None: + return date = track.date.date() - if date >= self.start_date and date <= self.end_date: + if self.start_date <= date <= self.end_date: self.tracks.setdefault(date, []).append(track) def rows(self) -> Iterator[Iterator[DayContributions]]: + """Returns the rows for the overview table. + + Each row is a list of the cells. Seven rows will be returned, one for each weekday. + + :return: An iterator over the rows to render. + """ for weekday in range(7): row = [] day = self.start_date + datetime.timedelta(days=weekday) while day <= self.end_date: row.append(DayContributions(day, self.tracks.get(day, []))) day += ONE_WEEK - yield row + yield iter(row) def header_row(self, localizer: Localizer) -> Iterator[str | None]: + """Returns the header row. + + Each string marks a month name (spanning three columns), and a ``None`` is an empty column. + + :param localizer: The localizer to use. + :return: An iterator over the column headers. + """ locale = localizer.locale_name day = self.start_date while day <= self.end_date: -- cgit v1.2.3 From 5178da7069304219a5c38b54a56a705627a88491 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 13 Aug 2026 17:33:41 +0200 Subject: add weekdays to year contributions --- asset-sources/theme.scss | 10 +++++++--- fietsboek/static/theme.css | 9 ++++++--- fietsboek/static/theme.css.map | 2 +- fietsboek/summaries.py | 27 +++++++++++++++++++++++++++ fietsboek/templates/profile_overview.jinja2 | 4 +++- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/asset-sources/theme.scss b/asset-sources/theme.scss index cdb4923..5432b43 100644 --- a/asset-sources/theme.scss +++ b/asset-sources/theme.scss @@ -274,14 +274,18 @@ strong { .contributions { tbody td.contribs-cell { div { - border: 2px solid rgba(0, 0, 0, 0.175); + border: 1px solid rgba(0, 0, 0, 0.175); border-radius: calc(0.375rem - (1px)); - width: 1em; - height: 1em; + width: 1.1em; + height: 1.1em; } } + .contribs-rowhead { + font-size: 90%; + } + .contribs-length-0 div { background-color: #FFFFFF; } diff --git a/fietsboek/static/theme.css b/fietsboek/static/theme.css index aa9fe1b..78d79e3 100644 --- a/fietsboek/static/theme.css +++ b/fietsboek/static/theme.css @@ -260,10 +260,13 @@ strong { } .contributions tbody td.contribs-cell div { - border: 2px solid rgba(0, 0, 0, 0.175); + border: 1px solid rgba(0, 0, 0, 0.175); border-radius: calc(0.375rem - 1px); - width: 1em; - height: 1em; + width: 1.1em; + height: 1.1em; +} +.contributions .contribs-rowhead { + font-size: 90%; } .contributions .contribs-length-0 div { background-color: #FFFFFF; diff --git a/fietsboek/static/theme.css.map b/fietsboek/static/theme.css.map index 6c87d3e..9408c30 100644 --- a/fietsboek/static/theme.css.map +++ b/fietsboek/static/theme.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAMA;EACE;EACA;EAEA;EACA;;AAIJ;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;;AAIJ;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAMA;EACE;EACA;EAEA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;;AAIJ;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index e3c58e6..8c54d5f 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -4,6 +4,7 @@ import datetime from dataclasses import dataclass from typing import Iterator, Optional +from babel import Locale from babel.dates import format_date from pyramid.i18n import Localizer @@ -337,6 +338,32 @@ class YearContributions: day += ONE_WEEK yield iter(row) + def _rowheads(self, localizer: Localizer) -> Iterator[str | None]: + """Returns the row heads (i.e., weekday names) to be prepended to the rows. + + :param localizer: The localizer to use. + :return: An iterator over the column headers. + """ + loc = Locale.parse(localizer.locale_name) + days = loc.days["stand-alone"]["abbreviated"] + return iter([ + days[0], + None, + None, + days[3], + None, + None, + days[6], + ]) + + def rows_with_heads(self, localizer: Localizer) -> Iterator[tuple[str | None, Iterator[DayContributions]]]: + """Returns each row with its associated heading (weekday name). + + :param localizer: The localizer to use. + :return: An iterator over (header, cells) pairs. + """ + return zip(self._rowheads(localizer), self.rows()) + def header_row(self, localizer: Localizer) -> Iterator[str | None]: """Returns the header row. diff --git a/fietsboek/templates/profile_overview.jinja2 b/fietsboek/templates/profile_overview.jinja2 index f563ad9..fbb1804 100644 --- a/fietsboek/templates/profile_overview.jinja2 +++ b/fietsboek/templates/profile_overview.jinja2 @@ -114,6 +114,7 @@ + {% for cell in year_contributions.header_row(request.localizer) %} {% if cell is none %} @@ -124,8 +125,9 @@ - {% for row in year_contributions.rows() %} + {% for rowhead, row in year_contributions.rows_with_heads(request.localizer) %} + {% for cell in row %}
{{ rowhead | default("", true) }} -- cgit v1.2.3 From f63341b5a5fd77144095dc4f974ffc32c1759614 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 13 Aug 2026 17:42:02 +0200 Subject: add legend to track activity --- asset-sources/theme.scss | 58 ++++++++++++++-------------- fietsboek/locale/de/LC_MESSAGES/messages.mo | Bin 20548 -> 20685 bytes fietsboek/locale/de/LC_MESSAGES/messages.po | 24 ++++++++---- fietsboek/locale/en/LC_MESSAGES/messages.mo | Bin 19355 -> 19490 bytes fietsboek/locale/en/LC_MESSAGES/messages.po | 24 ++++++++---- fietsboek/locale/fietslog.pot | 24 ++++++++---- fietsboek/static/theme.css | 23 +++++++---- fietsboek/static/theme.css.map | 2 +- fietsboek/templates/profile_overview.jinja2 | 17 ++++++++ 9 files changed, 109 insertions(+), 63 deletions(-) diff --git a/asset-sources/theme.scss b/asset-sources/theme.scss index 5432b43..2faaffa 100644 --- a/asset-sources/theme.scss +++ b/asset-sources/theme.scss @@ -271,39 +271,37 @@ strong { } } -.contributions { - tbody td.contribs-cell { - div { - border: 1px solid rgba(0, 0, 0, 0.175); - border-radius: calc(0.375rem - (1px)); - - width: 1.1em; - height: 1.1em; - } - } +.contribs-cell { + div { + border: 1px solid rgba(0, 0, 0, 0.175); + border-radius: calc(0.375rem - (1px)); - .contribs-rowhead { - font-size: 90%; + width: 1.1em; + height: 1.1em; } +} - .contribs-length-0 div { - background-color: #FFFFFF; - } - .contribs-length-1 div { - background-color: #8FF0A4; - } - .contribs-length-2 div { - background-color: #75DD95; - } - .contribs-length-3 div { - background-color: #5BC987; - } - .contribs-length-4 div { - background-color: #40B678; - } - .contribs-length-5 div { - background-color: #26A269; - } +.contribs-rowhead { + font-size: 90%; +} + +.contribs-length-0 div { + background-color: #FFFFFF; +} +.contribs-length-1 div { + background-color: #8FF0A4; +} +.contribs-length-2 div { + background-color: #75DD95; +} +.contribs-length-3 div { + background-color: #5BC987; +} +.contribs-length-4 div { + background-color: #40B678; +} +.contribs-length-5 div { + background-color: #26A269; } .browse-summary { diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.mo b/fietsboek/locale/de/LC_MESSAGES/messages.mo index 4ffa423..25b4a89 100644 Binary files a/fietsboek/locale/de/LC_MESSAGES/messages.mo and b/fietsboek/locale/de/LC_MESSAGES/messages.mo differ diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.po b/fietsboek/locale/de/LC_MESSAGES/messages.po index 8342327..bdd53a7 100644 --- a/fietsboek/locale/de/LC_MESSAGES/messages.po +++ b/fietsboek/locale/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-08-12 22:13+0200\n" +"POT-Creation-Date: 2026-08-13 17:40+0200\n" "PO-Revision-Date: 2022-07-02 17:35+0200\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -61,7 +61,7 @@ msgstr "Maximalgeschwindigkeit" msgid "pdf.table.avg_speed" msgstr "Durchschnittsgeschwindigkeit" -#: fietsboek/summaries.py:384 +#: fietsboek/summaries.py:429 msgid "page.profile.contribution_card.tooltip" msgid_plural "page.profile.contribution_card.tooltips" msgstr[0] "${count} Strecke am ${date}" @@ -1018,27 +1018,35 @@ msgstr "Anzahl der Strecken" msgid "page.profile.contribution_card.title" msgstr "Streckenaktivität" -#: fietsboek/templates/profile_overview.jinja2:142 +#: fietsboek/templates/profile_overview.jinja2:147 +msgid "page.profile.contribution_card.legend.less" +msgstr "Weniger km" + +#: fietsboek/templates/profile_overview.jinja2:154 +msgid "page.profile.contribution_card.legend.more" +msgstr "Mehr km" + +#: fietsboek/templates/profile_overview.jinja2:161 msgid "page.profile.longest_distance_track" msgstr "Weiteste Strecke" -#: fietsboek/templates/profile_overview.jinja2:147 +#: fietsboek/templates/profile_overview.jinja2:166 msgid "page.profile.shortest_distance_track" msgstr "Kürzeste Strecke" -#: fietsboek/templates/profile_overview.jinja2:152 +#: fietsboek/templates/profile_overview.jinja2:171 msgid "page.profile.longest_duration_track" msgstr "Am Längsten Dauernde Strecke" -#: fietsboek/templates/profile_overview.jinja2:157 +#: fietsboek/templates/profile_overview.jinja2:176 msgid "page.profile.shortest_duration_track" msgstr "Am Kürzesten Dauernde Strecke" -#: fietsboek/templates/profile_overview.jinja2:178 +#: fietsboek/templates/profile_overview.jinja2:197 msgid "page.profile.heatmap" msgstr "Heatmap" -#: fietsboek/templates/profile_overview.jinja2:186 +#: fietsboek/templates/profile_overview.jinja2:205 msgid "page.profile.tilehunt" msgstr "Kacheljäger" diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.mo b/fietsboek/locale/en/LC_MESSAGES/messages.mo index 39eabb5..b0c8a9c 100644 Binary files a/fietsboek/locale/en/LC_MESSAGES/messages.mo and b/fietsboek/locale/en/LC_MESSAGES/messages.mo differ diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.po b/fietsboek/locale/en/LC_MESSAGES/messages.po index a8e6c0c..e75d0e0 100644 --- a/fietsboek/locale/en/LC_MESSAGES/messages.po +++ b/fietsboek/locale/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-08-12 22:13+0200\n" +"POT-Creation-Date: 2026-08-13 17:40+0200\n" "PO-Revision-Date: 2023-04-03 20:42+0200\n" "Last-Translator: \n" "Language: en\n" @@ -61,7 +61,7 @@ msgstr "Max Speed" msgid "pdf.table.avg_speed" msgstr "Average Speed" -#: fietsboek/summaries.py:384 +#: fietsboek/summaries.py:429 msgid "page.profile.contribution_card.tooltip" msgid_plural "page.profile.contribution_card.tooltips" msgstr[0] "${count} track on ${date}" @@ -1012,27 +1012,35 @@ msgstr "Number of tracks" msgid "page.profile.contribution_card.title" msgstr "Track Activity" -#: fietsboek/templates/profile_overview.jinja2:142 +#: fietsboek/templates/profile_overview.jinja2:147 +msgid "page.profile.contribution_card.legend.less" +msgstr "Fewer km" + +#: fietsboek/templates/profile_overview.jinja2:154 +msgid "page.profile.contribution_card.legend.more" +msgstr "More km" + +#: fietsboek/templates/profile_overview.jinja2:161 msgid "page.profile.longest_distance_track" msgstr "Longest Track" -#: fietsboek/templates/profile_overview.jinja2:147 +#: fietsboek/templates/profile_overview.jinja2:166 msgid "page.profile.shortest_distance_track" msgstr "Shortest Track" -#: fietsboek/templates/profile_overview.jinja2:152 +#: fietsboek/templates/profile_overview.jinja2:171 msgid "page.profile.longest_duration_track" msgstr "Most Time-Consuming Track" -#: fietsboek/templates/profile_overview.jinja2:157 +#: fietsboek/templates/profile_overview.jinja2:176 msgid "page.profile.shortest_duration_track" msgstr "Quickest Track" -#: fietsboek/templates/profile_overview.jinja2:178 +#: fietsboek/templates/profile_overview.jinja2:197 msgid "page.profile.heatmap" msgstr "Heat Map" -#: fietsboek/templates/profile_overview.jinja2:186 +#: fietsboek/templates/profile_overview.jinja2:205 msgid "page.profile.tilehunt" msgstr "Tilehunt" diff --git a/fietsboek/locale/fietslog.pot b/fietsboek/locale/fietslog.pot index 7f7e325..53f697f 100644 --- a/fietsboek/locale/fietslog.pot +++ b/fietsboek/locale/fietslog.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-08-12 22:13+0200\n" +"POT-Creation-Date: 2026-08-13 17:40+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -57,7 +57,7 @@ msgstr "" msgid "pdf.table.avg_speed" msgstr "" -#: fietsboek/summaries.py:384 +#: fietsboek/summaries.py:429 msgid "page.profile.contribution_card.tooltip" msgid_plural "page.profile.contribution_card.tooltips" msgstr[0] "" @@ -1004,27 +1004,35 @@ msgstr "" msgid "page.profile.contribution_card.title" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:142 +#: fietsboek/templates/profile_overview.jinja2:147 +msgid "page.profile.contribution_card.legend.less" +msgstr "" + +#: fietsboek/templates/profile_overview.jinja2:154 +msgid "page.profile.contribution_card.legend.more" +msgstr "" + +#: fietsboek/templates/profile_overview.jinja2:161 msgid "page.profile.longest_distance_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:147 +#: fietsboek/templates/profile_overview.jinja2:166 msgid "page.profile.shortest_distance_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:152 +#: fietsboek/templates/profile_overview.jinja2:171 msgid "page.profile.longest_duration_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:157 +#: fietsboek/templates/profile_overview.jinja2:176 msgid "page.profile.shortest_duration_track" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:178 +#: fietsboek/templates/profile_overview.jinja2:197 msgid "page.profile.heatmap" msgstr "" -#: fietsboek/templates/profile_overview.jinja2:186 +#: fietsboek/templates/profile_overview.jinja2:205 msgid "page.profile.tilehunt" msgstr "" diff --git a/fietsboek/static/theme.css b/fietsboek/static/theme.css index 78d79e3..d12a9b7 100644 --- a/fietsboek/static/theme.css +++ b/fietsboek/static/theme.css @@ -259,31 +259,38 @@ strong { color: inherit; } -.contributions tbody td.contribs-cell div { +.contribs-cell div { border: 1px solid rgba(0, 0, 0, 0.175); border-radius: calc(0.375rem - 1px); width: 1.1em; height: 1.1em; } -.contributions .contribs-rowhead { + +.contribs-rowhead { font-size: 90%; } -.contributions .contribs-length-0 div { + +.contribs-length-0 div { background-color: #FFFFFF; } -.contributions .contribs-length-1 div { + +.contribs-length-1 div { background-color: #8FF0A4; } -.contributions .contribs-length-2 div { + +.contribs-length-2 div { background-color: #75DD95; } -.contributions .contribs-length-3 div { + +.contribs-length-3 div { background-color: #5BC987; } -.contributions .contribs-length-4 div { + +.contribs-length-4 div { background-color: #40B678; } -.contributions .contribs-length-5 div { + +.contribs-length-5 div { background-color: #26A269; } diff --git a/fietsboek/static/theme.css.map b/fietsboek/static/theme.css.map index 9408c30..acade8d 100644 --- a/fietsboek/static/theme.css.map +++ b/fietsboek/static/theme.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAMA;EACE;EACA;EAEA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;AAEF;EACE;;;AAIJ;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../asset-sources/theme.scss"],"names":[],"mappings":"AAAA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;AAEA;EACE;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAlCJ;EAqCE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACI;;;AAGJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEF;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;;AACA;EACE;;AAGJ;EACE;EACA;;AACA;EACE;;AAIJ;EACE;EACA;;;AAKF;EACE;EACA;EAEA;EACA;;;AAIJ;EACE;;;AAGF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAGF;AACA;EACE;;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI,eACE;;;AAIJ;EACE;;AAGF;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;;AAIJ;EACE;;;AAGF;AACA;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE","file":"theme.css"} \ No newline at end of file diff --git a/fietsboek/templates/profile_overview.jinja2 b/fietsboek/templates/profile_overview.jinja2 index fbb1804..381efb6 100644 --- a/fietsboek/templates/profile_overview.jinja2 +++ b/fietsboek/templates/profile_overview.jinja2 @@ -140,6 +140,23 @@
+
+ + + + + + + + + + + + + +
{{ _("page.profile.contribution_card.legend.less") }}
{{ _("page.profile.contribution_card.legend.more") }}
+
+ {% if total.longest_distance_track %}

{{ _("page.profile.longest_distance_track") }}

{{ render_track_card(total.longest_distance_track) }} -- cgit v1.2.3 From 4ac0a7a84425ed86ebbe70fded7dae6f0a65b45d Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 13 Aug 2026 17:50:05 +0200 Subject: make track contributions more responsive --- fietsboek/templates/profile_overview.jinja2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fietsboek/templates/profile_overview.jinja2 b/fietsboek/templates/profile_overview.jinja2 index 381efb6..9914146 100644 --- a/fietsboek/templates/profile_overview.jinja2 +++ b/fietsboek/templates/profile_overview.jinja2 @@ -110,7 +110,7 @@

{{ _("page.profile.contribution_card.title") }}

-
+
-- cgit v1.2.3 From b5d155c0aca75ca6a548b622117df56e03b2993a Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 13 Aug 2026 18:22:22 +0200 Subject: make cells in year contributions clickable --- fietsboek/summaries.py | 18 ++++++++++++++++++ fietsboek/templates/profile_overview.jinja2 | 6 ++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index 8c54d5f..9513917 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -7,6 +7,7 @@ from typing import Iterator, Optional from babel import Locale from babel.dates import format_date from pyramid.i18n import Localizer +from pyramid.request import Request from . import util from .models.track import TrackWithMetadata @@ -435,5 +436,22 @@ class DayContributions: }, ) + def browse_url(self, request: Request) -> str: + """Returns a URL to the browse page with filters for this day applied. + + :param request: The pyramid request. + :return: The URL. + """ + datestring = self.day.strftime("%Y-%m-%d") + return request.route_url( + "browse", + _query={ + "type[]": "ORGANIC", + "show-only[]": "user-tagged", + "min-date": datestring, + "max-date": datestring, + }, + ) + __all__ = ["Summary", "YearSummary", "MonthSummary", "CumulativeStats", "YearContributions"] diff --git a/fietsboek/templates/profile_overview.jinja2 b/fietsboek/templates/profile_overview.jinja2 index 9914146..a088ba5 100644 --- a/fietsboek/templates/profile_overview.jinja2 +++ b/fietsboek/templates/profile_overview.jinja2 @@ -130,8 +130,10 @@ {% for cell in row %} {% endfor %} -- cgit v1.2.3 From 349ca118f40fb591f4b7dd620ae812c13de377b4 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 13 Aug 2026 18:23:36 +0200 Subject: add DayContributions to __all__ --- fietsboek/summaries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index 9513917..8cba95c 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -454,4 +454,4 @@ class DayContributions: ) -__all__ = ["Summary", "YearSummary", "MonthSummary", "CumulativeStats", "YearContributions"] +__all__ = ["Summary", "YearSummary", "MonthSummary", "CumulativeStats", "YearContributions", "DayContributions"] -- cgit v1.2.3 From ea162c20d5a9c7025d6f5c80b4c8eb1c306e1e68 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Thu, 13 Aug 2026 18:26:10 +0200 Subject: fix formatting --- fietsboek/summaries.py | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/fietsboek/summaries.py b/fietsboek/summaries.py index 8cba95c..502e2f9 100644 --- a/fietsboek/summaries.py +++ b/fietsboek/summaries.py @@ -347,17 +347,21 @@ class YearContributions: """ loc = Locale.parse(localizer.locale_name) days = loc.days["stand-alone"]["abbreviated"] - return iter([ - days[0], - None, - None, - days[3], - None, - None, - days[6], - ]) - - def rows_with_heads(self, localizer: Localizer) -> Iterator[tuple[str | None, Iterator[DayContributions]]]: + return iter( + [ + days[0], + None, + None, + days[3], + None, + None, + days[6], + ] + ) + + def rows_with_heads( + self, localizer: Localizer + ) -> Iterator[tuple[str | None, Iterator[DayContributions]]]: """Returns each row with its associated heading (weekday name). :param localizer: The localizer to use. @@ -454,4 +458,11 @@ class DayContributions: ) -__all__ = ["Summary", "YearSummary", "MonthSummary", "CumulativeStats", "YearContributions", "DayContributions"] +__all__ = [ + "Summary", + "YearSummary", + "MonthSummary", + "CumulativeStats", + "YearContributions", + "DayContributions", +] -- cgit v1.2.3
{{ rowhead | default("", true) }} - -
+ + +
+