Fix pagination controls, move mixin to common app, fix pagination invocation on all views, and other random bug fixes

This commit is contained in:
badblocks 2025-04-01 23:01:05 -07:00
parent 7edefe23c3
commit 6a61b79bbe
425 changed files with 51656 additions and 243 deletions

View file

@ -1,7 +1,7 @@
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.shortcuts import redirect, get_object_or_404
from django.shortcuts import redirect, get_object_or_404, render
from django.views.generic import ListView, CreateView, DeleteView, View, TemplateView, UpdateView
from accounts.models import FriendCode, CustomUser
from accounts.forms import FriendCodeForm, UserSettingsForm
@ -9,6 +9,7 @@ from django.db.models import Case, When, Value, BooleanField
from trades.models import TradeOffer, TradeAcceptance
from django.core.exceptions import PermissionDenied
from trades.mixins import FriendCodeRequiredMixin
from common.mixins import ReusablePaginationMixin
class ListFriendCodesView(LoginRequiredMixin, ListView):
"""
@ -150,7 +151,7 @@ class EditFriendCodeView(LoginRequiredMixin, UpdateView):
messages.success(self.request, "Friend code updated successfully.")
return super().form_valid(form)
class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, TemplateView):
class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, ReusablePaginationMixin, TemplateView):
template_name = "account/dashboard.html"
def post(self, request, *args, **kwargs):
@ -179,10 +180,10 @@ class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, TemplateView):
return selected_friend_code
def get_dashboard_offers_paginated(self, page_param):
from django.core.paginator import Paginator
selected_friend_code = self.get_selected_friend_code()
queryset = TradeOffer.objects.filter(initiated_by=selected_friend_code, is_closed=False)
return Paginator(queryset, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(queryset, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_involved_acceptances(self, selected_friend_code):
from django.db.models import Q
@ -209,8 +210,8 @@ class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, TemplateView):
]) |
Q(accepted_by=selected_friend_code, state__in=[TradeAcceptance.AcceptanceState.SENT])
)
from django.core.paginator import Paginator
return Paginator(waiting, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(waiting, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_other_party_trade_acceptances_paginated(self, page_param):
selected_friend_code = self.get_selected_friend_code()
@ -224,18 +225,17 @@ class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, TemplateView):
Q(accepted_by=selected_friend_code, state__in=[TradeAcceptance.AcceptanceState.SENT])
)
others = involved.exclude(pk__in=waiting.values("pk"))
from django.core.paginator import Paginator
return Paginator(others, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(others, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_closed_offers_paginated(self, page_param):
from django.core.paginator import Paginator
selected_friend_code = self.get_selected_friend_code()
queryset = TradeOffer.objects.filter(initiated_by=selected_friend_code, is_closed=True)
return Paginator(queryset, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(queryset, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_closed_acceptances_paginated(self, page_param):
from django.db.models import Q
from django.core.paginator import Paginator
selected_friend_code = self.get_selected_friend_code()
terminal_success_states = [
TradeAcceptance.AcceptanceState.THANKED_BY_INITIATOR,
@ -246,41 +246,83 @@ class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, TemplateView):
Q(trade_offer__initiated_by=selected_friend_code) | Q(accepted_by=selected_friend_code),
state__in=terminal_success_states
).order_by("-updated_at")
return Paginator(acceptance_qs, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(acceptance_qs, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_rejected_by_me_paginated(self, page_param):
from django.db.models import Q
from django.core.paginator import Paginator
selected_friend_code = self.get_selected_friend_code()
rejection = TradeAcceptance.objects.filter(
Q(trade_offer__initiated_by=selected_friend_code, state=TradeAcceptance.AcceptanceState.REJECTED_BY_INITIATOR) |
Q(accepted_by=selected_friend_code, state=TradeAcceptance.AcceptanceState.REJECTED_BY_ACCEPTOR)
).order_by("-updated_at")
return Paginator(rejection, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(rejection, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_rejected_by_them_paginated(self, page_param):
from django.db.models import Q
from django.core.paginator import Paginator
selected_friend_code = self.get_selected_friend_code()
rejection = TradeAcceptance.objects.filter(
Q(trade_offer__initiated_by=selected_friend_code, state=TradeAcceptance.AcceptanceState.REJECTED_BY_ACCEPTOR) |
Q(accepted_by=selected_friend_code, state=TradeAcceptance.AcceptanceState.REJECTED_BY_INITIATOR)
).order_by("-updated_at")
return Paginator(rejection, 10).get_page(page_param)
object_list, pagination_context = self.paginate_data(rejection, int(page_param))
return {"object_list": object_list, "page_obj": pagination_context}
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
request = self.request
selected_friend_code = self.get_selected_friend_code()
context["selected_friend_code"] = selected_friend_code
context["friend_codes"] = request.user.friend_codes.all()
offers_page = request.GET.get("offers_page", 1)
waiting_page = request.GET.get("waiting_page", 1)
other_page = request.GET.get("other_page", 1)
closed_offers_page = request.GET.get("closed_offers_page", 1)
closed_acceptances_page = request.GET.get("closed_acceptances_page", 1)
rejected_by_me_page = request.GET.get("rejected_by_me_page", 1)
rejected_by_them_page = request.GET.get("rejected_by_them_page", 1)
# Get the default friend code's primary key if it exists
default_pk = getattr(request.user.default_friend_code, "pk", None)
# Annotate friend codes with is_default flag
context["friend_codes"] = request.user.friend_codes.all().annotate(
is_default=Case(
When(pk=default_pk, then=Value(True)),
default=Value(False),
output_field=BooleanField()
)
)
ajax_section = request.GET.get("ajax_section")
if ajax_section == "dashboard_offers":
offers_page = request.GET.get("page", 1)
else:
offers_page = request.GET.get("offers_page", 1)
if ajax_section == "waiting_acceptances":
waiting_page = request.GET.get("page", 1)
else:
waiting_page = request.GET.get("waiting_page", 1)
if ajax_section == "other_party_acceptances":
other_page = request.GET.get("page", 1)
else:
other_page = request.GET.get("other_page", 1)
if ajax_section == "closed_offers":
closed_offers_page = request.GET.get("page", 1)
else:
closed_offers_page = request.GET.get("closed_offers_page", 1)
if ajax_section == "closed_acceptances":
closed_acceptances_page = request.GET.get("page", 1)
else:
closed_acceptances_page = request.GET.get("closed_acceptances_page", 1)
if ajax_section == "rejected_by_me":
rejected_by_me_page = request.GET.get("page", 1)
else:
rejected_by_me_page = request.GET.get("rejected_by_me_page", 1)
if ajax_section == "rejected_by_them":
rejected_by_them_page = request.GET.get("page", 1)
else:
rejected_by_them_page = request.GET.get("rejected_by_them_page", 1)
context["dashboard_offers_paginated"] = self.get_dashboard_offers_paginated(offers_page)
context["trade_acceptances_waiting_paginated"] = self.get_trade_acceptances_waiting_paginated(waiting_page)
context["other_party_trade_acceptances_paginated"] = self.get_other_party_trade_acceptances_paginated(other_page)
@ -291,4 +333,33 @@ class DashboardView(LoginRequiredMixin, FriendCodeRequiredMixin, TemplateView):
from accounts.forms import UserSettingsForm
context["settings_form"] = UserSettingsForm(instance=request.user)
context["active_tab"] = request.GET.get("tab", "dash")
return context
return context
# Handle AJAX requests to return only the trade offer list fragment
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
ajax_section = request.GET.get("ajax_section")
if request.headers.get("X-Requested-With") == "XMLHttpRequest" and ajax_section:
if ajax_section == "dashboard_offers":
fragment_context = context.get("dashboard_offers_paginated", {})
elif ajax_section == "waiting_acceptances":
fragment_context = context.get("trade_acceptances_waiting_paginated", {})
elif ajax_section == "other_party_acceptances":
fragment_context = context.get("other_party_trade_acceptances_paginated", {})
elif ajax_section == "closed_offers":
fragment_context = context.get("closed_offers_paginated", {})
elif ajax_section == "closed_acceptances":
fragment_context = context.get("closed_acceptances_paginated", {})
elif ajax_section == "rejected_by_me":
fragment_context = context.get("rejected_by_me_paginated", {})
elif ajax_section == "rejected_by_them":
fragment_context = context.get("rejected_by_them_paginated", {})
else:
fragment_context = {}
if fragment_context:
return render(request, "trades/_trade_offer_list.html", {
"offers": fragment_context.get("object_list", []),
"page_obj": fragment_context.get("page_obj")
})
return super().get(request, *args, **kwargs)