Files
thrillwiki_django_no_react/moderation/admin.py

110 lines
4.8 KiB
Python

from django.contrib import admin
from django.contrib.admin import AdminSite
from django.utils.html import format_html
from django.urls import reverse
from django.utils.safestring import mark_safe
import pghistory
from .models import EditSubmission, PhotoSubmission
class ModerationAdminSite(AdminSite):
site_header = 'ThrillWiki Moderation'
site_title = 'ThrillWiki Moderation'
index_title = 'Moderation Dashboard'
def has_permission(self, request):
"""Only allow moderators and above to access this admin site"""
return request.user.is_authenticated and request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']
moderation_site = ModerationAdminSite(name='moderation')
class EditSubmissionAdmin(admin.ModelAdmin):
list_display = ['id', 'user_link', 'content_type', 'content_link', 'status', 'created_at', 'handled_by']
list_filter = ['status', 'content_type', 'created_at']
search_fields = ['user__username', 'reason', 'source', 'notes']
readonly_fields = ['user', 'content_type', 'object_id', 'changes', 'created_at']
def user_link(self, obj):
url = reverse('admin:accounts_user_change', args=[obj.user.id])
return format_html('<a href="{}">{}</a>', url, obj.user.username)
user_link.short_description = 'User'
def content_link(self, obj):
if hasattr(obj.content_object, 'get_absolute_url'):
url = obj.content_object.get_absolute_url()
return format_html('<a href="{}">{}</a>', url, str(obj.content_object))
return str(obj.content_object)
content_link.short_description = 'Content'
def save_model(self, request, obj, form, change):
if 'status' in form.changed_data:
if obj.status == 'APPROVED':
obj.approve(request.user)
elif obj.status == 'REJECTED':
obj.reject(request.user)
elif obj.status == 'ESCALATED':
obj.escalate(request.user)
super().save_model(request, obj, form, change)
class PhotoSubmissionAdmin(admin.ModelAdmin):
list_display = ['id', 'user_link', 'content_type', 'content_link', 'photo_preview', 'status', 'created_at', 'handled_by']
list_filter = ['status', 'content_type', 'created_at']
search_fields = ['user__username', 'caption', 'notes']
readonly_fields = ['user', 'content_type', 'object_id', 'photo_preview', 'created_at']
def user_link(self, obj):
url = reverse('admin:accounts_user_change', args=[obj.user.id])
return format_html('<a href="{}">{}</a>', url, obj.user.username)
user_link.short_description = 'User'
def content_link(self, obj):
if hasattr(obj.content_object, 'get_absolute_url'):
url = obj.content_object.get_absolute_url()
return format_html('<a href="{}">{}</a>', url, str(obj.content_object))
return str(obj.content_object)
content_link.short_description = 'Content'
def photo_preview(self, obj):
if obj.photo:
return format_html('<img src="{}" style="max-height: 100px; max-width: 200px;" />', obj.photo.url)
return ''
photo_preview.short_description = 'Photo Preview'
def save_model(self, request, obj, form, change):
if 'status' in form.changed_data:
if obj.status == 'APPROVED':
obj.approve(request.user, obj.notes)
elif obj.status == 'REJECTED':
obj.reject(request.user, obj.notes)
super().save_model(request, obj, form, change)
class HistoryAdmin(admin.ModelAdmin):
"""Admin interface for viewing model history events"""
list_display = ['pgh_label', 'pgh_created_at', 'get_object_link', 'get_context']
list_filter = ['pgh_label', 'pgh_created_at']
readonly_fields = ['pgh_label', 'pgh_obj_id', 'pgh_data', 'pgh_context', 'pgh_created_at']
date_hierarchy = 'pgh_created_at'
def get_object_link(self, obj):
"""Display a link to the related object if possible"""
if obj.pgh_obj and hasattr(obj.pgh_obj, 'get_absolute_url'):
url = obj.pgh_obj.get_absolute_url()
return format_html('<a href="{}">{}</a>', url, str(obj.pgh_obj))
return str(obj.pgh_obj or '')
get_object_link.short_description = 'Object'
def get_context(self, obj):
"""Format the context data nicely"""
if not obj.pgh_context:
return '-'
html = ['<table>']
for key, value in obj.pgh_context.items():
html.append(f'<tr><th>{key}</th><td>{value}</td></tr>')
html.append('</table>')
return mark_safe(''.join(html))
get_context.short_description = 'Context'
# Register with moderation site only
moderation_site.register(EditSubmission, EditSubmissionAdmin)
moderation_site.register(PhotoSubmission, PhotoSubmissionAdmin)
moderation_site.register(pghistory.models.Event, HistoryAdmin)