diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce55..8ccc282 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94..ea61c96 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index 291d043..3a184a9 100644 --- a/config/settings.py +++ b/config/settings.py @@ -180,3 +180,6 @@ if EMAIL_USE_SSL: # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +LOGIN_REDIRECT_URL = 'dashboard' +LOGOUT_REDIRECT_URL = 'login' diff --git a/config/urls.py b/config/urls.py index bcfc074..fecf250 100644 --- a/config/urls.py +++ b/config/urls.py @@ -21,9 +21,10 @@ from django.conf.urls.static import static urlpatterns = [ path("admin/", admin.site.urls), + path("accounts/", include("django.contrib.auth.urls")), path("", include("core.urls")), ] if settings.DEBUG: urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") - urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..8463b1e 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc new file mode 100644 index 0000000..44ec54c Binary files /dev/null and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..934d1a3 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..35266b8 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd6..d7dfe7b 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..3a0401b 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,13 @@ from django.contrib import admin +from .models import Ticket, Comment -# Register your models here. +@admin.register(Ticket) +class TicketAdmin(admin.ModelAdmin): + list_display = ('id', 'title', 'status', 'priority', 'category', 'created_by', 'created_at') + list_filter = ('status', 'priority', 'category') + search_fields = ('title', 'description') + +@admin.register(Comment) +class CommentAdmin(admin.ModelAdmin): + list_display = ('ticket', 'author', 'created_at') + list_filter = ('created_at',) \ No newline at end of file diff --git a/core/forms.py b/core/forms.py new file mode 100644 index 0000000..08dce08 --- /dev/null +++ b/core/forms.py @@ -0,0 +1,21 @@ +from django import forms +from .models import Ticket, Comment + +class TicketForm(forms.ModelForm): + class Meta: + model = Ticket + fields = ['title', 'description', 'priority', 'category'] + widgets = { + 'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Brief summary of the issue'}), + 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 4, 'placeholder': 'Describe your problem in detail...'}), + 'priority': forms.Select(attrs={'class': 'form-select'}), + 'category': forms.Select(attrs={'class': 'form-select'}), + } + +class CommentForm(forms.ModelForm): + class Meta: + model = Comment + fields = ['text'] + widgets = { + 'text': forms.Textarea(attrs={'class': 'form-control', 'rows': 3, 'placeholder': 'Type your reply here...'}), + } diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..0d6058f --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# Generated by Django 5.2.7 on 2026-02-16 11:01 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Ticket', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('description', models.TextField()), + ('status', models.CharField(choices=[('open', 'Open'), ('pending', 'Pending'), ('resolved', 'Resolved'), ('closed', 'Closed')], default='open', max_length=20)), + ('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('urgent', 'Urgent')], default='medium', max_length=20)), + ('category', models.CharField(choices=[('technical', 'Technical Issue'), ('billing', 'Billing'), ('feature', 'Feature Request'), ('other', 'Other')], default='technical', max_length=20)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_tickets', to=settings.AUTH_USER_MODEL)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-updated_at'], + }, + ), + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='core.ticket')), + ], + options={ + 'ordering': ['created_at'], + }, + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..bdb0ea9 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..8cf848d 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,52 @@ from django.db import models +from django.contrib.auth.models import User -# Create your models here. +class Ticket(models.Model): + STATUS_CHOICES = [ + ('open', 'Open'), + ('pending', 'Pending'), + ('resolved', 'Resolved'), + ('closed', 'Closed'), + ] + PRIORITY_CHOICES = [ + ('low', 'Low'), + ('medium', 'Medium'), + ('high', 'High'), + ('urgent', 'Urgent'), + ] + CATEGORY_CHOICES = [ + ('technical', 'Technical Issue'), + ('billing', 'Billing'), + ('feature', 'Feature Request'), + ('other', 'Other'), + ] + + title = models.CharField(max_length=200) + description = models.TextField() + status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open') + priority = models.CharField(max_length=20, choices=PRIORITY_CHOICES, default='medium') + category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, default='technical') + + created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tickets') + assigned_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_tickets') + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"#{self.id} - {self.title}" + + class Meta: + ordering = ['-updated_at'] + +class Comment(models.Model): + ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, related_name='comments') + author = models.ForeignKey(User, on_delete=models.CASCADE) + text = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"Comment by {self.author} on {self.ticket}" + + class Meta: + ordering = ['created_at'] \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..0155d6e 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,79 @@ +{% load static %} -
- -