[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",
limit: int = 15,
app_label: str = "music",
as_of: datetime = None,
) -> QuerySet:
now = timezone.now()
now = as_of if as_of else timezone.now()
tzinfo = now.tzinfo
now = now.date()
if user.is_authenticated:
if user.is_authenticated and not as_of:
now = now_user_timezone(user.profile)
tzinfo = now.tzinfo

View File

@ -915,12 +915,7 @@ class BaseEmbeddableWidget(TemplateView):
if date_param:
try:
if "W" in date_param and date_param[4] == "-":
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()
parsed_date = datetime.strptime(date_param, "%Y-%m-%d").date()
except ValueError:
parsed_date = None
@ -937,24 +932,31 @@ class BaseEmbeddableWidget(TemplateView):
period = self.kwargs.get("period", "week")
if period == "month":
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")
elif period == "year":
start = now.replace(month=1, day=1)
end = now.replace(year=now.year + 1, month=1, day=1)
label = now.strftime("%Y")
else:
start = now - timedelta(days=now.isoweekday() % 7)
end = start + timedelta(days=7)
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
model = model or self.model
queryset = (
model.objects.filter(
scrobble__user=user,
scrobble__user_id=user.id,
scrobble__timestamp__gte=start_date,
scrobble__timestamp__lt=end_date,
**self.scrobble_filter,
)
.annotate(count=Count("scrobble", distinct=True))
@ -976,10 +978,10 @@ class BaseEmbeddableWidget(TemplateView):
context["media_type"] = self.media_type
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
items = self.get_items(user, start_date)
items = self.get_items(user, start_date, end_date)
context["items"] = items
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")
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):
context = super().get_context_data(**kwargs)
user, profile = self.get_user_and_profile()
@ -1010,34 +1041,20 @@ class EmbeddableTopArtistsWidget(TemplateView):
context["count_label"] = self.count_label
context["no_data_message"] = self.no_data_message
now, period_label = self.get_date_range(user)
period = self.kwargs.get("period", "week")
period_map = {"week": "last7", "month": "last30", "year": "year"}
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))
for item in items:
item.count = item.num_scrobbles
context["items"] = items
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"
context["period_label"] = period_label
return context
@ -1163,10 +1180,10 @@ class EmbeddableTopBoardGamesWidget(BaseEmbeddableWidget):
no_data_message = "No board games played"
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
return super().get_items(user, start_date, BoardGame)
return super().get_items(user, start_date, end_date, BoardGame)
class EmbeddableTopBooksWidget(BaseEmbeddableWidget):
@ -1174,21 +1191,23 @@ class EmbeddableTopBooksWidget(BaseEmbeddableWidget):
count_label = "reads"
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 django.db.models import Count, Exists, OuterRef
completed_subquery = Book.objects.filter(
scrobble__user=user,
scrobble__user_id=user.id,
scrobble__timestamp__gte=start_date,
scrobble__timestamp__lt=end_date,
scrobble__long_play_complete=True,
pk=OuterRef("pk"),
)
queryset = (
Book.objects.filter(
scrobble__user=user,
scrobble__user_id=user.id,
scrobble__timestamp__gte=start_date,
scrobble__timestamp__lt=end_date,
)
.annotate(
count=Count("scrobble", distinct=True),
@ -1209,10 +1228,10 @@ class EmbeddableTopTrailsWidget(BaseEmbeddableWidget):
count_label = "visits"
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
return super().get_items(user, start_date, Trail)
return super().get_items(user, start_date, end_date, Trail)
class EmbeddableTopFoodsWidget(BaseEmbeddableWidget):
@ -1220,10 +1239,10 @@ class EmbeddableTopFoodsWidget(BaseEmbeddableWidget):
count_label = "meals"
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
return super().get_items(user, start_date, Food)
return super().get_items(user, start_date, end_date, Food)
class EmbeddableTopTasksWidget(BaseEmbeddableWidget):
@ -1231,7 +1250,7 @@ class EmbeddableTopTasksWidget(BaseEmbeddableWidget):
count_label = "sessions"
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
return super().get_items(user, start_date, Task)
return super().get_items(user, start_date, end_date, Task)