[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: :LOGBOOK:
CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20 CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20
:END: :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: ** TODO [#C] Add sentiment parsing for Scrobbles with notes :vrobbler:project:scrobbles:sentiment:
:PROPERTIES: :PROPERTIES:
:ID: 37781d6a-f3b0-48b2-bf98-33c2c791cf85 :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 date is being viewed, and the highlighted value on the graph would be the date
being viewed. 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: ** DONE [#A] Orgmode tasks are not updated if in progress :tasks:orgmode:bug:
:PROPERTIES: :PROPERTIES:
:ID: 7dcebb2c-7c4c-4ac5-bee6-c2e36c3811f9 :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 import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator 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 django.db.models.query import QuerySet
from rest_framework.authentication import TokenAuthentication from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
@ -367,6 +367,7 @@ class ScrobbleListView(LoginRequiredMixin, ListView):
else: else:
tag_list = [] tag_list = []
self.tag_list = tag_list self.tag_list = tag_list
self._full_queryset = qs
return qs return qs
def _compute_overlap_groups(self, scrobbles): def _compute_overlap_groups(self, scrobbles):
@ -433,6 +434,13 @@ class ScrobbleListView(LoginRequiredMixin, ListView):
ctx["tag_list"] = getattr(self, "tag_list", []) ctx["tag_list"] = getattr(self, "tag_list", [])
scrobbles = list(ctx.get("object_list", [])) scrobbles = list(ctx.get("object_list", []))
ctx["overlap_map"] = self._compute_overlap_groups(scrobbles) 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 return ctx

View File

@ -8,21 +8,20 @@ def natural_duration(value):
if not value: if not value:
return return
value = int(value) value = int(value)
total_minutes = int(value / 60) days = int(value / 86400)
hours = int(total_minutes / 60) remainder = value % 86400
minutes = total_minutes - (hours * 60) hours = int(remainder / 3600)
seconds = value % 60 minutes = int((remainder % 3600) / 60)
value_str = "" seconds = remainder % 60
if seconds: parts = []
value_str = f"{seconds} seconds" if days:
if minutes: parts.append(f"{days} day{'s' if days != 1 else ''}")
if value_str:
value_str = f"{minutes} minutes, " + value_str
else:
value_str = f"{minutes} minutes"
if hours: if hours:
if value_str: parts.append(f"{hours} hour{'s' if hours != 1 else ''}")
value_str = f"{hours} hours, " + value_str if minutes:
else: parts.append(f"{minutes} minute{'s' if minutes != 1 else ''}")
value_str = f"{hours} hours" if seconds or not parts:
return value_str 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> <h1 class="h2">All Scrobbles</h1>
{% if tag_list %} {% if tag_list %}
<h6 class="text-muted">Tagged {{ tag_list|join:", " }}</h6> <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 %} {% endif %}
</div> </div>
</div> </div>