from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Count, Q from django.views.generic import ListView from apps.submissions.models import Submission class IndexView(ListView): """Public dashboard (plan.md ยง8). Lists every submission whose status is one of the four dashboard-visible states -- `verifying`, `queued`, `printing`, `completed`. Anything in `identifying`, `processing`, `rejected`, or `failed` is excluded from the listing (still reachable by direct slug URL by the submitter). Status-chip filtering via `?status=`; only the four dashboard- visible values are honoured. Anything else falls back to the unfiltered list, so the chips stay safe even if someone hand-edits the URL. """ model = Submission template_name = "dashboard/index.html" context_object_name = "submissions" paginate_by = 20 def _requested_status(self) -> str: raw = self.request.GET.get("status", "") allowed = {str(s) for s in Submission.DASHBOARD_VISIBLE_STATUSES} return raw if raw in allowed else "" def get_queryset(self): qs = Submission.objects.filter( status__in=Submission.DASHBOARD_VISIBLE_STATUSES ).select_related("requested_filament") status = self._requested_status() if status: qs = qs.filter(status=status) return qs def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) # One conditional-aggregate for the chip counts, scoped to the same # dashboard-visible filter so `total` matches what "All" would list. ctx["counts"] = Submission.objects.filter( status__in=Submission.DASHBOARD_VISIBLE_STATUSES ).aggregate( total=Count("id"), verifying=Count("id", filter=Q(status=Submission.Status.VERIFYING)), queued=Count("id", filter=Q(status=Submission.Status.QUEUED)), printing=Count("id", filter=Q(status=Submission.Status.PRINTING)), completed=Count("id", filter=Q(status=Submission.Status.COMPLETED)), ) ctx["active_status"] = self._requested_status() return ctx class MyPrintsView(LoginRequiredMixin, ListView): """Private listing -- every submission the signed-in user has ever made. Anonymous users are bounced to allauth's `account_login` (the default `LoginRequiredMixin.login_url`, configured via `LOGIN_URL`). Guests don't have a `submitted_by`, so they have nothing to list here anyway. """ model = Submission template_name = "dashboard/my_prints.html" context_object_name = "submissions" paginate_by = 50 def get_queryset(self): # Ordering inherited from `Submission.Meta` (-created_at). return Submission.objects.filter( submitted_by=self.request.user ).select_related("requested_filament") def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) # Counts for the summary line in the page header. A single # conditional-aggregate query beats N separate `.count()` calls. agg = Submission.objects.filter(submitted_by=self.request.user).aggregate( total=Count("id"), queued=Count("id", filter=Q(status=Submission.Status.QUEUED)), printing=Count("id", filter=Q(status=Submission.Status.PRINTING)), completed=Count("id", filter=Q(status=Submission.Status.COMPLETED)), ) ctx["counts"] = agg return ctx