[scrobbles] Add total time to tag views

This commit is contained in:
2026-06-04 22:01:35 -04:00
parent 85bddb6cba
commit 50b10689fc
4 changed files with 39 additions and 19 deletions

View File

@ -93,7 +93,7 @@ fetching and simple saving.
:LOGBOOK:
CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20
:END:
* Backlog [3/17] :vrobbler:project:personal:
* Backlog [4/18] :vrobbler:project:personal:
** TODO [#C] Add sentiment parsing for Scrobbles with notes :vrobbler:project:scrobbles:sentiment:
:PROPERTIES:
:ID: 37781d6a-f3b0-48b2-bf98-33c2c791cf85
@ -503,6 +503,16 @@ The graph would contain all Weigh-in scrobbles for that user, no matter which
date is being viewed, and the highlighted value on the graph would be the date
being viewed.
** DONE [#B] When viewing scrobbles by tag, sum the total time :scrobbles:tags:
:PROPERTIES:
:ID: d51f23df-c2c5-4e1a-b000-67c89032af02
:END:
*** Description
On scrobbles filtered by tags, we should see a sum of the time spent doing those tasks, in a human
readable format like "X days, X hours, X minutes and X seconds"
** DONE [#A] Orgmode tasks are not updated if in progress :tasks:orgmode:bug:
:PROPERTIES:
:ID: 7dcebb2c-7c4c-4ac5-bee6-c2e36c3811f9

View File

@ -14,7 +14,7 @@ from django.contrib import messages
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db.models import Count, Max, Q
from django.db.models import Count, Max, Q, Sum
from django.db.models.query import QuerySet
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
@ -367,6 +367,7 @@ class ScrobbleListView(LoginRequiredMixin, ListView):
else:
tag_list = []
self.tag_list = tag_list
self._full_queryset = qs
return qs
def _compute_overlap_groups(self, scrobbles):
@ -433,6 +434,13 @@ class ScrobbleListView(LoginRequiredMixin, ListView):
ctx["tag_list"] = getattr(self, "tag_list", [])
scrobbles = list(ctx.get("object_list", []))
ctx["overlap_map"] = self._compute_overlap_groups(scrobbles)
full_qs = getattr(self, "_full_queryset", None)
if full_qs is not None and getattr(self, "tag_list", []):
total = (
full_qs.aggregate(total=Sum("playback_position_seconds"))["total"]
or 0
)
ctx["total_time_seconds"] = total
return ctx

View File

@ -8,21 +8,20 @@ def natural_duration(value):
if not value:
return
value = int(value)
total_minutes = int(value / 60)
hours = int(total_minutes / 60)
minutes = total_minutes - (hours * 60)
seconds = value % 60
value_str = ""
if seconds:
value_str = f"{seconds} seconds"
if minutes:
if value_str:
value_str = f"{minutes} minutes, " + value_str
else:
value_str = f"{minutes} minutes"
days = int(value / 86400)
remainder = value % 86400
hours = int(remainder / 3600)
minutes = int((remainder % 3600) / 60)
seconds = remainder % 60
parts = []
if days:
parts.append(f"{days} day{'s' if days != 1 else ''}")
if hours:
if value_str:
value_str = f"{hours} hours, " + value_str
else:
value_str = f"{hours} hours"
return value_str
parts.append(f"{hours} hour{'s' if hours != 1 else ''}")
if minutes:
parts.append(f"{minutes} minute{'s' if minutes != 1 else ''}")
if seconds or not parts:
parts.append(f"{seconds} second{'s' if seconds != 1 else ''}")
if len(parts) == 1:
return parts[0]
return ", ".join(parts[:-1]) + " and " + parts[-1]

View File

@ -9,6 +9,9 @@
<h1 class="h2">All Scrobbles</h1>
{% if tag_list %}
<h6 class="text-muted">Tagged {{ tag_list|join:", " }}</h6>
{% if total_time_seconds %}
<p class="text-muted small mb-0">Total time: {{ total_time_seconds|natural_duration }}</p>
{% endif %}
{% endif %}
</div>
</div>