diff options
-rw-r--r-- | fietsboek/jinja2.py | 3 | ||||
-rw-r--r-- | fietsboek/views/profile.py | 27 | ||||
-rw-r--r-- | tests/unit/views/test_profile.py | 21 |
3 files changed, 41 insertions, 10 deletions
diff --git a/fietsboek/jinja2.py b/fietsboek/jinja2.py index 3832e66..5106c38 100644 --- a/fietsboek/jinja2.py +++ b/fietsboek/jinja2.py @@ -37,6 +37,8 @@ def filter_format_datetime(ctx: Context, value: datetime.datetime, format: str=" :param format: The format string, see https://babel.pocoo.org/en/latest/dates.html. :return: The formatted date. """ + # We redefine format because it's the same name as used by babel + # pylint: disable=redefined-builtin request = ctx.get("request") locale = request.localizer.locale_name return format_datetime(value, format=format, locale=locale) @@ -51,6 +53,7 @@ def filter_format_date(ctx: Context, value: datetime.date, format: str="medium") :param format: The format string, see https://babel.pocoo.org/en/latest/dates.html. :return: The formatted date. """ + # pylint: disable=redefined-builtin request = ctx.get("request") locale = request.localizer.locale_name return format_date(value, format=format, locale=locale) diff --git a/fietsboek/views/profile.py b/fietsboek/views/profile.py index 0127cd3..a002a81 100644 --- a/fietsboek/views/profile.py +++ b/fietsboek/views/profile.py @@ -7,6 +7,7 @@ import urllib.parse from dataclasses import dataclass from typing import Optional +import sqlalchemy from pyramid.httpexceptions import HTTPNotFound from pyramid.request import Request from pyramid.response import Response @@ -250,22 +251,28 @@ def user_calendar_ym(request: Request) -> dict: def cell_style(tracks: list[TrackWithMetadata]) -> str: + """Returns the correct CSS style for a day with the given tracks. + + The style is determined by the amount of kilometers cycled on that day. + + :param tracks: The list of tracks. + :return: The CSS style for the calendar cell. + """ length = sum(track.length for track in tracks) # kilometers length = length / 1000 # Arbitrary cutoffs for the moment if length == 0: return "cell-length-0" - elif length <= 25: + if length <= 25: return "cell-length-1" - elif length <= 50: + if length <= 50: return "cell-length-2" - elif length <= 75: + if length <= 75: return "cell-length-3" - elif length <= 100: + if length <= 100: return "cell-length-4" - else: - return "cell-length-5" + return "cell-length-5" def calendar_rows( @@ -308,7 +315,7 @@ def calendar_rows( # Step 3: Associate days and tracks days = [ - (day, [track for track in tracks if track.date.date() == day]) + (day, [track for track in tracks if track.date and track.date.date() == day]) for day in days ] @@ -319,7 +326,7 @@ def calendar_rows( # Step 4: Layout rows = [] - row = [] + row: list[None | tuple[datetime.date, str, list[TrackWithMetadata]]] = [] while days: next_day = days.pop(0) # This should only matter in the first row, when the month does not @@ -338,7 +345,7 @@ def calendar_rows( return rows -def prev_next_month(date: datetime.date) -> datetime.date: +def prev_next_month(date: datetime.date) -> tuple[datetime.date, datetime.date]: """Return the previous and next months. Months are normalized to the first day of the month. @@ -418,4 +425,4 @@ def json_summary(request: Request) -> Response: return {y.year: {m.month: m.total_length for m in y} for y in summary} -__all__ = ["profile", "user_tile", "json_summary"] +__all__ = ["profile", "user_tile", "user_calendar_ym", "json_summary"] diff --git a/tests/unit/views/test_profile.py b/tests/unit/views/test_profile.py new file mode 100644 index 0000000..bc8e794 --- /dev/null +++ b/tests/unit/views/test_profile.py @@ -0,0 +1,21 @@ +import pytest +import datetime + +from fietsboek.views import profile + + +@pytest.mark.parametrize("current, prev_month, next_month", [ + ((2024, 2, 1), (2024, 1, 1), (2024, 3, 1)), + ((2024, 1, 1), (2023, 12, 1), (2024, 2, 1)), + ((2024, 12, 1), (2024, 11, 1), (2025, 1, 1)), + ((2024, 5, 5), (2024, 4, 1), (2024, 6, 1)), + ((2024, 7, 31), (2024, 6, 1), (2024, 8, 1)), +]) +def test_prev_next_month(current, prev_month, next_month): + current = datetime.date(*current) + prev_month = datetime.date(*prev_month) + next_month = datetime.date(*next_month) + + actual_prev, actual_next = profile.prev_next_month(current) + assert actual_prev == prev_month + assert actual_next == next_month |