You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
18 KiB
HTML

{% extends "main.html" %}
{%load static%}
{% block content %}
<!-- LEFT SIDE -->
<div class="w-full xxlg1:w-[75%] flex flex-col items-center 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 -->
<div class="w-full h-fit bg-white p-3 rounded-md shadow-md {% if not open_tickets %} hidden {% endif %}" id="tickets-div">
<div class="overflow-x-auto border border-gray-300 rounded-md tableContainer" 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 uppercase whitespace-nowrap">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200" id="tickets">
{% for ticket in open_tickets %}
{% include 'details_templates/partials/staff-ticket-display.html' %}
{% endfor %}
</tbody>
</table>
</div>
</div>
{% if tasks %}
<!-- TASKS ON DESKTOP -->
<div class="w-full hidden md:flex flex-col gap-5">
<!-- TASKS TABLE -->
{% for task in tasks %}
<div class="w-full h-fit bg-white p-3 rounded-md shadow-md">
<div class="w-full bg-white h-fit rounded-md border border-gray-200">
<!-- TABLE HEADER -->
<div class="w-full h-[70px] rounded-t-md grid grid-cols-2">
<a href="{% url 'detailed-task' task.task_id %}" class="h-[70px]">
<div
class="h-full flex justify-center items-center border-r border-b border-gray-200 px-3 {% if task.status == 'Open' %}bg-secondosiblue{% endif %} {% if task.status == 'Working On' %}bg-yellow-500{% endif %} {% if task.status == 'Closed' %}bg-green-700{% endif %} rounded-tl-md text-[17px] text-white text-center bg-opacity-70 hover:bg-opacity-100 duration-300">
<p>{{task.name}}</p>
</div>
</a>
<div class="grid grid-cols-3">
<div
class="flex justify-center items-center border-r border-b border-gray-200 text-white {% if task.status == 'Open' %}bg-secondosiblue{% endif %} {% if task.status == 'Working On' %}bg-yellow-500{% endif %} {% if task.status == 'Closed' %}bg-green-700{% endif %} bg-opacity-70">
<p>{{task.status}}</p>
</div>
<div
class="flex justify-center items-center border-r border-b border-gray-200 text-white {% if task.status == 'Open' %}bg-secondosiblue{% endif %} {% if task.status == 'Working On' %}bg-yellow-500{% endif %} {% if task.status == 'Closed' %}bg-green-700{% endif %} bg-opacity-70">
<p>{{task.start_date|date:"d-m-Y"}}</p>
</div>
<div
class="flex justify-center items-center border-r border-b border-gray-200 text-white {% if task.status == 'Open' %}bg-secondosiblue{% endif %} {% if task.status == 'Working On' %}bg-yellow-500{% endif %} {% if task.status == 'Closed' %}bg-green-700{% endif %} rounded-tr-md bg-opacity-70">
<p>{{task.end_date|date:"d-m-Y"}}</p>
</div>
</div>
</div>
<!-- TABLE BODY -->
<div class="w-full h-fit grid grid-cols-2">
<!-- LEFT SIDE OF TABLE BODY -->
<div class="h-fit bg-white p-3 rounded-bl-md">
<!-- 1st row -->
<div class="w-full flex flex-col gap-2">
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Project:</p>
<p class="text-secondosiblue text-base">{{task.project.name}}</p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Epic:</p>
<p class="text-secondosiblue text-base">{{task.epic.title}}</p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Assigned To:</p>
<p class="text-secondosiblue text-base">{{task.assigned_to.user.first_name}}
{{task.assigned_to.user.last_name}}</p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Files:</p>
<p class="text-secondosiblue text-base"></p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Tags:</p>
<p class="text-secondosiblue text-base"></p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Extra:</p>
<p class="text-secondosiblue text-base">{{task.extra}}</p>
</div>
</div>
</div>
<!-- RIGHT SIDE OF TABLE BODY -->
<div class="h-fit bg-white grid grid-cols-3 rounded-br-md">
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500">Close</button>
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 updateStatusButton"
data-modal-url="{% url 'edittaskstatusmodal' task.task_id %}">Update
Status</button>
<button class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 ">Add
Time</button>
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 deleteTaskButton"
data-modal-url="{% url 'deletetaskmodal' task.id %}">Delete</button>
<a href="{% url 'edittask' task.task_id %}">
<button
class="w-full p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500">Edit</button>
</a>
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 showPointsButton"
data-modal-url="{% url 'showpoints' task.task_id %}">Show
Points</button>
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 addPointButton"
data-modal-url="{% url 'addpointmodal' task.task_id %}">Add
Point</button>
<a href="{% url 'detailed-task' task.task_id %}">
<button
class="w-full p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500">Details</button>
</a>
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 rounded-br-md timelineButton"
data-modal-url="{% url 'timeline' task.task_id %}">Timeline</button>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<!-- TASKS ON MOBILE -->
<div class="w-full flex flex-col gap-5 md:hidden">
{% for task in tasks %}
<div class="w-full h-fit bg-white p-3 rounded-md shadow-md">
<div class="border border-gray-200 rounded-t-md">
<div class="w-full rounded-t-md">
<a href="{% url 'detailed-task' task.task_id %}">
<div
class="text-white {% if task.status == 'Open' %}bg-secondosiblue{% endif %} {% if task.status == 'Working On' %}bg-yellow-500{% endif %} {% if task.status == 'Closed' %}bg-green-700{% endif %} border-r border-gray-200 rounded-t-md flex justify-center items-center text-center py-3 text-sm bg-opacity-70 hover:bg-opacity-100 duration-300">
<p>{{task.name}}</p>
</div>
</a>
</div>
<div class="grid grid-cols-3 border-t border-gray-200">
<div
class="text-white {% if task.status == 'Open' %} bg-secondosiblue {% endif %} {% if task.status == 'Working On' %} bg-yellow-500 {% endif %} {% if task.status == 'Closed' %} bg-green-700{% endif %} border-r border-gray-200 flex justify-center items-center text-center py-3 text-sm bg-opacity-70">
<p>{{task.status}}</p>
</div>
<div
class="text-white {% if task.status == 'Open' %} bg-secondosiblue {% endif %} {% if task.status == 'Working On' %} bg-yellow-500 {% endif %} {% if task.status == 'Closed' %} bg-green-700{% endif %} border-r border-gray-200 flex justify-center items-center text-center py-3 text-sm bg-opacity-70">
<p>{{task.start_date|date:"d-m-Y"}}</p>
</div>
<div
class="text-white {% if task.status == 'Open' %} bg-secondosiblue {% endif %} {% if task.status == 'Working On' %} bg-yellow-500 {% endif %} {% if task.status == 'Closed' %} bg-green-700{% endif %} border-r border-gray-200 flex justify-center items-center text-center py-3 text-sm bg-opacity-70">
<p>{{task.end_date|date:"d-m-Y"}}</p>
</div>
</div>
<div class="w-full flex flex-col gap-2 p-3">
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Project:</p>
<p class="text-secondosiblue text-base">{{task.project.name}}</p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Epic:</p>
<p class="text-secondosiblue text-base">{{task.epic.title}}</p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Assigned To:</p>
<p class="text-secondosiblue text-base">{{task.assigned_to.user.first_name}}
{{task.assigned_to.user.last_name}}</p>
</div>
<div class="flex justify-start items-center gap-2">
<p class="text-gray-400 text-base">Extra:</p>
<p class="text-secondosiblue text-base">{{task.extra}}</p>
</div>
</div>
<div
class="w-full bg-gray-100 flex justify-between items-center py-3 px-3 text-secondosiblue actionsButton">
<p>Actions</p>
<i class="fa fa-angle-down" style="font-size: 20px;"></i>
<i class="fa fa-angle-up" style="font-size: 20px; display: none;"></i>
</div>
<div class="grid-cols-3 actionsContainer hidden">
<button class="p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500">Close</button>
<button
class="p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500 updateStatusButton"
data-modal-url="{% url 'edittaskstatusmodal' task.task_id %}">Update
Status</button>
<button class="p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500">Add
Time</button>
<button
class="p-2 border border-gray-200 text-base h-[70px] bg-gray-100 text-gray-500 deleteTaskButton"
data-modal-url="{% url 'deletetaskmodal' task.id %}">Delete</button>
<a href="{% url 'edittask' task.task_id %}">
<button
class="w-full p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500">Edit</button>
</a>
<button
class="p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500 showPointsButton"
data-modal-url="{% url 'showpoints' task.task_id %}">Show
Points</button>
<button class="p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500 addPointButton"
data-modal-url="{% url 'addpointmodal' task.task_id %}">Add
Point</button>
<a href="{% url 'detailed-task' task.task_id %}">
<button
class="w-full p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500">Details</button>
</a>
<button class="p-2 border border-gray-200 text-sm h-[70px] bg-gray-100 text-gray-500 timelineButton"
data-modal-url="{% url 'timeline' task.task_id %}">Timeline</button>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div
class="w-full h-fit bg-white p-5 rounded-md shadow-md mb-5 flex flex-col justify-center items-center text-secondosiblue text-center text-xl font-poppinsBold">
<p>No Available Tasks</p>
</div>
{% endif %}
</div>
<!---------------------- 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>
<script>
// WebSocket connection for new tickets
const ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
const newTicketsSocketUrl = `${ws_scheme}://${window.location.host}/ws/new-tickets/`;
const newTicketsSocket = new WebSocket(newTicketsSocketUrl);
newTicketsSocket.onopen = () => {
console.log('WebSocket connection to new tickets established');
};
newTicketsSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
if (data.event_type === 'new_ticket') {
const ticketsDiv = document.getElementById('tickets-div');
if (ticketsDiv.classList.contains('hidden')) {
ticketsDiv.classList.remove('hidden');
}
const html = data.html;
document.getElementById('tickets').insertAdjacentHTML('afterbegin', html);
}
};
newTicketsSocket.onclose = () => {
console.log('WebSocket connection to new tickets closed');
};
newTicketsSocket.onerror = (error) => {
console.log('WebSocket error:', error);
};
// WebSocket connection for new ticket updates
const newTicketUpdatesSocketUrl = `${ws_scheme}://${window.location.host}/ws/new-tickets/`;
const newTicketUpdatesSocket = new WebSocket(newTicketsSocketUrl);
newTicketUpdatesSocket.onopen = () => {
console.log('WebSocket connection to new ticket updates established');
};
newTicketUpdatesSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
if (data.event_type === 'new_ticket_update_group') {
const ticketsDiv = document.getElementById('tickets-div');
if (ticketsDiv.classList.contains('hidden')) {
ticketsDiv.classList.remove('hidden');
}
const html = data.html;
const ticketId = data.ticket_id;
// Remove the existing ticket row if it exists
const existingTicketRows = document.querySelectorAll(`.ticket-${ticketId}`);
existingTicketRows.forEach(row => row.remove());
// Insert the updated ticket row at the top
document.getElementById('tickets').insertAdjacentHTML('afterbegin', html);
}
};
newTicketUpdatesSocket.onclose = () => {
console.log('WebSocket connection to new ticket updates closed');
};
newTicketUpdatesSocket.onerror = (error) => {
console.log('WebSocket error:', error);
};
</script>
{% endblock content %}