From 2e7d6364a2295498bc167284e6edf2d342bc996f Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Wed, 18 Mar 2026 10:23:30 -0400 Subject: [PATCH] [templates] Adding some aggregation widgets --- vrobbler/apps/videos/views.py | 71 +++++++++++++++ vrobbler/apps/webpages/views.py | 55 ++++++++++++ vrobbler/templates/base_detail.html | 17 +++- vrobbler/templates/base_list.html | 12 ++- vrobbler/templates/scrobbles/_top_charts.html | 44 ---------- .../templates/scrobbles/scrobble_list.html | 2 + vrobbler/templates/videos/video_list.html | 88 +++++++++++++++++++ vrobbler/templates/webpages/webpage_list.html | 45 ++++++++++ 8 files changed, 288 insertions(+), 46 deletions(-) diff --git a/vrobbler/apps/videos/views.py b/vrobbler/apps/videos/views.py index 526ad47..bba1505 100644 --- a/vrobbler/apps/videos/views.py +++ b/vrobbler/apps/videos/views.py @@ -1,5 +1,8 @@ +import datetime from django.contrib.auth.mixins import LoginRequiredMixin +from django.utils import timezone from django.views import generic +from scrobbles.models import Scrobble from videos.models import Channel, Series, Video from scrobbles.views import ScrobbleableListView, ScrobbleableDetailView @@ -50,6 +53,74 @@ class ChannelDetailView(LoginRequiredMixin, generic.DetailView): class VideoListView(ScrobbleableListView): model = Video + def get_context_data(self, **kwargs): + context_data = super().get_context_data(**kwargs) + user = self.request.user + now = timezone.now() + start_day_of_week = now - datetime.timedelta(days=now.weekday()) + start_day_of_month = now.replace(day=1) + + movie_scrobbles = Scrobble.objects.filter( + user=user, + video__video_type=Video.VideoType.MOVIE, + played_to_completion=True, + ) + context_data["videos_this_week"] = movie_scrobbles.filter( + timestamp__gte=start_day_of_week + ).order_by("-timestamp") + context_data["videos_this_month"] = movie_scrobbles.filter( + timestamp__gte=start_day_of_month + ).order_by("-timestamp") + + youtube_scrobbles_this_week = Scrobble.objects.filter( + user=user, + video__video_type=Video.VideoType.YOUTUBE, + video__channel__isnull=False, + timestamp__gte=start_day_of_week, + ).select_related("video", "video__channel") + + youtube_scrobbles_this_month = Scrobble.objects.filter( + user=user, + video__video_type=Video.VideoType.YOUTUBE, + video__channel__isnull=False, + timestamp__gte=start_day_of_month, + ).select_related("video", "video__channel") + + channels_this_week = {} + for scrobble in youtube_scrobbles_this_week: + channel = scrobble.video.channel + if channel: + channels_this_week[channel.id] = { + "channel": channel, + "count": channels_this_week.get(channel.id, {}).get( + "count", 0 + ) + + 1, + } + + channels_this_month = {} + for scrobble in youtube_scrobbles_this_month: + channel = scrobble.video.channel + if channel: + channels_this_month[channel.id] = { + "channel": channel, + "count": channels_this_month.get(channel.id, {}).get( + "count", 0 + ) + + 1, + } + + context_data["channels_this_week"] = sorted( + channels_this_week.values(), key=lambda x: x["count"], reverse=True + ) + context_data["channels_this_month"] = sorted( + channels_this_month.values(), + key=lambda x: x["count"], + reverse=True, + ) + + return context_data + class VideoDetailView(ScrobbleableDetailView): model = Video diff --git a/vrobbler/apps/webpages/views.py b/vrobbler/apps/webpages/views.py index 85b09e8..f0577b2 100644 --- a/vrobbler/apps/webpages/views.py +++ b/vrobbler/apps/webpages/views.py @@ -1,17 +1,72 @@ +import datetime from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponseRedirect from django.shortcuts import redirect from django.urls import reverse +from django.utils import timezone from django.views import generic from webpages.forms import WebPageReadForm from webpages.models import WebPage +from scrobbles.models import Scrobble from scrobbles.views import ScrobbleableListView, ScrobbleableDetailView class WebPageListView(ScrobbleableListView): model = WebPage + def get_context_data(self, **kwargs): + context_data = super().get_context_data(**kwargs) + user = self.request.user + now = timezone.now() + start_day_of_week = now - datetime.timedelta(days=now.weekday()) + start_day_of_month = now.replace(day=1) + + scrobbles_this_week = Scrobble.objects.filter( + user=user, + web_page__isnull=False, + timestamp__gte=start_day_of_week, + ).select_related("web_page", "web_page__domain") + + scrobbles_this_month = Scrobble.objects.filter( + user=user, + web_page__isnull=False, + timestamp__gte=start_day_of_month, + ).select_related("web_page", "web_page__domain") + + domains_this_week = {} + for scrobble in scrobbles_this_week: + domain = scrobble.web_page.domain + if domain: + domains_this_week[domain.id] = { + "domain": domain, + "count": domains_this_week.get(domain.id, {}).get( + "count", 0 + ) + + 1, + } + + domains_this_month = {} + for scrobble in scrobbles_this_month: + domain = scrobble.web_page.domain + if domain: + domains_this_month[domain.id] = { + "domain": domain, + "count": domains_this_month.get(domain.id, {}).get( + "count", 0 + ) + + 1, + } + + context_data["domains_this_week"] = sorted( + domains_this_week.values(), key=lambda x: x["count"], reverse=True + ) + context_data["domains_this_month"] = sorted( + domains_this_month.values(), key=lambda x: x["count"], reverse=True + ) + + return context_data + class WebPageDetailView(ScrobbleableDetailView): model = WebPage diff --git a/vrobbler/templates/base_detail.html b/vrobbler/templates/base_detail.html index 034b7b6..37d10d6 100644 --- a/vrobbler/templates/base_detail.html +++ b/vrobbler/templates/base_detail.html @@ -5,9 +5,21 @@

{% block title %}{% endblock %}

+ {% if user.is_authenticated %}
- +
+ +
+
+ + {% block charts_button %}{% endblock %} +
+ {% endif %}
@@ -16,3 +28,6 @@ {% endblock %} + +{% block extra_modals %} +{% endblock %} diff --git a/vrobbler/templates/base_list.html b/vrobbler/templates/base_list.html index b0d94bc..85b6a22 100644 --- a/vrobbler/templates/base_list.html +++ b/vrobbler/templates/base_list.html @@ -7,14 +7,24 @@ class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">

{% block title %}{% endblock %}

+ {% if user.is_authenticated %} +
+
+ +
+
+ {% endif %}
{% if view == 'grid' %}
+ {% block charts_button %}{% endblock %}
diff --git a/vrobbler/templates/scrobbles/_top_charts.html b/vrobbler/templates/scrobbles/_top_charts.html index 1d2d7b6..4340bd1 100644 --- a/vrobbler/templates/scrobbles/_top_charts.html +++ b/vrobbler/templates/scrobbles/_top_charts.html @@ -642,47 +642,3 @@ {% endfor %} - - {% if videos_this_week or videos_this_month %} -
-

Movies Watched

- - {% if videos_this_week %} -

This Week

-
- - - {% for scrobble in videos_this_week %} - - - - - {% empty %} - - {% endfor %} - -
{{scrobble.video}}{{scrobble.timestamp|date:"N d"}}
No movies watched this week
-
- {% endif %} - - {% if videos_this_month %} -

This Month

-
- - - {% for scrobble in videos_this_month %} - - - - - {% empty %} - - {% endfor %} - -
{{scrobble.video}}{{scrobble.timestamp|date:"N d"}}
No movies watched this month
-
- {% endif %} - -
- {% endif %} - diff --git a/vrobbler/templates/scrobbles/scrobble_list.html b/vrobbler/templates/scrobbles/scrobble_list.html index f733178..115cb93 100644 --- a/vrobbler/templates/scrobbles/scrobble_list.html +++ b/vrobbler/templates/scrobbles/scrobble_list.html @@ -95,7 +95,9 @@ + {% block charts_button %} Charts + {% endblock %} {% endif %} +{% endif %} +
{% include "_scrobblable_list.html" %}
diff --git a/vrobbler/templates/webpages/webpage_list.html b/vrobbler/templates/webpages/webpage_list.html index 8f7ddae..86ae4a1 100644 --- a/vrobbler/templates/webpages/webpage_list.html +++ b/vrobbler/templates/webpages/webpage_list.html @@ -4,6 +4,51 @@ {% block title %}Webpages{% endblock %} {% block lists %} +{% if domains_this_week or domains_this_month %} +
+
+

Domains Read

+ + {% if domains_this_week %} +

This Week

+
+ + + {% for item in domains_this_week %} + + + + + {% empty %} + + {% endfor %} + +
{{item.domain}}{{item.count}} pages
No pages read this week
+
+ {% endif %} + + {% if domains_this_month %} +

This Month

+
+ + + {% for item in domains_this_month %} + + + + + {% empty %} + + {% endfor %} + +
{{item.domain}}{{item.count}} pages
No pages read this month
+
+ {% endif %} + +
+
+{% endif %} +