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
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 %} |