mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-28 21:07:04 -05:00
feat: Add user leaderboard API, Cloudflare Turnstile integration, and support ticket categorization.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.1.6 on 2025-12-27 18:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("support", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="ticket",
|
||||
name="category",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("general", "General Inquiry"),
|
||||
("bug", "Bug Report"),
|
||||
("partnership", "Partnership"),
|
||||
("press", "Press/Media"),
|
||||
("data", "Data Correction"),
|
||||
("account", "Account Issue"),
|
||||
],
|
||||
db_index=True,
|
||||
default="general",
|
||||
help_text="Category of the ticket",
|
||||
max_length=20,
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -13,6 +13,22 @@ class Ticket(TrackedModel):
|
||||
(STATUS_CLOSED, 'Closed'),
|
||||
]
|
||||
|
||||
CATEGORY_GENERAL = 'general'
|
||||
CATEGORY_BUG = 'bug'
|
||||
CATEGORY_PARTNERSHIP = 'partnership'
|
||||
CATEGORY_PRESS = 'press'
|
||||
CATEGORY_DATA = 'data'
|
||||
CATEGORY_ACCOUNT = 'account'
|
||||
|
||||
CATEGORY_CHOICES = [
|
||||
(CATEGORY_GENERAL, 'General Inquiry'),
|
||||
(CATEGORY_BUG, 'Bug Report'),
|
||||
(CATEGORY_PARTNERSHIP, 'Partnership'),
|
||||
(CATEGORY_PRESS, 'Press/Media'),
|
||||
(CATEGORY_DATA, 'Data Correction'),
|
||||
(CATEGORY_ACCOUNT, 'Account Issue'),
|
||||
]
|
||||
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.SET_NULL,
|
||||
@@ -22,6 +38,13 @@ class Ticket(TrackedModel):
|
||||
help_text="User who submitted the ticket (optional)"
|
||||
)
|
||||
|
||||
category = models.CharField(
|
||||
max_length=20,
|
||||
choices=CATEGORY_CHOICES,
|
||||
default=CATEGORY_GENERAL,
|
||||
db_index=True,
|
||||
help_text="Category of the ticket"
|
||||
)
|
||||
subject = models.CharField(max_length=255)
|
||||
message = models.TextField()
|
||||
email = models.EmailField(help_text="Contact email", blank=True)
|
||||
@@ -39,10 +62,11 @@ class Ticket(TrackedModel):
|
||||
ordering = ["-created_at"]
|
||||
|
||||
def __str__(self):
|
||||
return f"[{self.get_status_display()}] {self.subject}"
|
||||
return f"[{self.get_category_display()}] {self.subject}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# If user is set but email is empty, autofill from user
|
||||
if self.user and not self.email:
|
||||
self.email = self.user.email
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -4,16 +4,21 @@ from apps.accounts.serializers import UserSerializer
|
||||
|
||||
class TicketSerializer(serializers.ModelSerializer):
|
||||
user = UserSerializer(read_only=True)
|
||||
category_display = serializers.CharField(source='get_category_display', read_only=True)
|
||||
status_display = serializers.CharField(source='get_status_display', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
fields = [
|
||||
"id",
|
||||
"user",
|
||||
"category",
|
||||
"category_display",
|
||||
"subject",
|
||||
"message",
|
||||
"email",
|
||||
"status",
|
||||
"status_display",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
]
|
||||
@@ -25,3 +30,4 @@ class TicketSerializer(serializers.ModelSerializer):
|
||||
if request and not request.user.is_authenticated and not data.get('email'):
|
||||
raise serializers.ValidationError({"email": "Email is required for guests."})
|
||||
return data
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class TicketViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = TicketSerializer
|
||||
permission_classes = [permissions.AllowAny] # We handle granular perms in get_queryset/perform_create
|
||||
filter_backends = [DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["status"]
|
||||
filterset_fields = ["status", "category"]
|
||||
ordering_fields = ["created_at", "status"]
|
||||
ordering = ["-created_at"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user