From a99dca246b658db57ea407c5cb7c835a8682152c Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 28 Feb 2023 01:58:22 -0500 Subject: [PATCH] Fix chart display --- vrobbler/apps/music/views.py | 21 ++- vrobbler/apps/scrobbles/models.py | 17 +- vrobbler/apps/scrobbles/views.py | 98 ++++------ vrobbler/templates/music/artist_detail.html | 3 + vrobbler/templates/music/track_detail.html | 44 ++++- vrobbler/templates/scrobbles/chart_index.html | 173 ++++++++++-------- 6 files changed, 214 insertions(+), 142 deletions(-) diff --git a/vrobbler/apps/music/views.py b/vrobbler/apps/music/views.py index f2f7b60..c3cbf3f 100644 --- a/vrobbler/apps/music/views.py +++ b/vrobbler/apps/music/views.py @@ -1,6 +1,8 @@ -from django.db.models import Count +from datetime import timedelta +from django.utils import timezone from django.views import generic -from music.models import Track, Artist, Album +from music.models import Album, Artist, Track +from scrobbles.models import ChartRecord from scrobbles.stats import get_scrobble_count_qs @@ -17,6 +19,14 @@ class TrackDetailView(generic.DetailView): model = Track slug_field = 'uuid' + def get_context_data(self, **kwargs): + context_data = super().get_context_data(**kwargs) + + context_data['charts'] = ChartRecord.objects.filter( + track=self.object, rank__in=[1, 2, 3] + ) + return context_data + class ArtistListView(generic.ListView): model = Artist @@ -29,6 +39,13 @@ class ArtistDetailView(generic.DetailView): model = Artist slug_field = 'uuid' + def get_context_data(self, **kwargs): + context_data = super().get_context_data(**kwargs) + context_data['charts'] = ChartRecord.objects.filter( + artist=self.object, rank__in=[1, 2, 3] + ) + return context_data + class AlbumListView(generic.ListView): model = Album diff --git a/vrobbler/apps/scrobbles/models.py b/vrobbler/apps/scrobbles/models.py index ea6e56c..757d6ff 100644 --- a/vrobbler/apps/scrobbles/models.py +++ b/vrobbler/apps/scrobbles/models.py @@ -312,7 +312,22 @@ class ChartRecord(TimeStampedModel): return period def __str__(self): - return f"#{self.rank} in {self.period} - {self.media_obj}" + title = f"#{self.rank} in {self.period}" + if self.day or self.week: + title = f"#{self.rank} on {self.period}" + return title + + def link(self): + get_params = f"?date={self.year}" + if self.week: + get_params = get_params = get_params + f"-W{self.week}" + if self.month: + get_params = get_params = get_params + f"-{self.month}" + if self.day: + get_params = get_params = get_params + f"-{self.day}" + if self.artist: + get_params = get_params + "&media=Artist" + return reverse('scrobbles:charts-home') + get_params @classmethod def build(cls, user, **kwargs): diff --git a/vrobbler/apps/scrobbles/views.py b/vrobbler/apps/scrobbles/views.py index 5a890a9..7c9bf5a 100644 --- a/vrobbler/apps/scrobbles/views.py +++ b/vrobbler/apps/scrobbles/views.py @@ -2,7 +2,6 @@ import calendar import json import logging from datetime import datetime, timedelta -from django.db.models.query import QuerySet import pytz from django.conf import settings @@ -10,6 +9,7 @@ from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Q from django.db.models.fields import timezone +from django.db.models.query import QuerySet from django.http import FileResponse, HttpResponseRedirect, JsonResponse from django.urls import reverse, reverse_lazy from django.utils import timezone @@ -17,12 +17,7 @@ from django.views.decorators.csrf import csrf_exempt from django.views.generic import DetailView, FormView, TemplateView from django.views.generic.edit import CreateView from django.views.generic.list import ListView -from music.aggregators import ( - scrobble_counts, - top_artists, - top_tracks, - week_of_scrobbles, -) +from music.aggregators import scrobble_counts, week_of_scrobbles from rest_framework import status from rest_framework.decorators import ( api_view, @@ -62,6 +57,8 @@ from scrobbles.tasks import ( ) from scrobbles.thesportsdb import lookup_event_from_thesportsdb +from vrobbler.apps.music.aggregators import live_charts + logger = logging.getLogger(__name__) @@ -406,19 +403,17 @@ class ChartRecordView(TemplateView): template_name = 'scrobbles/chart_index.html' @staticmethod - def get_media_filter(media_type: str = "Track"): - media_filter = Q() - if media_type == 'Track': - media_filter = Q(track__isnull=False) - if media_type == 'Artist': - media_filter = Q(artist__isnull=False) - if media_type == 'Series': - media_filter = Q(series__isnull=False) - if media_type == 'Video': - media_filter = Q(video__isnull=False) - return media_filter + def get_media_filter(media_type: str = "") -> Q: + filters = { + "Track": Q(track__isnull=False), + "Artist": Q(artist__isnull=False), + "Series": Q(series__isnull=False), + "Video": Q(video__isnull=False), + "": Q(), + } + return filters[media_type] - def get_chart_records(self, media_type: str = "Track", **kwargs): + def get_chart_records(self, media_type: str = "", **kwargs): media_filter = self.get_media_filter(media_type) charts = ChartRecord.objects.filter( media_filter, user=self.request.user, **kwargs @@ -434,37 +429,24 @@ class ChartRecordView(TemplateView): return charts def get_chart( - self, period: str = "all_time", limit=15, media: str = "Track" + self, period: str = "all_time", limit=15, media: str = "" ) -> QuerySet: - chart = QuerySet() now = timezone.now() - if period == "all_time": - chart = self.get_chart_records(media_type=media) + params = {} + params['media_type'] = media if period == "today": - chart = self.get_chart_records( - media_type=media, - day=now.day, - month=now.month, - year=now.year, - ) + params['day'] = now.day + params['month'] = now.month + params['year'] = now.year if period == "week": - chart = self.get_chart_records( - media_type=media, - year=now.year, - week=now.isocalendar()[1], - ) + params['week'] = now.ioscalendar()[1] + params['year'] = now.year if period == "month": - chart = self.get_chart_records( - media_type=media, - year=now.year, - month=now.month, - ) + params['month'] = now.month + params['year'] = now.year if period == "year": - chart = self.get_chart_records( - media_type=media, - year=now.year, - ) - return chart[:limit] + params['year'] = now.year + return self.get_chart_records(**params)[:limit] def get_context_data(self, **kwargs): context_data = super().get_context_data(**kwargs) @@ -475,21 +457,24 @@ class ChartRecordView(TemplateView): context_data["artist_charts"] = {} if not date: + artist_params = {'user': user, 'media_type': 'Artist'} context_data['artist_charts'] = { - "today": top_artists(user, filter="today")[:30], - "week": top_artists(user, filter="week")[:30], - "month": top_artists(user, filter="month")[:30], - "all": top_artists(user), + "today": live_charts(**artist_params, chart_period="today"), + "week": live_charts(**artist_params, chart_period="week"), + "month": live_charts(**artist_params, chart_period="month"), + "all": live_charts(**artist_params), } + track_params = {'user': user, 'media_type': 'Track'} context_data['track_charts'] = { - "today": top_tracks(user, filter="today")[:30], - "week": top_tracks(user, filter="week")[:30], - "month": top_tracks(user, filter="month")[:30], - "all": top_tracks(user), + "today": live_charts(**track_params, chart_period="today"), + "week": live_charts(**track_params, chart_period="week"), + "month": live_charts(**track_params, chart_period="month"), + "all": live_charts(**track_params), } return context_data + # Date provided, lookup past charts, returning nothing if it's now or in the future. now = timezone.now() year = now.year params = {'year': year} @@ -531,7 +516,7 @@ class ChartRecordView(TemplateView): media_filter, user=self.request.user, **params ).order_by("rank") - if charts.count() == 0: + if charts.count() == 0 and not in_progress: ChartRecord.build( user=self.request.user, model_str=media_type, **params ) @@ -539,11 +524,8 @@ class ChartRecordView(TemplateView): media_filter, user=self.request.user, **params ).order_by("rank") - if in_progress: - # TODO recalculate - ... - + context_data['media_type'] = media_type context_data['charts'] = charts - context_data['name'] = name + context_data['name'] = " ".join(["Top", media_type, "for", name]) context_data['in_progress'] = in_progress return context_data diff --git a/vrobbler/templates/music/artist_detail.html b/vrobbler/templates/music/artist_detail.html index f89fae1..a442850 100644 --- a/vrobbler/templates/music/artist_detail.html +++ b/vrobbler/templates/music/artist_detail.html @@ -14,6 +14,9 @@

{{artist.scrobbles.count}} scrobbles

+ {% if charts %} +

{% for chart in charts %}{{chart}}{% if forloop.last %}{% else %} | {% endif %}{% endfor %}

+ {% endif %}

Top tracks

diff --git a/vrobbler/templates/music/track_detail.html b/vrobbler/templates/music/track_detail.html index 117dee7..f301138 100644 --- a/vrobbler/templates/music/track_detail.html +++ b/vrobbler/templates/music/track_detail.html @@ -1,13 +1,41 @@ -{% extends "base_detail.html" %} +{% extends "base_list.html" %} {% block title %}{{object.title}}{% endblock %} -{% block details %} -

Last scrobbles

-{% for scrobble in object.scrobble_set.all %} -
    -
  • {{scrobble.timestamp|date:"d M Y h:m"}} - - {{object}}
  • -
-{% endfor %} +{% block lists %} +
+ {% if track.album.cover_image %} +

+ {% endif %} +
+
+

{{object.scrobble_set.count}} scrobbles

+ {% if charts %} +

{% for chart in charts %}{{chart}}{% if forloop.last %}{% else %} | {% endif %}{% endfor %}

+ {% endif %} +
+

Last scrobbles

+
+ + + + + + + + + + {% for scrobble in object.scrobble_set.all %} + + + + + + {% endfor %} + +
DateTrackAlbum
{{scrobble.timestamp}}{{scrobble.track.title}}{{scrobble.track.album.name}}
+
+
+
{% endblock %} diff --git a/vrobbler/templates/scrobbles/chart_index.html b/vrobbler/templates/scrobbles/chart_index.html index 6e44c78..b580425 100644 --- a/vrobbler/templates/scrobbles/chart_index.html +++ b/vrobbler/templates/scrobbles/chart_index.html @@ -5,6 +5,30 @@ {% block lists %}
{% if charts %} + {% if "Artist" in name %} +
+
+ + + + + + + + + + {% for chart in charts %} + + + + + + {% endfor %} + +
RankArtistScrobbles
{{chart.rank}}{{chart.media_obj}}{{chart.count}}
+
+
+ {% elif media_type == "Track" %}
@@ -29,93 +53,96 @@
+ {% elif "Video" in name %} + {% elif "Series" in name %} + {% endif %} {% endif %} {% if artist_charts %} -

Top Artists

+
+

Top Artists

- + -
- {% for chart_name, artists in artist_charts.items %} -
-
- - - - - - - - - {% for artist in artists %} - - - - - {% endfor %} - -
ArtistScrobbles
{{artist}}{{artist.num_scrobbles}}
+
+ {% for chart_name, artists in artist_charts.items %} +
+
+ + + + + + + + + {% for artist in artists %} + + + + + {% endfor %} + +
ArtistScrobbles
{{artist}}{{artist.num_scrobbles}}
+
+ {% endfor %}
- {% endfor %} + {% endif %}
- {% endif %} -
-
{% if track_charts %} -

Top Tracks

+
+

Top Tracks

- + -
- {% for chart_name, tracks in track_charts.items %} -
-
- - - - - - - - - - - {% for track in tracks %} - - - - - - - {% endfor %} - -
RankArtistTrackScrobbles
{{track.rank}}{{track.artist}}{{track.title}}{{track.num_scrobbles}}
+
+ {% for chart_name, tracks in track_charts.items %} +
+
+ + + + + + + + + + {% for track in tracks %} + + + + + + {% endfor %} + +
TrackArtistScrobbles
{{track.title}}{{track.artist}}{{track.num_scrobbles}}
+
+ {% endfor %}
- {% endfor %}
{% endif %}