emile 1 year ago
parent 2c709854c2
commit 25a5714f56

Binary file not shown.

@ -4,15 +4,51 @@
<div class="w-full xxlg1:w-[75%] bg-white h-fit rounded-md shadow-md p-5">
<div class="w-full h-fit flex flex-col gap-2 bg-gray-100 shadow-md rounded-md px-3 py-3">
<p class="text-secondosiblue text-xl">Ticket: <span class="font-semibold">{{ticket.ticket_number}}</span></p>
<p class="text-secondosiblue text-[20px]">Ticket <span class="font-semibold">#{{ticket.ticket_number}}</span></p>
{% if last_ticket_status.status == 'Open' %}
<div class="flex justify-start items-center gap-1">
<div class="w-[16px] h-[16px] rounded-full bg-green-200 shadow-md"></div>
<p class="text-secondosiblue font-light">Opened by {{last_ticket_status.added_by.first_name}} at {{last_ticket_status.date_added}}</p>
</div>
{% elif last_ticket_status.status == 'Working On' %}
<div class="flex justify-start items-center gap-1">
<div class="w-[16px] h-[16px] rounded-full bg-yellow-200 shadow-md"></div>
<p class="text-secondosiblue font-light">Updated to 'Working On' by {{last_ticket_status.added_by.first_name}} at {{last_ticket_status.date_added}}</p>
</div>
{% elif last_ticket_status.status == 'Closed' %}
<div class="flex justify-start items-center gap-1">
<div class="w-[16px] h-[16px] rounded-full bg-red-200 shadow-md"></div>
<p class="text-secondosiblue font-light">Closed by Linode at 20-4-24 16:30</p>
<p class="text-secondosiblue font-light">Closed by {{last_ticket_status.added_by.first_name}} at {{last_ticket_status.date_added}}</p>
</div>
{% endif %}
<div class="w-full mt-3">
<p class="text-gray-500 font-light text-sm leading-7">{{ticket.description}}
</p>
</div>
{% if ticket.ticketattachment_set.all %}
<div class="w-full flex flex-wrap justify-end items-center gap-3">
<a>
<div class="flex items-center gap-1 text-secondosiblue hover:text-gray-500 duration-300 cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />
</svg>
{% for file in ticket.ticketattachment_set.all %}
<a href="{{file.file.url}}">{{ file.file }}{% if not forloop.last %}, {% endif %}</a>
{% endfor %}
</div>
</a>
</div>
{% endif %}
</div>
<div class="w-full flex flex-col gap-8 mt-5 s:mt-10">
<!-- REPLY 1 -->
{% for update in ticket_updates %}
@ -67,6 +103,22 @@
{{update.description}}
</p>
{% if update.ticketattachment_set.all %}
<div class="w-full flex flex-wrap justify-end items-center gap-3">
<a>
<div class="flex items-center gap-1 text-secondosiblue hover:text-gray-500 duration-300 cursor-pointer text-sm">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 text-secondosiblue">
<path stroke-linecap="round" stroke-linejoin="round" d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />
</svg>
{% for file in update.ticketattachment_set.all %}
<a href="{{file.file.url}}">{{ file.file }}{% if not forloop.last %}, {% endif %}</a>
{% endfor %}
</div>
</a>
</div>
{% endif %}
</div>
@ -112,7 +164,7 @@
<div class="w-full flex flex-col s:flex-row justify-end items-center gap-3">
<div class="w-full s:w-[50px] h-[50px] rounded-md bg-gray-50 shadow-md border border-gray-100 flex justify-center items-center p-2 cursor-pointer relative hover:scale-105 duration-300 transition-transform">
<input type="file" name="file" id="fileInput" class="opacity-0">
<input type="file" name="files" id="fileInput" class="opacity-0">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5 text-secondosiblue z-10 absolute pointer-events-none">
<path stroke-linecap="round" stroke-linejoin="round" d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />

@ -26,13 +26,100 @@
<div class="w-full flex flex-col gap-3 mt-5">
<div class="w-full bg-gray-200 rounded-md shadow-md h-fit p-3 flex items-center justify-between gap-5">
<div class="flex items-center gap-5 text-[17px]">
<p class="text-secondosiblue font-semibold cursor-pointer">Open Tickets</p>
<p class="text-gray-500 cursor-pointer">Closed Tickets</p>
<p class="text-secondosiblue font-semibold cursor-pointer" id="openTicketsLink">Open Tickets</p>
<p class="text-gray-500 cursor-pointer" id="closedTicketsLink">Closed Tickets</p>
</div>
</div>
<div class="overflow-x-auto border border-gray-300 rounded-md">
<!-- OPEN TICKETS -->
<div class="overflow-x-auto border border-gray-300 rounded-md" id="openTickets">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Subject
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Ticket ID
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Regarding
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 border-r border-gray-300 uppercase whitespace-nowrap">
Last Updated
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 border-r border-gray-300 uppercase whitespace-nowrap">
Updated By
</th>
<th scope="col"
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase whitespace-nowrap">
Actions
</th>
</tr>
</thead>
<!-- TABLE BODY -->
{% for ticket in open_tickets %}
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.title}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticket_number}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.regarding}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.last_update_date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.last_update_added_by}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<a href="{% url 'ticketdetails' ticket.ticket_number %}">
<div class="text-[15px] text-blue-500 cursor-pointer">
<i class="fa fa-eye"></i>
</div>
</a>
<a href="">
<div class="text-[15px] text-blue-500 cursor-pointer">
<i class="fa fa-edit"></i>
</div>
</a>
<div class="text-[15px] text-red-500 cursor-pointer">
<i class="fa fa-trash"></i>
</div>
</div>
</td>
</tr>
</tbody>
{% endfor %}
</table>
</div>
<!-- CLOSED TICKETS -->
<div class="overflow-x-auto border border-gray-300 rounded-md hidden" id="closedTickets">
<table class="min-w-full divide-y">
<!-- TABLE HEADER -->
<thead class="bg-gray-50">
@ -65,28 +152,28 @@
</thead>
<!-- TABLE BODY -->
{% for ticket in closed_tickets %}
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">My
Account Balance</p>
<p class="text-secondosiblue">{{ticket.title}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">22666766</p>
<p class="text-secondosiblue">{{ticket.ticket_number}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Django</p>
<p class="text-secondosiblue">{{ticket.regarding}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-2024</p>
<p class="text-secondosiblue">{{ticket.last_update_date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">Ositcom Ltd</p>
<p class="text-secondosiblue">{{ticket.last_update_added_by}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
@ -108,11 +195,19 @@
</td>
</tr>
</tbody>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript" src='{% static "js/tickets-filtering.js" %}'></script>
{% endblock %}

@ -245,14 +245,6 @@ def customers(request, *args, **kwargs):
return render(request, 'listing_pages/customers.html', context)
@staff_login_required
def tickets(request, *args, **kwargs):
context = {
}
return render(request, 'listing_pages/tickets.html', context)
@staff_login_required
@ -334,6 +326,53 @@ def my_tasks(request, *args, **kwargs):
return render(request, 'listing_pages/tasks.html', context)
@staff_login_required
def tickets(request, *args, **kwargs):
if request.user.is_superuser:
open_tickets = Ticket.objects.filter(status__in=['Open', 'Working On'])
closed_tickets = Ticket.objects.filter(status__in=['Closed'])
else:
open_tickets = Ticket.objects.filter(status__in=['Open', 'Working On'], department=request.user.staffprofile.staff_position.department)
closed_tickets = Ticket.objects.filter(status__in=['Closed'], department=request.user.staffprofile.staff_position.department)
for ticket in open_tickets:
unread_updates_count = 0
last_update = ticket.ticketupdate_set.exclude(added_by=request.user).order_by('-date_added').first()
if last_update:
last_update_added_by = last_update.added_by.first_name
last_update_date_added = last_update.date_added
else:
last_update_added_by = None
last_update_date_added = None
for ticket_update in ticket.ticketupdate_set.exclude(added_by=request.user):
if not TicketRead.objects.filter(ticket_update=ticket_update, user=request.user, read=True).exists():
unread_updates_count += 1
ticket.unread_updates_count = unread_updates_count
ticket.last_update_added_by = last_update_added_by
ticket.last_update_date_added = last_update_date_added
for ticket in closed_tickets:
last_update = ticket.ticketupdate_set.order_by('-date_added').first()
if last_update:
last_update_added_by = last_update.added_by
last_update_date_added = last_update.date_added
else:
last_update_added_by = None
last_update_date_added = None
ticket.last_update_added_by = last_update_added_by
ticket.last_update_date_added = last_update_date_added
context = {
'open_tickets': open_tickets,
'closed_tickets': closed_tickets
}
return render(request, 'listing_pages/tickets.html', context)
@staff_login_required
def my_notes(request):
@ -444,13 +483,16 @@ def customerdetails(request, customer_id):
def ticket_details(request, ticket_number):
ticket = get_object_or_404(Ticket, ticket_number=ticket_number)
ticket_updates = TicketUpdate.objects.filter(ticket=ticket).order_by('id')
for update in ticket_updates:
for update in TicketUpdate.objects.filter(ticket=ticket).exclude(added_by=request.user).order_by('id'):
if not TicketRead.objects.filter(ticket_update=update, user=request.user).exists():
TicketRead.objects.create(ticket_update=update, user=request.user, read=True)
last_ticket_status = TicketStatusUpdate.objects.all().last()
context = {
'ticket' : ticket,
'ticket_updates': ticket_updates,
'last_ticket_status': last_ticket_status
}

@ -0,0 +1,28 @@
function showOpenTickets() {
openTicketsContainer.classList.remove('hidden');
closedTicketsContainer.classList.add('hidden');
openTicketsLink.classList.add('text-secondosiblue', 'font-semibold');
closedTicketsLink.classList.remove('text-secondosiblue', 'font-semibold');
closedTicketsLink.classList.add('text-gray-500');
}
function showClosedTickets() {
openTicketsContainer.classList.add('hidden');
closedTicketsContainer.classList.remove('hidden');
closedTicketsLink.classList.add('text-secondosiblue', 'font-semibold');
openTicketsLink.classList.remove('text-secondosiblue', 'font-semibold');
openTicketsLink.classList.add('text-gray-500');
}
const openTicketsLink = document.getElementById('openTicketsLink');
const closedTicketsLink = document.getElementById('closedTicketsLink');
const openTicketsContainer = document.getElementById('openTickets');
const closedTicketsContainer = document.getElementById('closedTickets');
openTicketsLink.addEventListener('click', showOpenTickets);
closedTicketsLink.addEventListener('click', showClosedTickets);
showOpenTickets();
Loading…
Cancel
Save