88 lines
3.5 KiB
Python
88 lines
3.5 KiB
Python
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=<value>`; 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
|