Add @extend_schema decorators to moderation ViewSet actions

- Add drf_spectacular imports (extend_schema, OpenApiResponse, inline_serializer)
- Annotate claim action with response schemas for 200/404/409/400
- Annotate unclaim action with response schemas for 200/403/400
- Annotate approve action with request=None and response schemas
- Annotate reject action with reason request body schema
- Annotate escalate action with reason request body schema
- All actions tagged with 'Moderation' for API docs grouping
This commit is contained in:
pacnpal
2026-01-13 19:34:41 -05:00
parent d631f3183c
commit 4140a0d8e7
18 changed files with 526 additions and 692 deletions

View File

@@ -45,23 +45,16 @@ class SubmissionListView(TemplateView):
template_name = "moderation/partials/dashboard_content.html"
def get_context_data(self, **kwargs):
from itertools import chain
from .models import EditSubmission, PhotoSubmission
from .models import EditSubmission
context = super().get_context_data(**kwargs)
status = self.request.GET.get("status", "PENDING")
# Get filtered submissions
# Get filtered submissions (EditSubmission now handles all types including PHOTO)
edit_submissions = EditSubmission.objects.filter(status=status).select_related("user")
photo_submissions = PhotoSubmission.objects.filter(status=status).select_related("user")
# Combine and sort
context["submissions"] = sorted(
chain(edit_submissions, photo_submissions),
key=lambda x: x.created_at,
reverse=True,
)
# Sort by created_at descending
context["submissions"] = edit_submissions.order_by("-created_at")
return context
@@ -78,10 +71,10 @@ router.register(r"queue", ModerationQueueViewSet, basename="moderation-queue")
router.register(r"actions", ModerationActionViewSet, basename="moderation-actions")
router.register(r"bulk-operations", BulkOperationViewSet, basename="bulk-operations")
router.register(r"users", UserModerationViewSet, basename="user-moderation")
# EditSubmission - register under both names for compatibility
# EditSubmission - handles all submission types (EDIT, CREATE, PHOTO)
router.register(r"submissions", EditSubmissionViewSet, basename="submissions")
router.register(r"edit-submissions", EditSubmissionViewSet, basename="edit-submissions")
# PhotoSubmission - register under both names for compatibility
# PhotoSubmissionViewSet - now queries EditSubmission with type=PHOTO, kept for API compatibility
router.register(r"photos", PhotoSubmissionViewSet, basename="photos")
router.register(r"photo-submissions", PhotoSubmissionViewSet, basename="photo-submissions")
@@ -98,12 +91,12 @@ fsm_transition_patterns = [
{"app_label": "moderation", "model_name": "editsubmission"},
name="submission_transition",
),
# PhotoSubmission transitions
# PhotoSubmission transitions (now use editsubmission model since photos are EditSubmission with type=PHOTO)
# URL: /api/moderation/photos/<pk>/transition/<transition_name>/
path(
"photos/<int:pk>/transition/<str:transition_name>/",
FSMTransitionView.as_view(),
{"app_label": "moderation", "model_name": "photosubmission"},
{"app_label": "moderation", "model_name": "editsubmission"},
name="photo_transition",
),
# ModerationReport transitions
@@ -150,23 +143,23 @@ fsm_transition_patterns = [
{"app_label": "moderation", "model_name": "editsubmission", "transition_name": "transition_to_escalated"},
name="escalate_submission",
),
# Backward compatibility aliases for PhotoSubmission actions
# Photo transition aliases (use editsubmission model since photos are EditSubmission with type=PHOTO)
path(
"photos/<int:pk>/approve/",
FSMTransitionView.as_view(),
{"app_label": "moderation", "model_name": "photosubmission", "transition_name": "transition_to_approved"},
{"app_label": "moderation", "model_name": "editsubmission", "transition_name": "transition_to_approved"},
name="approve_photo",
),
path(
"photos/<int:pk>/reject/",
FSMTransitionView.as_view(),
{"app_label": "moderation", "model_name": "photosubmission", "transition_name": "transition_to_rejected"},
{"app_label": "moderation", "model_name": "editsubmission", "transition_name": "transition_to_rejected"},
name="reject_photo",
),
path(
"photos/<int:pk>/escalate/",
FSMTransitionView.as_view(),
{"app_label": "moderation", "model_name": "photosubmission", "transition_name": "transition_to_escalated"},
{"app_label": "moderation", "model_name": "editsubmission", "transition_name": "transition_to_escalated"},
name="escalate_photo",
),
]