mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 10:11:09 -05:00
Improve moderation dashboard UI and functionality
- Add status tabs (Pending, Approved, Rejected, Escalated) - Implement HTMX for smooth tab switching and status changes - Add proper permissions for escalated submissions - Change Status filter to Submission Type (Text/Photo) - Move navigation into dashboard content - Fix tab menu visibility and transitions - Add contextual loading indicator - Update styling to match dark theme - Ensure consistent styling across components
This commit is contained in:
@@ -8,6 +8,7 @@ from django.apps import apps
|
||||
from django.core.exceptions import ObjectDoesNotExist, FieldDoesNotExist
|
||||
from django.contrib.auth.base_user import AbstractBaseUser
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.utils.text import slugify
|
||||
|
||||
UserType = Union[AbstractBaseUser, AnonymousUser]
|
||||
|
||||
@@ -102,21 +103,56 @@ class EditSubmission(models.Model):
|
||||
|
||||
return resolved_data
|
||||
|
||||
def _prepare_model_data(self, data: Dict[str, Any], model_class: Type[models.Model]) -> Dict[str, Any]:
|
||||
"""Prepare data for model creation/update by filtering out auto-generated fields"""
|
||||
prepared_data = data.copy()
|
||||
|
||||
# Remove fields that are auto-generated or handled by the model's save method
|
||||
auto_fields = {'created_at', 'updated_at', 'slug'}
|
||||
for field in auto_fields:
|
||||
prepared_data.pop(field, None)
|
||||
|
||||
# Set default values for required fields if not provided
|
||||
for field in model_class._meta.fields:
|
||||
if not field.auto_created and not field.blank and not field.null:
|
||||
if field.name not in prepared_data and field.has_default():
|
||||
prepared_data[field.name] = field.get_default()
|
||||
|
||||
return prepared_data
|
||||
|
||||
def _check_duplicate_name(self, model_class: Type[models.Model], name: str) -> Optional[models.Model]:
|
||||
"""Check if an object with the same name already exists"""
|
||||
try:
|
||||
return model_class.objects.filter(name=name).first()
|
||||
except:
|
||||
return None
|
||||
|
||||
def approve(self, user: UserType) -> Optional[models.Model]:
|
||||
"""Approve the submission and apply the changes"""
|
||||
self.status = "APPROVED"
|
||||
self.handled_by = user # type: ignore
|
||||
self.handled_at = timezone.now()
|
||||
|
||||
if not (model_class := self.content_type.model_class()):
|
||||
raise ValueError("Could not resolve model class")
|
||||
|
||||
try:
|
||||
resolved_data = self._resolve_foreign_keys(self.changes)
|
||||
prepared_data = self._prepare_model_data(resolved_data, model_class)
|
||||
|
||||
# For CREATE submissions, check for duplicates by name
|
||||
if self.submission_type == "CREATE" and "name" in prepared_data:
|
||||
if existing_obj := self._check_duplicate_name(model_class, prepared_data["name"]):
|
||||
self.status = "REJECTED"
|
||||
self.handled_by = user # type: ignore
|
||||
self.handled_at = timezone.now()
|
||||
self.notes = f"A {model_class.__name__} with the name '{prepared_data['name']}' already exists (ID: {existing_obj.id})"
|
||||
self.save()
|
||||
raise ValueError(self.notes)
|
||||
|
||||
self.status = "APPROVED"
|
||||
self.handled_by = user # type: ignore
|
||||
self.handled_at = timezone.now()
|
||||
|
||||
if self.submission_type == "CREATE":
|
||||
# Create new object
|
||||
obj = model_class(**resolved_data)
|
||||
obj = model_class(**prepared_data)
|
||||
obj.save()
|
||||
# Update object_id after creation
|
||||
self.object_id = getattr(obj, "id", None)
|
||||
@@ -124,13 +160,16 @@ class EditSubmission(models.Model):
|
||||
# Apply changes to existing object
|
||||
if not (obj := self.content_object):
|
||||
raise ValueError("Content object not found")
|
||||
for field, value in resolved_data.items():
|
||||
for field, value in prepared_data.items():
|
||||
setattr(obj, field, value)
|
||||
obj.save()
|
||||
|
||||
self.save()
|
||||
return obj
|
||||
except Exception as e:
|
||||
if self.status != "REJECTED": # Don't override if already rejected due to duplicate
|
||||
self.status = "NEW" # Reset status if approval failed
|
||||
self.save()
|
||||
raise ValueError(f"Error approving submission: {str(e)}") from e
|
||||
|
||||
def reject(self, user: UserType) -> None:
|
||||
|
||||
Reference in New Issue
Block a user