From 042a3eb737936082a56598413bff174f12714d5f Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Mon, 15 Jun 2026 15:26:46 -0400 Subject: [PATCH] [templates] Add aggregate data --- PROJECT.org | 15 +++++++-- vrobbler/apps/scrobbles/views.py | 31 +++++++++++++++++++ .../templates/_longplay_scrobblable_list.html | 6 +++- vrobbler/templates/books/book_detail.html | 6 +++- .../templates/bricksets/brickset_detail.html | 6 +++- .../templates/scrobbles/scrobble_detail.html | 14 +++++++-- vrobbler/templates/tasks/task_detail.html | 6 +++- vrobbler/templates/tasks/task_list.html | 2 +- .../videogames/videogame_detail.html | 6 +++- .../templates/videogames/videogame_list.html | 2 +- 10 files changed, 83 insertions(+), 11 deletions(-) diff --git a/PROJECT.org b/PROJECT.org index e03ccf4..d0ef1cf 100644 --- a/PROJECT.org +++ b/PROJECT.org @@ -88,7 +88,7 @@ fetching and simple saving. *** Metadata sources **** Scraper -* Backlog [0/20] :vrobbler:project:personal: +* Backlog [1/21] :vrobbler:project:personal: ** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles: :PROPERTIES: :ID: 702462cf-d54b-48c6-8a7c-78b8de751deb @@ -594,7 +594,18 @@ named constants for maintainability. - ~vrobbler/apps/webpages/models.py~ (line 290) -- ="url"= - ~vrobbler/apps/scrobbles/importers/tsv.py~ (line 55) -- ="S"= completion status -** TODO [#C] Show time per scrobble in long play lists and total time playing :templates:longplay:scrobbles: +** DONE [#C] Show time per scrobble in long play lists and total time playing :templates:longplay:scrobbles: +:PROPERTIES: +:ID: b3d16230-8ec5-46db-b166-59e98d0ee06c +:END: + +*** Description + +Long play time should be show in the table of scrobbles on a media detail page. +The total time spent in a long play that's either no completed yet or completed +should be displayed as well. If completed, the date finished should be shown as +well. + * Version 52.0 [5/5] ** DONE [#B] Allow marking media as long play complete from detail page :templates:scrobbles:longplay: :PROPERTIES: diff --git a/vrobbler/apps/scrobbles/views.py b/vrobbler/apps/scrobbles/views.py index d61d2ac..92fb3bc 100644 --- a/vrobbler/apps/scrobbles/views.py +++ b/vrobbler/apps/scrobbles/views.py @@ -206,6 +206,19 @@ class ScrobbleableDetailView(ChartContextMixin, DetailView): context_data["scrobbles"] = page_obj.object_list context_data["is_paginated"] = paginator.num_pages > 1 + media = self.object + if hasattr(media, "is_long_play_media") and media.is_long_play_media(): + qs = media.scrobble_set.filter(user=self.request.user) + completed = qs.filter(long_play_complete=True).order_by("-timestamp").first() + if completed and completed.long_play_seconds: + context_data["long_play_total_seconds"] = completed.long_play_seconds + context_data["long_play_finished_date"] = completed.timestamp + else: + latest_finished = qs.filter(played_to_completion=True).order_by("-timestamp").first() + if latest_finished and latest_finished.long_play_seconds: + context_data["long_play_total_seconds"] = latest_finished.long_play_seconds + context_data["long_play_finished_date"] = None + return context_data @@ -1297,6 +1310,24 @@ class ScrobbleDetailView(DetailView): else: context["has_mopidy_uri"] = False + if self.object.is_long_play and fk_field: + all_scrobbles = Scrobble.objects.filter( + user=user, **{fk_field: media_obj} + ) + completed = all_scrobbles.filter( + long_play_complete=True + ).order_by("-timestamp").first() + if completed and completed.long_play_seconds: + context["long_play_total_seconds"] = completed.long_play_seconds + context["long_play_finished_date"] = completed.timestamp + else: + latest_finished = all_scrobbles.filter( + played_to_completion=True + ).order_by("-timestamp").first() + if latest_finished and latest_finished.long_play_seconds: + context["long_play_total_seconds"] = latest_finished.long_play_seconds + context["long_play_finished_date"] = None + return context diff --git a/vrobbler/templates/_longplay_scrobblable_list.html b/vrobbler/templates/_longplay_scrobblable_list.html index e6d48fc..18428bb 100644 --- a/vrobbler/templates/_longplay_scrobblable_list.html +++ b/vrobbler/templates/_longplay_scrobblable_list.html @@ -6,6 +6,7 @@ Latest Title + Time Scrobbles Complete Start @@ -15,16 +16,19 @@ {% for obj in object_list %} {% if obj.title %} + {% with last=obj.scrobble_set.last %} - {{obj.scrobble_set.last.local_timestamp}} + {{last.local_timestamp}} {{obj}} {% if request.user.is_authenticated %} + {% if last.long_play_seconds %}{{ last.long_play_seconds|natural_duration }}{% elif last.elapsed_time %}{{ last.elapsed_time|natural_duration }}{% endif %} {{obj.scrobble_count}} {% if obj.scrobble_set.last.long_play_complete == True %}Yes{% else %}No{% endif %} Scrobble Finish {% endif %} + {% endwith %} {% endif %} {% endfor %} diff --git a/vrobbler/templates/books/book_detail.html b/vrobbler/templates/books/book_detail.html index 8bbe953..1dc5dd7 100644 --- a/vrobbler/templates/books/book_detail.html +++ b/vrobbler/templates/books/book_detail.html @@ -33,7 +33,11 @@

Read next issue

{% endif %} -

{{scrobbles.count}} scrobbles

+

+ {{scrobbles.count}} scrobbles + {% if long_play_total_seconds %} | Total time: {{ long_play_total_seconds|natural_duration }}{% endif %} + {% if long_play_finished_date %} | Finished: {{ long_play_finished_date|date:"M d, Y" }}{% endif %} +

Resume reading

diff --git a/vrobbler/templates/bricksets/brickset_detail.html b/vrobbler/templates/bricksets/brickset_detail.html index 731d83c..814fe67 100644 --- a/vrobbler/templates/bricksets/brickset_detail.html +++ b/vrobbler/templates/bricksets/brickset_detail.html @@ -26,7 +26,11 @@
-

{{scrobbles.count}} scrobbles

+

+ {{scrobbles.count}} scrobbles + {% if long_play_total_seconds %} | Total time: {{ long_play_total_seconds|natural_duration }}{% endif %} + {% if long_play_finished_date %} | Finished: {{ long_play_finished_date|date:"M d, Y" }}{% endif %} +

diff --git a/vrobbler/templates/scrobbles/scrobble_detail.html b/vrobbler/templates/scrobbles/scrobble_detail.html index d11b273..0d0cebe 100644 --- a/vrobbler/templates/scrobbles/scrobble_detail.html +++ b/vrobbler/templates/scrobbles/scrobble_detail.html @@ -264,7 +264,13 @@

All scrobbles of this {{ object.media_type|lower }}

{% if related_scrobbles %} -

{{ related_scrobbles.paginator.count }} scrobble{{ related_scrobbles.paginator.count|pluralize }}

+

+ {{ related_scrobbles.paginator.count }} scrobble{{ related_scrobbles.paginator.count|pluralize }} + {% if object.is_long_play and long_play_total_seconds %} + | Total time: {{ long_play_total_seconds|natural_duration }} + {% if long_play_finished_date %} | Finished: {{ long_play_finished_date|date:"M d, Y" }}{% endif %} + {% endif %} +

@@ -281,7 +287,11 @@ {% if scrobble.media_type == "Task" and scrobble.logdata.title %}{{ scrobble.media_obj.title }}: {{ scrobble.logdata.title }}{% else %}{{ scrobble.media_obj.title|default:scrobble.media_obj }}{% endif %} {% endfor %} diff --git a/vrobbler/templates/tasks/task_detail.html b/vrobbler/templates/tasks/task_detail.html index 7c50335..f8cdc4a 100644 --- a/vrobbler/templates/tasks/task_detail.html +++ b/vrobbler/templates/tasks/task_detail.html @@ -50,7 +50,11 @@ {% endif %}
-

{{scrobbles.count}} scrobbles

+

+ {{scrobbles.count}} scrobbles + {% if long_play_total_seconds %} | Total time: {{ long_play_total_seconds|natural_duration }}{% endif %} + {% if long_play_finished_date %} | Finished: {{ long_play_finished_date|date:"M d, Y" }}{% endif %} +

Play again

diff --git a/vrobbler/templates/tasks/task_list.html b/vrobbler/templates/tasks/task_list.html index b0cca16..62edc38 100644 --- a/vrobbler/templates/tasks/task_list.html +++ b/vrobbler/templates/tasks/task_list.html @@ -26,7 +26,7 @@ {% block lists %}
-
{% include "_scrobblable_list.html" %}
+
{% include "_longplay_scrobblable_list.html" %}
{% endblock %} diff --git a/vrobbler/templates/videogames/videogame_detail.html b/vrobbler/templates/videogames/videogame_detail.html index d1f1cbe..c635899 100644 --- a/vrobbler/templates/videogames/videogame_detail.html +++ b/vrobbler/templates/videogames/videogame_detail.html @@ -59,7 +59,11 @@
-

{{scrobbles.count}} scrobbles

+

+ {{scrobbles.count}} scrobbles + {% if long_play_total_seconds %} | Total time: {{ long_play_total_seconds|natural_duration }}{% endif %} + {% if long_play_finished_date %} | Finished: {{ long_play_finished_date|date:"M d, Y" }}{% endif %} +

Play again

diff --git a/vrobbler/templates/videogames/videogame_list.html b/vrobbler/templates/videogames/videogame_list.html index b8f3436..a40e8ae 100644 --- a/vrobbler/templates/videogames/videogame_list.html +++ b/vrobbler/templates/videogames/videogame_list.html @@ -16,7 +16,7 @@
- {% include "_scrobblable_list.html" %} + {% include "_longplay_scrobblable_list.html" %}
- {% if scrobble.playback_position_seconds %}{{ scrobble.playback_position_seconds|natural_duration }}{% endif %} + {% if scrobble.is_long_play and scrobble.long_play_seconds %} + {{ scrobble.playback_position_seconds|natural_duration }} ({{ scrobble.long_play_seconds|natural_duration }} total) + {% elif scrobble.playback_position_seconds %} + {{ scrobble.playback_position_seconds|natural_duration }} + {% endif %}