emile 10 months ago
parent ee3e406cf3
commit 2012967043

@ -46,13 +46,9 @@
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Date Created
</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 uppercase whitespace-nowrap">
Updated By
Last Updated
</th>
</tr>
</thead>
@ -62,7 +58,7 @@
{% for ticket in open_tickets %}
<tr data-href="{% url 'ticketroom' ticket.ticket_number %}" class="hover:bg-gray-100 duration-300 cursor-pointer">
<td class="min-w-[250px] max-w-[250px] px-6 py-4 text-center text-sm border-r border-gray-300">
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<div class="w-full flex {% if ticket.unread_updates_count > 0 %} justify-between {% else %} justify-center {% endif %} items-center gap-3">
<a href="{% url 'ticketroom' ticket.ticket_number %}">
<p class="text-secondosiblue">{{ticket.title }}</p>
@ -90,12 +86,10 @@
<p class="text-secondosiblue">{{ ticket.opened_date }}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.added_by.first_name}}</p>
{% if ticket.ticketupdate_set.all %}
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.date_added}} <br> by {{ticket.ticketupdate_set.last.added_by.first_name}}</p>
{% endif %}
</td>
</tr>
{% endfor %}
@ -124,13 +118,9 @@
class="px-6 py-3 text-sm font-medium text-gray-500 uppercase border-r border-gray-300 whitespace-nowrap">
Date Created
</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 uppercase whitespace-nowrap">
Updated By
Last Updated
</th>
</tr>
</thead>
@ -159,12 +149,10 @@
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.added_by.first_name}}</p>
{% if ticket.ticketupdate_set.all %}
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.date_added}} <br> by {{ticket.ticketupdate_set.last.added_by.first_name}}</p>
{% endif %}
</td>
</tr>
{% endfor %}

Binary file not shown.

@ -3,6 +3,7 @@ from django.contrib.auth.models import AnonymousUser
from datetime import datetime, timedelta
from django.shortcuts import get_object_or_404
from django.db.models import Max, F
from support.models import *
def calculate_time_ago(status):
@ -22,11 +23,7 @@ def calculate_time_ago(status):
def utilities(request):
latest_connections = Connection.objects.filter(
user__staffprofile__isnull=False
).values('user').annotate(
latest_connection=Max('date')
)
latest_connections = Connection.objects.filter(user__staffprofile__isnull=False).values('user').annotate(latest_connection=Max('date'))
online_staff_profiles = []
for connection in latest_connections:
user_id = connection['user']
@ -34,32 +31,87 @@ def utilities(request):
last_connection = Connection.objects.filter(user_id=user_id, date=latest_connection).first()
if last_connection.status == 'Online':
online_staff_profiles.append(last_connection.user.staffprofile)
notes = None
recent_note = None
user_offline=None
if request.user.is_authenticated:
open_task_count = 0
working_on_task_count = 0
open_tickets = None
closed_tickets = None
if request.user.is_authenticated and StaffProfile.objects.filter(user=request.user):
notes = Note.objects.filter(user=request.user).order_by('-date')[:6]
recent_note = Note.objects.filter(user=request.user).last()
last_user_activity = Connection.objects.filter(user=request.user).last()
if last_user_activity and last_user_activity.status == 'Offline':
# Send 'user_offline' object to your context
user_offline = True
else:
user_offline = False
if request.user.is_authenticated and request.user.is_superuser:
open_task_count = Task.objects.filter(status='Open').count()
working_on_task_count = Task.objects.filter(status='Working On').count()
if request.user.is_superuser:
open_task_count = Task.objects.filter(status='Open').count()
working_on_task_count = Task.objects.filter(status='Working On').count()
all_tickets = Ticket.objects.all()
all_tickets_with_update_date = all_tickets.annotate(latest_update_date=Max('ticketupdate__date_added'))
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
open_tickets = []
closed_tickets = []
for ticket in all_tickets_ordered:
last_status = ticket.ticketstatus_set.last()
if last_status:
last_status = last_status.status
if last_status == 'Closed':
closed_tickets.append(ticket)
else:
open_tickets.append(ticket)
else:
# If no status is found, assume it's open
open_tickets.append(ticket)
else:
open_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Open').count()
working_on_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Working On').count()
all_tickets = Ticket.objects.all()
filtered_tickets = []
for ticket in all_tickets:
staff_profiles = ticket.get_all_ticket_staff()
if any(staff.user == request.user for staff in staff_profiles):
filtered_tickets.append(ticket)
all_tickets = Ticket.objects.filter(id__in=[ticket.id for ticket in filtered_tickets]).annotate(
latest_update_date=Max('ticketupdate__date_added'))
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
open_tickets = []
closed_tickets = []
for ticket in all_tickets_ordered:
last_status = ticket.ticketstatus_set.last()
if last_status:
last_status = last_status.status
if last_status == 'Closed':
closed_tickets.append(ticket)
else:
open_tickets.append(ticket)
else:
# If no status is found, assume it's open
open_tickets.append(ticket)
elif request.user.is_authenticated and StaffProfile.objects.filter(user=request.user):
open_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Open').count()
working_on_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Working On').count()
else:
# Handle the case when the user is not logged in
open_task_count = 0
working_on_task_count = 0
for ticket in open_tickets:
unread_updates_count = 0
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
total_tasks = open_task_count + working_on_task_count
@ -69,19 +121,18 @@ def utilities(request):
today = datetime.now().date()
# Fetch the latest statuses from the last 24 hours
latest_statuses = Status.objects.filter(date=today).order_by('-id')
# Calculate time ago for each status and store it in a dictionary
latest_statuses_time_ago = [{'status': status, 'time_ago': calculate_time_ago(status)} for status in latest_statuses]
recent_logged_in_staffs = User.objects.filter(
staffprofile__isnull=False, # Ensure there's a StaffProfile associated
last_login__isnull=False # Ensure they have logged in at least once
staffprofile__isnull=False,
last_login__isnull=False
).order_by('-last_login')[:8]
recent_logged_in_customers = User.objects.filter(
customerprofile__isnull=False, # Ensure there's a CustomerProfile associated
last_login__isnull=False # Ensure they have logged in at least once
customerprofile__isnull=False,
last_login__isnull=False
).order_by('-last_login')[:8]
return {'total_tasks': total_tasks,
@ -93,6 +144,8 @@ def utilities(request):
'user_offline' : user_offline,
'recent_logged_in_staffs' : recent_logged_in_staffs,
'recent_logged_in_customers' : recent_logged_in_customers,
'open_tickets': open_tickets,
'closed_tickets': closed_tickets
}

@ -141,13 +141,9 @@
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 uppercase whitespace-nowrap">
Updated By
Last Updated
</th>
</tr>
</thead>
@ -157,7 +153,7 @@
<tbody class="bg-white divide-y divide-gray-200">
<tr data-href="{% url 'ticketroom' ticket.ticket_number %}"
class="hover:bg-gray-100 duration-300 cursor-pointer">
<td class="min-w-[250px] max-w-[250px] px-6 py-4 text-center text-sm border-r border-gray-300">
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<div class="w-full flex {% if ticket.unread_updates_count > 0 %} justify-between {% else %} justify-center {% endif %} items-center gap-3">
<a href="{% url 'ticketroom' ticket.ticket_number %}">
<p class="text-secondosiblue">{{ticket.title }}</p>
@ -181,14 +177,11 @@
<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.ticketupdate_set.last.date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.added_by.first_name}}</p>
{% if ticket.ticketupdate_set.all %}
<p class="text-secondosiblue">{{ticket.ticketupdate_set.last.date_added}} <br> by {{ticket.ticketupdate_set.last.added_by.first_name}}</p>
{% endif %}
</td>
</tr>
</tbody>

@ -5,6 +5,10 @@
<!-- LEFT SIDE -->
<div class="w-full xxlg1:w-[75%] flex flex-col gap-5">
<!-- RESPONSE MESSGAE FOR SHARING A TICKET -->
<div id="successMessage"
class="fixed mx-auto top-10 opacity-0 w-[85%] s:w-fit px-9 s:px-14 py-3 rounded-md bg-osiblue bg-opacity-80 text-white text-center rounded-t-md shadow-md z-10 pointer-events-none">
</div>
<!-- TICKETS -->
@ -30,10 +34,6 @@
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>
@ -41,71 +41,82 @@
</thead>
<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 Subject</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">234233</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">ggg</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-234</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">20-2-234</p>
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<button onclick="myFunction()">
<input type="text" class="hidden"
value="https://osina.ositcom.com/my-tickets/{{ticket.ticket_number}}/"
id="myInput">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[16px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" />
</svg>
</button>
<a href="">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
<path stroke-linecap="round" stroke-linejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
</a>
<a href="">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
</svg>
</a>
<div class="cursor-pointer deleteTicketButton" data-modal-url="">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[18px] text-red-500 hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
{% for ticket in open_tickets %}
<tr>
<td class="px-6 py-4 text-sm border-r border-gray-300">
<div class="w-full flex {% if ticket.unread_updates_count > 0 %} justify-between {% else %} justify-center text-center {% endif %} items-center gap-3">
<p class="text-secondosiblue">{{ticket.title}}</p>
{% if ticket.unread_updates_count > 0 %}
<div>
<div
class="w-[25px] h-[25px] rounded-full bg-green-700 text-white flex justify-center items-center text-sm">
<p>{{ticket.unread_updates_count}}</p>
</div>
</div>
{% endif %}
</div>
</div>
</td>
</tr>
</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">
{% if ticket.ticketupdate_set.all %}
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.date_added}} <br> by {{ticket.ticketupdate_set.all.last.added_by.first_name}}</p>
{% endif %}
</td>
<td class="px-6 py-4 text-center text-sm">
<div class="flex justify-center items-center gap-3">
<button class="copyButton">
<input type="text" class="hidden copyInput"
value="https://osina.ositcom.com/my-tickets/{{ticket.ticket_number}}/">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[16px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z" />
</svg>
</button>
<a href="{% url 'ticketroom' ticket.ticket_number %}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
<path stroke-linecap="round" stroke-linejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
</a>
<a href="">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[18px] text-fifthosiblue hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
</svg>
</a>
<div class="cursor-pointer deleteTicketButton" data-modal-url="">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="w-[18px] text-red-500 hover:scale-110 duration-500 transition-transform">
<path stroke-linecap="round" stroke-linejoin="round"
d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
</div>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
@ -351,6 +362,7 @@
<!---------------------- JS SCRIPTS -------------------->
<script type="text/javascript" src='{% static "js/projects/calculate-all-pinned-projects-time.js" %}'></script>
<script type="text/javascript" src='{% static "js/tickets/share-ticket.js" %}'></script>
{% endblock content %}

@ -58,10 +58,6 @@
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
@ -75,7 +71,7 @@
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="min-w-[300px] max-w-[300px] px-6 py-4 text-sm border-r border-gray-300">
<td class="px-6 py-4 text-sm border-r border-gray-300">
<div class="w-full flex {% if ticket.unread_updates_count > 0 %} justify-between {% else %} justify-center text-center {% endif %} items-center gap-3">
<p class="text-secondosiblue">{{ticket.title}}</p>
@ -99,12 +95,9 @@
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.added_by.first_name}}
</p>
{% if ticket.ticketupdate_set.all %}
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.date_added}} <br> by {{ticket.ticketupdate_set.all.last.added_by.first_name}}</p>
{% endif %}
</td>
<td class="px-6 py-4 text-center text-sm">
@ -181,10 +174,6 @@
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
@ -210,12 +199,9 @@
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.date_added}}</p>
</td>
<td class="px-6 py-4 text-center text-sm border-r border-gray-300">
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.added_by.first_name}}
</p>
{% if ticket.ticketupdate_set.all %}
<p class="text-secondosiblue">{{ticket.ticketupdate_set.all.last.date_added}} <br> by {{ticket.ticketupdate_set.all.last.added_by.first_name}}</p>
{% endif %}
</td>
<td class="px-6 py-4 text-center text-sm">

@ -367,56 +367,7 @@ def my_tasks(request, *args, **kwargs):
@staff_login_required
def tickets(request, *args, **kwargs):
if request.user.is_superuser:
all_tickets = Ticket.objects.all()
all_tickets_with_update_date = all_tickets.annotate(
latest_update_date=Max('ticketupdate__date_added'))
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
open_tickets = []
closed_tickets = []
for ticket in all_tickets_ordered:
last_status = ticket.ticketstatus_set.last()
if last_status:
last_status = last_status.status
if last_status == 'Closed':
closed_tickets.append(ticket)
else:
open_tickets.append(ticket)
else:
# If no status is found, assume it's open
open_tickets.append(ticket)
else:
all_tickets = Ticket.objects.all()
all_tickets_with_update_date = all_tickets.annotate(
latest_update_date=Max('ticketupdate__date_added'))
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
open_tickets = []
closed_tickets = []
for ticket in all_tickets_ordered:
last_status = ticket.ticketstatus_set.last()
if last_status:
last_status = last_status.status
if last_status == 'Closed':
closed_tickets.append(ticket)
else:
open_tickets.append(ticket)
else:
# If no status is found, assume it's open
open_tickets.append(ticket)
for ticket in open_tickets:
unread_updates_count = 0
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
context = {
'open_tickets': open_tickets,
'closed_tickets': closed_tickets
}
return render(request, 'listing_pages/tickets.html', context)

@ -916,6 +916,14 @@ video {
margin-right: auto;
}
.-ml-10 {
margin-left: -2.5rem;
}
.-ml-5 {
margin-left: -1.25rem;
}
.-mr-3 {
margin-right: -0.75rem;
}
@ -960,6 +968,10 @@ video {
margin-left: 0px;
}
.ml-10 {
margin-left: 2.5rem;
}
.ml-2 {
margin-left: 0.5rem;
}
@ -968,6 +980,10 @@ video {
margin-left: 1rem;
}
.ml-5 {
margin-left: 1.25rem;
}
.ml-\[300px\] {
margin-left: 300px;
}
@ -1081,22 +1097,6 @@ video {
margin-top: 80px;
}
.ml-5 {
margin-left: 1.25rem;
}
.ml-10 {
margin-left: 2.5rem;
}
.-ml-10 {
margin-left: -2.5rem;
}
.-ml-5 {
margin-left: -1.25rem;
}
.block {
display: block;
}
@ -1221,6 +1221,10 @@ video {
height: 16px;
}
.h-\[180px\] {
height: 180px;
}
.h-\[18px\] {
height: 18px;
}
@ -1560,14 +1564,6 @@ video {
width: 100%;
}
.min-w-\[250px\] {
min-width: 250px;
}
.min-w-\[300px\] {
min-width: 300px;
}
.min-w-full {
min-width: 100%;
}
@ -1584,14 +1580,6 @@ video {
max-width: 72rem;
}
.max-w-\[250px\] {
max-width: 250px;
}
.max-w-\[300px\] {
max-width: 300px;
}
.max-w-lg {
max-width: 32rem;
}
@ -3076,6 +3064,11 @@ video {
color: rgb(156 163 175 / var(--tw-text-opacity));
}
.text-gray-50 {
--tw-text-opacity: 1;
color: rgb(249 250 251 / var(--tw-text-opacity));
}
.text-gray-500 {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity));
@ -3171,11 +3164,6 @@ video {
color: rgb(234 179 8 / var(--tw-text-opacity));
}
.text-gray-50 {
--tw-text-opacity: 1;
color: rgb(249 250 251 / var(--tw-text-opacity));
}
.underline {
text-decoration-line: underline;
}

@ -120,10 +120,10 @@ function initializeWebSocket() {
});
} else if (data.event_type === 'user_status') {
const onlineUsersDiv = document.getElementById('online-users');
if (onlineUsersDiv) {
onlineUsersDiv.innerHTML = data.html;
}
const toponlineUsersDiv = document.getElementById('top-online-users');
const fixedonlineUsersDiv = document.getElementById('fixed-online-users');
toponlineUsersDiv.innerHTML = data.html;
fixedonlineUsersDiv.innerHTML = data.html;
} else {
messagesDiv.insertAdjacentHTML('beforeend', data.html);
typingDiv.innerHTML = '';

@ -3,13 +3,25 @@
from django.shortcuts import render, get_object_or_404
from support.models import *
from osinacore.decorators import *
def add_ticket_department_modal(request):
context = {
from django.http import HttpResponse
def add_ticket_department_modal(request, ticket_number):
ticket = get_object_or_404(Ticket, ticket_number=ticket_number)
departments = Department.objects.all().order_by('-id')
if request.method == 'POST':
department = get_object_or_404(Department, id=request.POST.get('department'))
ticketdepartment = TicketDepartment(
department=department,
ticket=ticket,
date_added = request.POST.get('date')
)
ticketdepartment.save()
return HttpResponse('<script>window.top.location.reload();</script>')
context = {
'ticket': ticket,
'departments': departments,
}
return render(request, 'add_templates/add-ticket-department-modal.html', context)
@ -17,10 +29,22 @@ def add_ticket_department_modal(request):
def add_ticket_member_modal(request):
context = {
def add_ticket_member_modal(request, ticket_number):
ticket = get_object_or_404(Ticket, ticket_number=ticket_number)
staffprofiles = StaffProfile.objects.filter(active=True).all()
if request.method == 'POST':
staff = get_object_or_404(StaffProfile, id=request.POST.get('staff'))
ticketstaff = TicketStaff(
staff=staff,
ticket=ticket,
date_added = request.POST.get('date')
)
ticketstaff.save()
return HttpResponse('<script>window.top.location.reload();</script>')
context = {
'ticket': ticket,
'staffprofiles': staffprofiles,
}
return render(request, 'add_templates/add-ticket-member-modal.html', context)

@ -129,14 +129,15 @@ class Ticket(models.Model):
return f"last seen on {last_seen_time.strftime('%b %d at %I:%M %p')}"
def get_all_ticket_staff(self):
ticket_staff = TicketStaff.objects.filter(ticket=self).select_related('staff')
ticket_staff = TicketStaff.objects.filter(ticket=self)
staff_members = [entry.staff for entry in ticket_staff]
latest_department = TicketDepartment.objects.filter(ticket=self).order_by('-date_added').first()
if latest_department:
department_staff = latest_department.department.get_staff()
else:
department_staff = []
all_staff = list(ticket_staff.values_list('staff', flat=True)) + list(department_staff)
all_staff = list(staff_members) + list(department_staff)
return all_staff

@ -14,16 +14,19 @@
</head>
<body class="font-poppinsLight">
<form method="POST" action="">
<form method="POST" action="{% url 'addticketdepartmentmodal' ticket.ticket_number %}">
{% csrf_token %}
<h1 class="text-secondosiblue text-2xl font-semibold text-center">Add New Department</h1>
<select name="department" id="" class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-4">
<option value="">Dep 1</option>
<select name="department" class="w-full h-[50px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-4">
<option value="" disabled selected>Select Department</option>
{% for department in departments %}
<option value="{{department.id}}">{{department.name}}</option>
{% endfor %}
</select>
<div class="w-full">
<input required name="date" type="date" id="date" name="date"
<input required name="date" type="datetime-local" id="date" name="date"
class="w-full p-3 border border-gray-300 rounded-md bg-transparent outline-none mt-1">
</div>

@ -14,14 +14,23 @@
</head>
<body class="font-poppinsLight">
<form method="POST" action="">
<form method="POST" action="{% url 'addticketmembermodal' ticket.ticket_number %}">
{% csrf_token %}
<h1 class="text-secondosiblue text-2xl font-semibold text-center">Add New Member</h1>
<select name="member" id="" class="w-full h-[100px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-4" multiple>
<option value="">Member 1</option>
<select name="staff" class="w-full h-[150px] py-1 px-3 border border-gray-300 outline-none rounded-md mt-4" multiple>
<option value="" selected disabled>Select Staff</option>
{% for staff in staffprofiles %}
<option value="{{staff.id}}">{{staff.user.first_name}} {{staff.user.last_name}}</option>
{% endfor %}
</select>
<div class="w-full">
<input required name="date" type="datetime-local" id="date" name="date"
class="w-full p-3 border border-gray-300 rounded-md bg-transparent outline-none mt-1">
</div>
<div class="w-full flex justify-center items-center mt-4">
<button type="submit"

@ -22,7 +22,7 @@
<div class="w-full flex flex-col md:flex-row justify-between items-start md:items-center gap-3 mb-5 md:mb-0">
<p class="text-secondosiblue text-[20px] flex items-center gap-1">Ticket <span
class="font-semibold">#{{ticket.ticket_number}}</span> - <span
class="font-semibold text-base">Department</span></p>
class="font-semibold text-base">{{ticket.ticketdepartment_set.all.last.department}}</span></p>
<div class="w-full s:w-fit flex flex-col s:flex-row justify-end items-center gap-2">
@ -81,12 +81,21 @@
</div>
{% endif %}
<div class="w-full mt-3">
<div class="w-full">
<p class="text-gray-500 font-light text-sm leading-7">{{ticket.description}}
</p>
</div>
<div class="w-full flex items-center gap-1">
<p class="text-secondosiblue">Online:</p>
<div class="flex items-center" id="top-online-users">
{% include 'details_templates/partials/ticket-online-users.html' %}
</div>
</div>
{% if ticket.ticketattachment_set.all %}
<div class="w-full flex flex-wrap justify-end items-center gap-3">
{% for file in ticket.ticketattachment_set.all %}
@ -110,7 +119,7 @@
<div class="w-full flex flex-col md:flex-row justify-between items-start md:items-center gap-3">
<p class="text-secondosiblue text-[17px] flex items-center gap-1">Ticket <span
class="font-semibold">#{{ticket.ticket_number}}</span> - <span
class="font-semibold text-base">Department</span>
class="font-semibold text-base">{{ticket.ticketdepartment_set.all.last.department}}</span>
</p>
{% if last_ticket_status.status == 'Open' %}
@ -139,7 +148,7 @@
<p class="text-secondosiblue">Online:</p>
<div class="flex items-center" id="online-users">
<div class="flex items-center" id="fixed-online-users">
{% include 'details_templates/partials/ticket-online-users.html' %}
</div>

@ -18,7 +18,7 @@
<button
class="h-full rounded-tr-md px-4 bg-secondosiblue text-gray-200 text-[18px] outline-none border-none cursor-pointer flex justify-center items-center xsmallPopupButton"
data-modal-url="{% url 'addticketdepartmentmodal' %}">
data-modal-url="{% url 'addticketdepartmentmodal' ticket.ticket_number %}">
<i class="fa fa-plus"></i>
</button>
</div>
@ -27,7 +27,7 @@
<div class="w-full flex flex-col gap-3 mt-3">
{% for department in ticket_departments %}
<div
class="w-full rounded-md py-5 px-3 {% if forloop.first %} bg-secondosiblue border border-secondosiblue {% else %} bg-gray-50 border border-gray-100 {% endif %} flex justify-between items-center gap-3 text-gray-50">
class="w-full rounded-md py-5 px-3 {% if forloop.first %} bg-secondosiblue border border-secondosiblue text-gray-50 {% else %} bg-gray-50 border border-gray-100 text-secondosiblue {% endif %} flex justify-between items-center gap-3">
<p class="text-sm sm:text-[17px]">{{department.department.name}}</p>
<p class="text-sm sm:text-base">{{department.date_added}}</p>
@ -45,8 +45,8 @@
</div>
<button
class="h-full rounded-tr-md px-4 bg-secondosiblue text-gray-200 text-[18px] outline-none border-none cursor-pointer flex justify-center items-center xsmallPopupButton"
data-modal-url="{% url 'addticketmembermodal' %}">
class="h-full rounded-tr-md px-4 bg-secondosiblue text-gray-200 text-[18px] outline-none border-none cursor-pointer flex justify-center items-center smallPopupButton"
data-modal-url="{% url 'addticketmembermodal' ticket.ticket_number %}">
<i class="fa fa-plus"></i>
</button>
</div>

@ -7,7 +7,6 @@ from django.http import Http404
# Create your views here.
def ticket_room(request, ticket_number):
ticket = get_object_or_404(Ticket, ticket_number=ticket_number)
print(ticket.get_all_ticket_staff())
if request.user.is_superuser:
base_template = "main.html"
elif hasattr(request.user, 'customerprofile') and request.user.customerprofile == ticket.customer:

Loading…
Cancel
Save