Files
thrillwiki_django_no_react/moderation/views.py
pacnpal 08e97f21b7 Reorganize moderation dashboard structure:
- Move from /moderation/admin to /moderation to avoid conflicts
- Improve template organization with partials
- Add HTMX-powered navigation and filtering
- Add smooth transitions and loading states
- Improve photo submission handling
- Add review notes functionality
- Add confirmation dialogs
2024-11-13 14:50:34 +00:00

180 lines
6.5 KiB
Python

from django.views.generic import ListView, TemplateView
from django.shortcuts import get_object_or_404
from django.http import HttpResponse, JsonResponse
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.decorators import login_required
from django.template.loader import render_to_string
from django.db.models import Q
from django.core.exceptions import PermissionDenied
from .models import EditSubmission, PhotoSubmission
class ModeratorRequiredMixin(UserPassesTestMixin):
def test_func(self):
if not hasattr(self, 'request'):
return False
if not self.request.user.is_authenticated:
return False
return getattr(self.request.user, 'role', None) in ['MODERATOR', 'ADMIN', 'SUPERUSER']
def handle_no_permission(self):
if not self.request.user.is_authenticated:
return super().handle_no_permission()
raise PermissionDenied("You do not have moderator permissions.")
class DashboardView(LoginRequiredMixin, ModeratorRequiredMixin, TemplateView):
template_name = 'moderation/dashboard.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['submissions'] = EditSubmission.objects.all().order_by('-created_at')[:10]
return context
class EditSubmissionListView(LoginRequiredMixin, ModeratorRequiredMixin, ListView):
template_name = 'moderation/edit_submission_list.html'
context_object_name = 'submissions'
def get_queryset(self):
queryset = EditSubmission.objects.all().order_by('-created_at')
status = self.request.GET.get('status')
if status:
queryset = queryset.filter(status=status)
submission_type = self.request.GET.get('type')
if submission_type:
queryset = queryset.filter(submission_type=submission_type)
content_type = self.request.GET.get('content_type')
if content_type:
queryset = queryset.filter(content_type__model=content_type)
return queryset
class PhotoSubmissionListView(LoginRequiredMixin, ModeratorRequiredMixin, ListView):
template_name = 'moderation/photo_submission_list.html'
context_object_name = 'submissions'
def get_queryset(self):
queryset = PhotoSubmission.objects.all().order_by('-created_at')
status = self.request.GET.get('status')
if status:
queryset = queryset.filter(status=status)
return queryset
@login_required
def submission_list(request):
"""HTMX endpoint for filtered submission list"""
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
return HttpResponse(status=403)
status = request.GET.get('status')
submission_type = request.GET.get('type')
content_type = request.GET.get('content_type')
queryset = EditSubmission.objects.all().order_by('-created_at')
if status:
queryset = queryset.filter(status=status)
if submission_type:
queryset = queryset.filter(submission_type=submission_type)
if content_type:
queryset = queryset.filter(content_type__model=content_type)
context = {
'submissions': queryset
}
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
return HttpResponse(html)
@login_required
def approve_submission(request, submission_id):
"""HTMX endpoint for approving a submission"""
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
return HttpResponse(status=403)
submission = get_object_or_404(EditSubmission, id=submission_id)
notes = request.POST.get('notes', '')
try:
submission.approve(request.user)
if notes:
submission.notes = notes
submission.save()
context = {'submission': submission}
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
return HttpResponse(html)
except ValueError as e:
return HttpResponse(str(e), status=400)
@login_required
def reject_submission(request, submission_id):
"""HTMX endpoint for rejecting a submission"""
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
return HttpResponse(status=403)
submission = get_object_or_404(EditSubmission, id=submission_id)
notes = request.POST.get('notes', '')
submission.reject(request.user)
if notes:
submission.notes = notes
submission.save()
context = {'submission': submission}
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
return HttpResponse(html)
@login_required
def escalate_submission(request, submission_id):
"""HTMX endpoint for escalating a submission"""
if not request.user.role == 'MODERATOR':
return HttpResponse(status=403)
submission = get_object_or_404(EditSubmission, id=submission_id)
notes = request.POST.get('notes', '')
submission.escalate(request.user)
if notes:
submission.notes = notes
submission.save()
context = {'submission': submission}
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
return HttpResponse(html)
@login_required
def approve_photo(request, submission_id):
"""HTMX endpoint for approving a photo submission"""
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
return HttpResponse(status=403)
submission = get_object_or_404(PhotoSubmission, id=submission_id)
notes = request.POST.get('notes', '')
try:
submission.approve(request.user, notes)
context = {'submission': submission}
html = render_to_string('moderation/partials/photo_submission.html', context, request=request)
return HttpResponse(html)
except Exception as e:
return HttpResponse(str(e), status=400)
@login_required
def reject_photo(request, submission_id):
"""HTMX endpoint for rejecting a photo submission"""
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
return HttpResponse(status=403)
submission = get_object_or_404(PhotoSubmission, id=submission_id)
notes = request.POST.get('notes', '')
submission.reject(request.user, notes)
context = {'submission': submission}
html = render_to_string('moderation/partials/photo_submission.html', context, request=request)
return HttpResponse(html)