default migrations

This commit is contained in:
Corban-Lee Jones 2024-01-05 12:06:50 +00:00
parent f630e00c21
commit a59baefd8f
23 changed files with 423 additions and 185 deletions

View File

@ -1,8 +1,8 @@
# -*- encoding: utf-8 -*-
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
from .models import User, Department
admin.site.register(User, UserAdmin)
admin.site.register(User)
admin.site.register(Department)

View File

@ -5,14 +5,15 @@ Copyright (c) 2019 - present AppSeed.us
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import User
class LoginForm(forms.Form):
username = forms.CharField(
widget=forms.TextInput(
email = forms.EmailField(
widget=forms.EmailInput(
attrs={
"placeholder": "Username",
"placeholder": "Email Address",
"class": "form-control"
}
))
@ -26,10 +27,17 @@ class LoginForm(forms.Form):
class SignUpForm(UserCreationForm):
username = forms.CharField(
forename = forms.CharField(
widget=forms.TextInput(
attrs={
"placeholder": "Username",
"placeholder": "Forename",
"class": "form-control"
}
))
surname = forms.CharField(
widget=forms.TextInput(
attrs={
"placeholder": "Surname",
"class": "form-control"
}
))
@ -50,11 +58,11 @@ class SignUpForm(UserCreationForm):
password2 = forms.CharField(
widget=forms.PasswordInput(
attrs={
"placeholder": "Password check",
"placeholder": "Password (Again)",
"class": "form-control"
}
))
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
fields = ('forename', 'surname', 'email', 'password1', 'password2')

View File

@ -1,8 +1,7 @@
# Generated by Django 3.2.16 on 2024-01-04 14:05
# Generated by Django 3.2.16 on 2024-01-05 12:04
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
@ -16,30 +15,36 @@ class Migration(migrations.Migration):
]
operations = [
migrations.CreateModel(
name='Department',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=150)),
('icon', models.CharField(blank=True, max_length=32, null=True)),
],
),
migrations.CreateModel(
name='User',
fields=[
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('icon', models.ImageField(default='users/default.webp', upload_to='users', verbose_name='profile picture')),
('email', models.EmailField(error_messages={'unique': 'A user with this email address already exists.'}, max_length=254, unique=True, verbose_name='email address')),
('forename', models.CharField(help_text='This should be your real first name.', max_length=150, verbose_name='first name')),
('surname', models.CharField(help_text='This should be your real last name.', max_length=150, verbose_name='last name')),
('create_timestamp', models.DateTimeField(default=django.utils.timezone.now, help_text='When the user was created.', verbose_name='Creation Date')),
('edit_timestamp', models.DateTimeField(default=django.utils.timezone.now, help_text='When the user was last edited.', verbose_name='Last Edited')),
('is_active', models.BooleanField(default=True, help_text='Use as a "soft delete" rather than deleting the user.', verbose_name='active status')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_superuser', models.BooleanField(default=False, help_text='Designates whether the user has unrestricted site control.', verbose_name='superuser status')),
('department', models.ForeignKey(blank=True, help_text='Which department does this user belong to?', null=True, on_delete=django.db.models.deletion.SET_NULL, to='authentication.department', verbose_name='department')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.16 on 2024-01-04 14:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='user',
name='icon',
field=models.ImageField(default='users/default.webp', upload_to='users'),
),
]

View File

@ -1,24 +0,0 @@
# Generated by Django 3.2.16 on 2024-01-04 14:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0002_user_icon'),
]
operations = [
migrations.AddField(
model_name='user',
name='name',
field=models.CharField(default='Corban-Lee Jones', max_length=150),
preserve_default=False,
),
migrations.AlterField(
model_name='user',
name='email',
field=models.EmailField(max_length=254, unique=True),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.16 on 2024-01-04 22:15
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('authentication', '0003_auto_20240104_1447'),
]
operations = [
migrations.AlterModelManagers(
name='user',
managers=[
],
),
]

View File

@ -0,0 +1,35 @@
# Generated by Django 3.2.16 on 2024-01-05 10:44
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
from django.apps import apps
import uuid
def create_departments(app, schema_editor):
Department = apps.get_model("authentication", "Department")
data = [
{"title": "Development", "icon": None},
{"title": "Sales", "icon": None},
{"title": "Marketing", "icon": None},
{"title": "Management", "icon": None},
{"title": "Business Strategy", "icon": None},
]
for item in data:
priority = Department.objects.create(title=item["title"], icon=item["icon"])
class Migration(migrations.Migration):
dependencies = [
("authentication", "0001_initial"),
]
operations = [
migrations.RunPython(create_departments)
]

View File

@ -3,23 +3,39 @@
import uuid
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.utils.translation import gettext_lazy as _
class Department(models.Model):
title = models.CharField(max_length=150)
icon = models.CharField(max_length=32, null=True, blank=True)
def __str__(self):
return self.title
def serialize(self) -> dict:
return {
"title": self.title,
"icon": self.icon
}
class UserManager(BaseUserManager):
def create_user(self, email: str, name: str, password: str=None, **extra_fields):
def create_user(self, email: str, forename: str, surname: str, password: str=None, **extra_fields):
if not email:
raise ValueError("Please provide an email address")
email = self.normalize_email(email)
user = self.model(email=email, name=name, **extra_fields)
user = self.model(email=email, forename=forename, surname=surname, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email: str, name: str, password: str, **extra_fields):
def create_superuser(self, email: str, forename: str, surname: str, password: str, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_active", True)
@ -30,27 +46,108 @@ class UserManager(BaseUserManager):
if not extra_fields.get("is_superuser"):
raise ValueError("Superuser must have is_superuser=True")
return self.create_user(email, name, password, **extra_fields)
return self.create_user(email, forename, surname, password, **extra_fields)
class User(AbstractUser):
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
icon = models.ImageField(upload_to="users", default="users/default.webp")
name = models.CharField(max_length=150)
email = models.EmailField(unique=True)
icon = models.ImageField(_("profile picture"), upload_to="users", default="users/default.webp")
email = models.EmailField(
_("email address"),
unique=True,
error_messages = {
"unique": _("A user with this email address already exists.")
}
)
forename = models.CharField(
_("first name"),
max_length=150,
help_text=_("This should be your real first name.")
)
surname = models.CharField(
_("last name"),
max_length=150,
help_text=_("This should be your real last name.")
)
department = models.ForeignKey(
Department,
blank=True,
null=True,
on_delete=models.SET_NULL,
verbose_name=_("department"),
help_text=_("Which department does this user belong to?")
)
create_timestamp = models.DateTimeField(
_("Creation Date"),
editable=True,
default=timezone.now,
help_text=_("When the user was created.")
)
edit_timestamp = models.DateTimeField(
_("Last Edited"),
editable=True,
default=timezone.now,
help_text=_("When the user was last edited.")
)
is_active = models.BooleanField(
_("active status"),
default=True,
help_text=_('Use as a "soft delete" rather than deleting the user.')
)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site.")
)
is_superuser = models.BooleanField(
_("superuser status"),
default=False,
help_text=_("Designates whether the user has unrestricted site control.")
)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["name"]
EMAIL_FIELD = "email"
REQUIRED_FIELDS = ["forename", "surname"]
objects = UserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def __str__(self):
return self.name
return f"{self.id}{self.email}{self.formal_fullname}"
def save(self, *args, **kwargs):
self.edit_timestamp = timezone.now()
super().save(*args, **kwargs)
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
@property
def fullname(self) -> str:
return f"{self.forename} {self.surname}"
@property
def formal_fullname(self) -> str:
return f"{self.surname}, {self.forename}"
def serialize(self) -> dict:
department = self.department.serialize() if self.department else None
return {
"id": self.id,
"icon": self.icon.url,
"name": self.name,
"email": self.email
"email": self.email,
"forename": self.forename,
"surname": self.surname,
"department": department,
"create_timestamp": self.create_timestamp,
"edit_timestamp": self.edit_timestamp
}

View File

@ -15,9 +15,9 @@ def login_view(request):
if request.method == "POST":
if form.is_valid():
username = form.cleaned_data.get("username")
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(username=username, password=password)
user = authenticate(username=email, password=password)
if user is not None:
login(request, user)
return redirect("/")
@ -36,10 +36,16 @@ def register_user(request):
if request.method == "POST":
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
user = form.save(commit=False)
# Develepment, give all new users admin
user.is_staff = True
user.is_superuser = True
user.save()
email = form.cleaned_data.get("email")
raw_password = form.cleaned_data.get("password1")
user = authenticate(username=username, password=raw_password)
user = authenticate(username=email, password=raw_password)
msg = 'User created successfully.'
success = True

View File

@ -2,6 +2,8 @@
from django.contrib import admin
from .models import Ticket
from .models import Ticket, TicketPriority, TicketTag
admin.site.register(Ticket)
admin.site.register(TicketPriority)
admin.site.register(TicketTag)

View File

@ -1,9 +1,10 @@
# Generated by Django 3.2.16 on 2024-01-04 14:05
# Generated by Django 3.2.16 on 2024-01-05 10:44
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
class Migration(migrations.Migration):
@ -34,12 +35,14 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Ticket',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=60)),
('description', models.TextField(max_length=650)),
('create_timestamp', models.DateTimeField(default=django.utils.timezone.now)),
('edit_timestamp', models.DateTimeField(default=django.utils.timezone.now)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('title', models.CharField(help_text='An extremely short summary of the ticket subject.', max_length=100, verbose_name='title')),
('description', models.TextField(help_text='Detailed description of the ticket subject.', max_length=650, verbose_name='description')),
('create_timestamp', models.DateTimeField(default=django.utils.timezone.now, help_text='When the user was created.', verbose_name='Creation Date')),
('edit_timestamp', models.DateTimeField(default=django.utils.timezone.now, help_text='When the user was last edited.', verbose_name='Last Edited')),
('author', models.ForeignKey(help_text='The creator of the ticket.', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='author')),
('priority', models.ForeignKey(help_text='The importance level of this ticket.', on_delete=django.db.models.deletion.CASCADE, to='home.ticketpriority', verbose_name='priority')),
('tags', models.ManyToManyField(blank=True, help_text='Categories of the ticket.', to='home.TicketTag', verbose_name='tags')),
],
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 3.2.16 on 2024-01-04 23:51
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('home', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='ticket',
name='id',
field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False),
),
]

View File

@ -0,0 +1,34 @@
# Generated by Django 3.2.16 on 2024-01-05 10:44
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
from django.apps import apps
import uuid
def create_priorities(app, schema_editor):
TicketPriority = apps.get_model("home", "TicketPriority")
data = [
{"title": "Urgent", "colour": "#FF0000"},
{"title": "High", "colour": "#FFA500"},
{"title": "Normal", "colour": "#FFFF00"},
{"title": "Low", "colour": "#008000"}
]
for item in data:
priority = TicketPriority.objects.create(title=item["title"], colour=item["colour"])
class Migration(migrations.Migration):
dependencies = [
("home", "0001_initial"),
]
operations = [
migrations.RunPython(create_priorities)
]

View File

@ -0,0 +1,36 @@
# Generated by Django 3.2.16 on 2024-01-05 10:44
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
from django.apps import apps
import uuid
def create_tags(app, schema_editor):
TicketTag = apps.get_model("home", "TicketTag")
data = [
{"title": "Network", "colour": "#0000FF"},
{"title": "Software", "colour": "#FFA500"},
{"title": "Hardware", "colour": "#808080"},
{"title": "Question", "colour": "#FFFF00"},
{"title": "Require's Help", "colour": "#00FF00"},
{"title": "Issue", "colour": "#FF0000"}
]
for item in data:
priority = TicketTag.objects.create(title=item["title"], colour=item["colour"])
class Migration(migrations.Migration):
dependencies = [
("home", "default_priorities"),
]
operations = [
migrations.RunPython(create_tags)
]

View File

@ -7,28 +7,86 @@ from datetime import timedelta, datetime
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
class TicketPriority(models.Model):
title = models.CharField(max_length=32)
colour = models.CharField(max_length=7)
def __str__(self):
return self.title
def serialize(self) -> dict:
return {
"title": self.title,
"colour": self.colour
}
class TicketTag(models.Model):
title = models.CharField(max_length=32)
colour = models.CharField(max_length=7)
def __str__(self):
return self.title
def serialize(self) -> dict:
return {
"title": self.title,
"colour": self.colour
}
class Ticket(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=60)
description = models.TextField(max_length=650)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
create_timestamp = models.DateTimeField(editable=True, default=timezone.now)
edit_timestamp = models.DateTimeField(editable=True, default=timezone.now)
title = models.CharField(
_("title"),
max_length=100,
help_text=_("An extremely short summary of the ticket subject.")
)
description = models.TextField(
_("description"),
max_length=650,
help_text=_("Detailed description of the ticket subject.")
)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name=_("author"),
on_delete=models.CASCADE,
help_text=_("The creator of the ticket.")
)
priority = models.ForeignKey(
TicketPriority,
verbose_name=_("priority"),
on_delete=models.CASCADE,
help_text=_("The importance level of this ticket.")
)
tags = models.ManyToManyField(
TicketTag,
verbose_name=_("tags"),
blank=True,
help_text=_("Categories of the ticket.")
)
create_timestamp = models.DateTimeField(
_("Creation Date"),
editable=True,
default=timezone.now,
help_text=_("When the user was created.")
)
edit_timestamp = models.DateTimeField(
_("Last Edited"),
editable=True,
default=timezone.now,
help_text=_("When the user was last edited.")
)
def __str__(self):
return f"#{self.id}{self.title}{self.author}"
return f"#{self.id}{self.title}{f' {self.author.department.title}' if self.author.department else ''} {self.author.formal_fullname}"
def clean_description(self):
cleaned_description = bleach.clean(
@ -40,6 +98,7 @@ class Ticket(models.Model):
def save(self, *args, **kwargs):
self.description = self.clean_description()
self.edit_timestamp = timezone.now()
super().save(*args, **kwargs)
@property
@ -91,5 +150,7 @@ class Ticket(models.Model):
"edit_timestamp": self.edit_timestamp,
"is_edited": self.is_edited,
"is_older_than_day": self.is_older_than_day,
"timestamp": self.timestamp
"timestamp": self.timestamp,
"priority": self.priority.serialize(),
"tags": [tag.serialize() for tag in self.tags.all()]
}

View File

@ -11,7 +11,8 @@ from django.shortcuts import render
from django.urls import reverse
from django.forms.models import model_to_dict
from .models import Ticket
from ..authentication.models import Department
from .models import Ticket, TicketPriority, TicketTag
@login_required()
@ -22,8 +23,15 @@ def dashboard(request):
@login_required()
def tickets(request):
tickets = Ticket.objects.all().order_by("-create_timestamp")
priorities = TicketPriority.objects.all()
tags = TicketTag.objects.all()
departments = Department.objects.all()
context = {
"tickets": tickets,
"priorities": priorities,
"tags": tags,
"departments": departments,
"dayago": datetime.now() - timedelta(hours=24)
}

View File

@ -32,10 +32,10 @@
{% csrf_token %}
<div class="mb-3">
<label class="text-normal text-dark form-label">Username</label>
{{ form.username }}
<label class="text-normal text-dark form-label">Email Address</label>
{{ form.email }}
</div>
<span class="text-error">{{ form.username.errors }}</span>
<span class="text-error">{{ form.email.errors }}</span>
<div class="mb-3">
<label class="text-normal text-dark form-label">Password</label>

View File

@ -40,10 +40,16 @@
{% csrf_token %}
<div class="mb-3">
<label class="form-label" class="text-normal text-dark">Username</label>
{{ form.username }}
<label class="form-label" class="text-normal text-dark">Forename</label>
{{ form.forename }}
</div>
<span class="text-error">{{ form.username.errors }}</span>
<span class="text-error">{{ form.forename.errors }}</span>
<div class="mb-3">
<label class="form-label" class="text-normal text-dark">Surname</label>
{{ form.surname }}
</div>
<span class="text-error">{{ form.surname.errors }}</span>
<div class="mb-3">
<label class="form-label" class="text-normal text-dark">Email Address</label>
@ -58,7 +64,7 @@
<span class="text-error">{{ form.password1.errors }}</span>
<div class="mb-3">
<label class="form-label" class="text-normal text-dark">Password Check</label>
<label class="form-label" class="text-normal text-dark">Password (Again)</label>
{{ form.password2 }}
</div>
<span class="text-error">{{ form.password2.errors }}</span>

View File

@ -22,39 +22,43 @@
<li class="nav-item">
<h6>Filters</h6>
</li>
<li class="nav-item ps-3 mT-15">
<h6 class="small">Priority</h6>
<div class="form-check">
<input type="checkbox" id="priority1" class="form-check-input">
<label for="priority1" class="form-check-label">High</label>
</div>
<div class="form-check">
<input type="checkbox" id="priority2" class="form-check-input">
<label for="priority2" class="form-check-label">Medium</label>
</div>
<div class="form-check">
<input type="checkbox" id="priority3" class="form-check-input">
<label for="priority3" class="form-check-label">Low</label>
</div>
</li>
<li class="nav-item ps-3 mT-15">
<h6 class="small">Department</h6>
<div class="form-check">
<input type="checkbox" id="sales" class="form-check-input">
<label for="sales" class="form-check-label">Sales</label>
</div>
<div class="form-check">
<input type="checkbox" id="strategy" class="form-check-input">
<label for="strategy" class="form-check-label">Strategy</label>
</div>
<div class="form-check">
<input type="checkbox" id="marketing" class="form-check-input">
<label for="marketing" class="form-check-label">Marketing</label>
</div>
</li>
<li class="nav-item ps-3 mT-15">
<h6 class="small">Tags</h6>
</li>
{% if priorities %}
<li class="nav-item ps-3 mT-15">
<h6 class="small">Priority</h6>
{% for priority in priorities %}
<div class="form-check">
<input type="checkbox" id="priority-{{ priority.id }}" class="form-check-input">
<label for="priority-{{ priority.id }}" class="form-check-label">{{ priority.title }}</label>
</div>
{% endfor %}
</li>
{% endif %}
{% if departments %}
<li class="nav-item ps-3 mT-15">
<h6 class="small">Department</h6>
{% for department in departments %}
<div class="form-check">
<input type="checkbox" id="department-{{ department.id }}" class="form-check-input">
<label for="department-{{ department.id }}" class="form-check-label">{{ department.title }}</label>
</div>
{% endfor %}
</li>
{% endif %}
{% if tags %}
<li class="nav-item ps-3 mT-15">
<h6 class="small">Tags</h6>
{% for tag in tags %}
<div class="form-check">
<input type="checkbox" id="tag-{{ tag.id }}" class="form-check-input">
<label for="tag-{{ tag.id }}" class="form-check-label">{{ tag.title }}</label>
</div>
{% endfor %}
</li>
{% endif %}
<!-- <li class="nav-item mt-5">
<a href="javascript:void(0)" class="nav-link c-grey-800 cH-blue-500 actived">
<div class="peers ai-c jc-sb">
@ -209,7 +213,7 @@
<div class="peer peer-greed ov-h">
<div class="peers ai-c">
<div class="peer peer-greed">
<h6 class="ticket-author mb-0">{{ ticket.author }}</h6>
<h6 class="ticket-author mb-0">{{ ticket.author.fullname }}</h6>
</div>
<div class="peer">
<small class="ticket-timestamp">
@ -394,7 +398,7 @@
$("#ticketAuthorImg").prop("src", "");
$("#ticketTimestamp").text("");
$("#btnGroupDrop2").hide();
$("#ticketBadges").hide();
$("#ticketBadges").empty().hide();
if (displayedTicketID === ticketID) {
displayedTicketID = -1;
@ -411,19 +415,31 @@
csrfmiddlewaretoken: '{{ csrf_token }}'
},
success: function (data) {
alert(JSON.stringify(data, null, 4));
console.log(JSON.stringify(data, null, 4));
var ticket = data.ticket;
var author = ticket.author;
var department = author.department;
var priority = ticket.priority;
$("#ticketTitle").text(ticket.title);
$("#ticketDesc").append($(ticket.description));
$("#ticketAuthor").text(author.name);
$("#ticketDesc").append($(`<div>${ticket.description}</div>`));
$("#ticketAuthor").text(`${author.forename} ${author.surname}`);
$("#ticketAuthorImg").show();
$("#ticketAuthorImg").prop("src", author.icon);
$("#btnGroupDrop2").show();
$("#ticketBadges").show();
$("#ticketBadges").append($(`<div class="badge me-1" style="background-color: ${priority.colour};">${priority.title}</div>`));
if (department != null) {
$("#ticketBadges").append($(`<div class="badge bgc-deep-purple-500 me-1">${department.title}</div>`));
}
ticket.tags.forEach(function(tag) {
$("#ticketBadges").append($(`<div class="badge me-1" style="background-color: ${tag.colour};">${tag.title}</div>`));
});
// timestamp
var timestamp = new Date(ticket.timestamp);
var formattedTime;

View File

@ -184,7 +184,7 @@
<img class="w-2r bdrs-50p" src="{{ request.user.icon.url }}" alt="">
</div>
<div class="peer">
<span class="fsz-sm c-grey-900">{{ request.user }}</span>
<span class="fsz-sm c-grey-900">{{ request.user.formal_fullname }}</span>
</div>
</a>
<ul class="dropdown-menu fsz-sm">

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
media/users/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB