[widgets] Fix the date filter
All checks were successful
build & deploy / test (push) Successful in 1m48s
build & deploy / deploy (push) Successful in 22s

This commit is contained in:
2026-03-31 17:19:14 -04:00
parent 192d0c489b
commit 0a74c692d2
2 changed files with 62 additions and 42 deletions

View File

@ -84,11 +84,12 @@ def live_charts(
chart_period: str = "all", chart_period: str = "all",
limit: int = 15, limit: int = 15,
app_label: str = "music", app_label: str = "music",
as_of: datetime = None,
) -> QuerySet: ) -> QuerySet:
now = timezone.now() now = as_of if as_of else timezone.now()
tzinfo = now.tzinfo tzinfo = now.tzinfo
now = now.date() now = now.date()
if user.is_authenticated: if user.is_authenticated and not as_of:
now = now_user_timezone(user.profile) now = now_user_timezone(user.profile)
tzinfo = now.tzinfo tzinfo = now.tzinfo

View File

@ -915,12 +915,7 @@ class BaseEmbeddableWidget(TemplateView):
if date_param: if date_param:
try: try:
if "W" in date_param and date_param[4] == "-": parsed_date = datetime.strptime(date_param, "%Y-%m-%d").date()
parsed_date = datetime.strptime(date_param, "%Y-W%W").date()
elif "-" in date_param and len(date_param) > 4:
parsed_date = datetime.strptime(date_param, "%Y-%m-%d").date()
else:
parsed_date = datetime.strptime(date_param, "%Y").date()
except ValueError: except ValueError:
parsed_date = None parsed_date = None
@ -937,24 +932,31 @@ class BaseEmbeddableWidget(TemplateView):
period = self.kwargs.get("period", "week") period = self.kwargs.get("period", "week")
if period == "month": if period == "month":
start = now.replace(day=1) start = now.replace(day=1)
if now.month == 12:
end = now.replace(year=now.year + 1, month=1, day=1)
else:
end = now.replace(month=now.month + 1, day=1)
label = now.strftime("%B %Y") label = now.strftime("%B %Y")
elif period == "year": elif period == "year":
start = now.replace(month=1, day=1) start = now.replace(month=1, day=1)
end = now.replace(year=now.year + 1, month=1, day=1)
label = now.strftime("%Y") label = now.strftime("%Y")
else: else:
start = now - timedelta(days=now.isoweekday() % 7) start = now - timedelta(days=now.isoweekday() % 7)
end = start + timedelta(days=7)
label = f"Week {now.isocalendar()[1]}" label = f"Week {now.isocalendar()[1]}"
return start, label return start, end, label
def get_items(self, user, start_date, model=None): def get_items(self, user, start_date, end_date, model=None):
from django.db.models import Count from django.db.models import Count
model = model or self.model model = model or self.model
queryset = ( queryset = (
model.objects.filter( model.objects.filter(
scrobble__user=user, scrobble__user_id=user.id,
scrobble__timestamp__gte=start_date, scrobble__timestamp__gte=start_date,
scrobble__timestamp__lt=end_date,
**self.scrobble_filter, **self.scrobble_filter,
) )
.annotate(count=Count("scrobble", distinct=True)) .annotate(count=Count("scrobble", distinct=True))
@ -976,10 +978,10 @@ class BaseEmbeddableWidget(TemplateView):
context["media_type"] = self.media_type context["media_type"] = self.media_type
context["count_label"] = self.count_label context["count_label"] = self.count_label
start_date, period_label = self.get_date_range(user) start_date, end_date, period_label = self.get_date_range(user)
context["period_label"] = period_label context["period_label"] = period_label
items = self.get_items(user, start_date) items = self.get_items(user, start_date, end_date)
context["items"] = items context["items"] = items
context["no_data_message"] = self.no_data_message context["no_data_message"] = self.no_data_message
@ -1000,6 +1002,35 @@ class EmbeddableTopArtistsWidget(TemplateView):
raise Http404("Public widgets are not enabled for this user") raise Http404("Public widgets are not enabled for this user")
return user, profile return user, profile
def get_date_range(self, user):
date_param = self.request.GET.get("date")
if date_param:
try:
parsed_date = datetime.strptime(date_param, "%Y-%m-%d").date()
except ValueError:
parsed_date = None
if parsed_date:
now = parsed_date
else:
now = timezone.now().date()
else:
now = timezone.now()
if user.is_authenticated:
now = now_user_timezone(user.profile)
now = now.date()
period = self.kwargs.get("period", "week")
if period == "month":
label = now.strftime("%B %Y")
elif period == "year":
label = now.strftime("%Y")
else:
label = f"Week {now.isocalendar()[1]}"
return now, label
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
user, profile = self.get_user_and_profile() user, profile = self.get_user_and_profile()
@ -1010,34 +1041,20 @@ class EmbeddableTopArtistsWidget(TemplateView):
context["count_label"] = self.count_label context["count_label"] = self.count_label
context["no_data_message"] = self.no_data_message context["no_data_message"] = self.no_data_message
now, period_label = self.get_date_range(user)
period = self.kwargs.get("period", "week") period = self.kwargs.get("period", "week")
period_map = {"week": "last7", "month": "last30", "year": "year"} period_map = {"week": "last7", "month": "last30", "year": "year"}
chart_period = period_map.get(period, "last7") chart_period = period_map.get(period, "last7")
artist = {"user": user, "media_type": "Artist", "limit": 10} artist = {"user": user, "media_type": "Artist", "limit": 10, "as_of": now}
items = list(live_charts(**artist, chart_period=chart_period)) items = list(live_charts(**artist, chart_period=chart_period))
for item in items: for item in items:
item.count = item.num_scrobbles item.count = item.num_scrobbles
context["items"] = items context["items"] = items
context["period_label"] = period_label
from datetime import timedelta
from django.utils import timezone
now = timezone.now()
if user.is_authenticated:
now = now_user_timezone(user.profile)
now = now.date()
if period == "month":
context["period_label"] = now.strftime("%B %Y")
elif period == "year":
context["period_label"] = now.strftime("%Y")
else:
start = now - timedelta(days=now.isoweekday() % 7)
context["period_label"] = "This Week"
return context return context
@ -1163,10 +1180,10 @@ class EmbeddableTopBoardGamesWidget(BaseEmbeddableWidget):
no_data_message = "No board games played" no_data_message = "No board games played"
scrobble_filter = {"scrobble__played_to_completion": True} scrobble_filter = {"scrobble__played_to_completion": True}
def get_items(self, user, start_date): def get_items(self, user, start_date, end_date):
from boardgames.models import BoardGame from boardgames.models import BoardGame
return super().get_items(user, start_date, BoardGame) return super().get_items(user, start_date, end_date, BoardGame)
class EmbeddableTopBooksWidget(BaseEmbeddableWidget): class EmbeddableTopBooksWidget(BaseEmbeddableWidget):
@ -1174,21 +1191,23 @@ class EmbeddableTopBooksWidget(BaseEmbeddableWidget):
count_label = "reads" count_label = "reads"
no_data_message = "No books read" no_data_message = "No books read"
def get_items(self, user, start_date): def get_items(self, user, start_date, end_date):
from books.models import Book from books.models import Book
from django.db.models import Count, Exists, OuterRef from django.db.models import Count, Exists, OuterRef
completed_subquery = Book.objects.filter( completed_subquery = Book.objects.filter(
scrobble__user=user, scrobble__user_id=user.id,
scrobble__timestamp__gte=start_date, scrobble__timestamp__gte=start_date,
scrobble__timestamp__lt=end_date,
scrobble__long_play_complete=True, scrobble__long_play_complete=True,
pk=OuterRef("pk"), pk=OuterRef("pk"),
) )
queryset = ( queryset = (
Book.objects.filter( Book.objects.filter(
scrobble__user=user, scrobble__user_id=user.id,
scrobble__timestamp__gte=start_date, scrobble__timestamp__gte=start_date,
scrobble__timestamp__lt=end_date,
) )
.annotate( .annotate(
count=Count("scrobble", distinct=True), count=Count("scrobble", distinct=True),
@ -1209,10 +1228,10 @@ class EmbeddableTopTrailsWidget(BaseEmbeddableWidget):
count_label = "visits" count_label = "visits"
no_data_message = "No trails visited" no_data_message = "No trails visited"
def get_items(self, user, start_date): def get_items(self, user, start_date, end_date):
from trails.models import Trail from trails.models import Trail
return super().get_items(user, start_date, Trail) return super().get_items(user, start_date, end_date, Trail)
class EmbeddableTopFoodsWidget(BaseEmbeddableWidget): class EmbeddableTopFoodsWidget(BaseEmbeddableWidget):
@ -1220,10 +1239,10 @@ class EmbeddableTopFoodsWidget(BaseEmbeddableWidget):
count_label = "meals" count_label = "meals"
no_data_message = "No foods logged" no_data_message = "No foods logged"
def get_items(self, user, start_date): def get_items(self, user, start_date, end_date):
from foods.models import Food from foods.models import Food
return super().get_items(user, start_date, Food) return super().get_items(user, start_date, end_date, Food)
class EmbeddableTopTasksWidget(BaseEmbeddableWidget): class EmbeddableTopTasksWidget(BaseEmbeddableWidget):
@ -1231,7 +1250,7 @@ class EmbeddableTopTasksWidget(BaseEmbeddableWidget):
count_label = "sessions" count_label = "sessions"
no_data_message = "No tasks logged" no_data_message = "No tasks logged"
def get_items(self, user, start_date): def get_items(self, user, start_date, end_date):
from tasks.models import Task from tasks.models import Task
return super().get_items(user, start_date, Task) return super().get_items(user, start_date, end_date, Task)