App v0.1
This commit is contained in:
15
apps/dashboard/urls.py
Normal file
15
apps/dashboard/urls.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = "dashboard"
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.IndexView.as_view(), name="index"),
|
||||
path("my-prints/", views.MyPrintsView.as_view(), name="my_prints"),
|
||||
# Routes to be added as features land (see plan.md Section 7):
|
||||
# path("p/<slug:slug>/", views.SubmissionDetailView.as_view(), name="detail"),
|
||||
# path("p/<slug:slug>/status/", views.SubmissionStatusFragment.as_view(), name="status"),
|
||||
# path("p/<slug:slug>/confirm/<str:token>/", views.ConfirmEmailView.as_view(), name="confirm"),
|
||||
# path("p/<slug:slug>/resend/", views.ResendConfirmationView.as_view(), name="resend"),
|
||||
]
|
||||
@@ -1,3 +1,87 @@
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db.models import Count, Q
|
||||
from django.views.generic import ListView
|
||||
|
||||
# Create your views here.
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user