Ticket JavaScript rewrite

This commit is contained in:
Corban-Lee Jones 2024-01-18 20:00:46 +00:00
parent 24a65014b9
commit 506ed5e338
4 changed files with 620 additions and 314 deletions

View File

@ -99,4 +99,18 @@ body {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
/* Ticket Content */
.ticket-content .ticket-content-icon {
border-radius: 50%;
width: 3rem;
height: 3rem;
object-fit: cover;
}
.ticket-content .ticket-content.author {
margin-bottom: 5px;
}

373
apps/static/js/_tickets.js Normal file
View File

@ -0,0 +1,373 @@
var displayedTicketID = -1;
filters = {"ordering": "-edit_timestamp", "page_size": 100};
editor = null;
searchTimeout = null;
loadingTickets = false;
const formControls = [
{
id: "newTitle",
validation: function(element) {
const value = element.val();
return (!element.attr("required") || value.trim() !== "")
},
errorMessage: function(element) {
return "This field is required."
}
}
];
$(document).ready(function() {
ClassicEditor
.create( document.getElementById("newDesc"), {})
.then( newEditor => {
editor = newEditor;
})
.catch( error => {
console.error(error)
});
$("#searchTickets").keyup(() => {
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").show();
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
console.debug("searching");
value = $("#searchTickets").val();
if (value === "") {
console.debug("deleted search filters");
delete filters["search"];
}
else {
console.debug("updated search filters");
filters["search"] = value;
}
loadAllTickets();
}, 500);
})
setupFilter("#filterSidebar .filter-department", "author__department");
setupFilter("#filterSidebar .filter-tags", "tags");
setupFilter("#filterSidebar .filter-priority", "priority");
loadFilterCounts();
loadAllTickets();
$(".select2-selection__choice").each(function() {
// Work out how to apply the colours of the tags to the selection choices.
})
});
function setupFilter(selector, key) {
$(selector).each(function () {
var input = $(this).find("input[type=checkbox], input[type=radio]");
var uuid = input.val();
input.on("change", function () {
if (input.is(":checkbox")) {
if ($(this).is(":checked")) {
filters[key] = filters[key] || [];
filters[key].push(uuid);
}
else {
filters[key] = filters[key].filter(id => id !== uuid);
if (filters[key].length === 0) {
delete filters[key];
}
}
}
else if (input.is(":radio") && input.is(":checked")) {
if (uuid === "all") {
delete filters[key];
}
else {
filters[key] = [uuid];
}
}
console.debug(`Filter applied '${key}' as '${uuid}'`)
loadAllTickets();
});
});
}
function validateForm() {
$("#ticketModal form").find(".form-control,.form-select").removeClass("is-valid is-invalid");
$("#ticketModal form .invalid-feedback").text("");
var valid = true;
formControls.forEach(function(control) {
var element = $("#" + control.id);
if (!control.validation(element)) {
element.addClass("is-invalid");
element.siblings(".invalid-feedback").text(control.errorMessage(element));
valid = false;
}
else {
element.addClass("is-valid");
}
});
return valid;
}
$("#ticketModal form").on("submit", function(event) {
event.preventDefault();
if (!validateForm()) {
return;
}
$.ajax({
url: URL_NewTicket,
type: "POST",
dataType: "json",
data: {
csrfmiddlewaretoken: CSRFMiddlewareToken,
title: $("#newTitle").val(),
description: editor.getData(),
author_id: CurrentUserID,
priority_id: $("#newPriority").val(),
tag_ids: $("#newTags").val()
},
success: function(data) {
loadAllTickets();
loadFilterCounts();
},
error: function(data) {
alert(JSON.stringify(data, null, 4))
}
});
});
function getOrdinalSuffix(day) {
if (day >= 11 && day <= 13) {
return day + 'th';
} else {
switch (day % 10) {
case 1: return day + 'st';
case 2: return day + 'nd';
case 3: return day + 'rd';
default: return day + 'th';
}
}
}
function updateFilterCounts(filterType, data) {
$("#filterSidebar .filter-" + filterType).each(function() {
var uuid = $(this).find("input[type=checkbox],input[type=radio]").val();
var count = data[filterType][uuid];
$(this).find(".badge").text(count);
});
}
function loadFilterCounts() {
$.ajax({
url: URL_FilterCounts,
type: "GET",
success: function(data) {
updateFilterCounts('priority', data);
updateFilterCounts('tags', data);
updateFilterCounts('department', data);
$("#filterPriorityAll .badge").text(data.tickets);
$("#filterDepartmentAll .badge").text(data.tickets)
$("#ticketCounts .total").text(data.tickets)
},
error: function(data) {
console.error(JSON.stringify(data, null, 4))
}
});
}
function timestampToHumanDate(timestamp, wasYesterday) {
if (wasYesterday) {
var day = getOrdinalSuffix(timestamp.getDate());
var month = timestamp.toLocaleString('en-GB', { month: 'short' });
var year = timestamp.toLocaleString('en-GB', { year: 'numeric' });
var time = timestamp.toLocaleString('en-GB', { hour: 'numeric', minute: 'numeric' });
return time + ', ' + day + ' ' + month + ' ' + year;
}
var hours = timestamp.getUTCHours();
var minutes = timestamp.getUTCMinutes();
return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0');
}
function loadAllTickets() {
if (loadingTickets === true) {
return;
}
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").show();
loadingTickets = true;
// alert(JSON.stringify(filters, null, 4));
$.ajax({
url: URL_Tickets,
type: "GET",
dataType: "json",
data: $.param(filters, true),
success: function(data) {
loadingTickets = false;
// console.log(JSON.stringify(data, null, 4))
$("#ticketCounts .current").text(data.results.length);
$("#ticketsContainer .loading").hide();
if (data.results.length === 0) $("#ticketsContainer .none-found").show();
else $("#ticketsContainer .none-found").hide();
data.results.forEach(function(ticket) {
var timestamp = new Date(ticket.timestamp);
var formattedTime = timestampToHumanDate(timestamp, ticket.was_yesterday);
if (ticket.is_edited) {
formattedTime += " • edited";
}
var template = $($("#ticketItemTemplate").html());
template.find(".ticket-item-author").text(`${ticket.author.forename} ${ticket.author.surname}`);
template.find(".ticket-item-datetime").text(formattedTime);
template.find(".ticket-item-title").text(ticket.title);
template.find(".ticket-item-desc").text(ticket.description);
template.find(".ticket-item-icon").attr("src", ticket.author.icon);
template.attr("data-uuid", ticket.uuid);
$("#ticketsContainer .content").append(template);
});
applyTicketClickFunction();
},
error: function(data) {
loadingTickets = false;
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").hide();
if (data.status === 429) {
alert(`HTTP ${data.status} - ${data.statusText}\n${data.responseJSON.detail}`)
}
}
});
}
function applyTicketClickFunction() {
$(".ticket-item").on("click", function(e) {
e.preventDefault();
displayTicket(this);
$('.email-app').removeClass('side-active');
$('.email-content').toggleClass('open');
});
}
function reloadCurrentTicket() {
displayTicket($(".ticket-item.bgc-grey-100"));
}
function changeTicket(next=true) {
var selectedTicket = $(".ticket-item.bgc-grey-100");
if (!selectedTicket.length) {
displayTicket($(".ticket-item").first());
return;
}
if (next) {
displayTicket(selectedTicket.next());
}
else {
displayTicket(selectedTicket.prev());
}
if (!$('.email-content').hasClass('open')) {
$('.email-content').addClass('open');
}
}
function displayTicket(ticketElement) {
ticket = $(ticketElement);
ticketID = ticket.data("uuid");
// $(".back-to-mailbox").off("click").on("click", function(event) {
// event.preventDefault();
// $('.email-content').toggleClass('open');
// displayTicket(ticketElement);
// });
if (displayedTicketID === ticketID) {
// displayedTicketID = -1;
return;
}
ticket.siblings().removeClass("bgc-grey-100");
ticket.addClass("bgc-grey-100");
$("#ticketTitle").text("")
$("#ticketDesc").empty();
$("#ticketAuthor").text("");
$("#ticketAuthorImg").hide();
$("#ticketAuthorImg").prop("src", "");
$("#ticketTimestamp").text("");
$("#btnGroupDrop2").hide();
$("#ticketBadges").empty().hide();
displayedTicketID = ticketID;
$.ajax({
url: URL_Tickets,
type: 'get',
dataType: 'json',
data: $.param({uuid: ticketID}, true),
success: function (data) {
console.log(JSON.stringify(data, null, 4));
var ticket = data.results[0];
var author = ticket.author;
var department = author.department;
var priority = ticket.priority;
$("#ticketTitle").text(ticket.title);
$("#ticketDesc").append($(`<div class="w-100">${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="color: ${priority.colour}; background-color: ${priority.backgroundcolour};">${priority.title} Priority <i class="ti-control-record "></i></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="color: ${tag.colour}; background-color: ${tag.backgroundcolour};">${tag.title} <i class="ti-tag"></i></div>`));
});
// timestamp
var timestamp = new Date(ticket.timestamp);
var formattedTime = timestampToHumanDate(timestamp, ticket.was_yesterday);
if (ticket.is_edited) {
formattedTime += " • edited";
}
$("#ticketTimestamp").text(formattedTime);
},
error: function(message) {
alert(JSON.stringify(message, null, 4));
}
});
}

View File

@ -1,36 +1,44 @@
var displayedTicketID = -1;
filters = {"ordering": "-edit_timestamp", "page_size": 100};
editor = null;
var filters = {"order": "-edit_timestamp"};
global_loadingTickets = false;
searchTimeout = null;
loadingTickets = false;
const formControls = [
{
id: "newTitle",
validation: function(element) {
const value = element.val();
return (!element.attr("required") || value.trim() !== "")
},
errorMessage: function(element) {
return "This field is required."
}
}
];
pagination = {};
$(document).ready(function() {
ClassicEditor
.create( document.getElementById("newDesc"), {})
.then( newEditor => {
editor = newEditor;
})
.catch( error => {
console.error(error)
});
initSearchBar();
setupFilter("#filterSidebar .filter-department", "author__department");
setupFilter("#filterSidebar .filter-tags", "tags");
setupFilter("#filterSidebar .filter-priority", "priority");
loadFilterCounts();
loadTicketItems();
});
function updateInterfaceState(state) {
console.debug(`updating interface state to '${state}'`);
switch (state) {
case "content":
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").hide();
break;
case "loading":
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").show();
break;
case "no-content":
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").show();
$("#ticketsContainer .loading").hide();
break;
default:
throw new Error(`Invalid Interface State '${state}'`);
}
}
function initSearchBar() {
$("#searchTickets").keyup(() => {
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").show();
updateInterfaceState("loading");
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
console.debug("searching");
@ -44,21 +52,10 @@ $(document).ready(function() {
filters["search"] = value;
}
loadAllTickets();
loadTicketItems();
}, 500);
})
setupFilter("#filterSidebar .filter-department", "author__department");
setupFilter("#filterSidebar .filter-tags", "tags");
setupFilter("#filterSidebar .filter-priority", "priority");
loadFilterCounts();
loadAllTickets();
$(".select2-selection__choice").each(function() {
// Work out how to apply the colours of the tags to the selection choices.
})
});
}
function setupFilter(selector, key) {
$(selector).each(function () {
@ -66,86 +63,27 @@ function setupFilter(selector, key) {
var uuid = input.val();
input.on("change", function () {
if (input.is(":checkbox")) {
if ($(this).is(":checked")) {
filters[key] = filters[key] || [];
filters[key].push(uuid);
}
else {
filters[key] = filters[key].filter(id => id !== uuid);
if (filters[key].length === 0) {
delete filters[key];
}
if (filters[key].length === 0) delete filters[key];
}
}
else if (input.is(":radio") && input.is(":checked")) {
if (uuid === "all") {
delete filters[key];
}
else {
filters[key] = [uuid];
}
if (uuid === "all") delete filters[key];
else filters[key] = [uuid];
}
console.debug(`Filter applied '${key}' as '${uuid}'`)
loadAllTickets();
loadTicketItems();
});
});
}
function validateForm() {
$("#ticketModal form").find(".form-control,.form-select").removeClass("is-valid is-invalid");
$("#ticketModal form .invalid-feedback").text("");
var valid = true;
formControls.forEach(function(control) {
var element = $("#" + control.id);
if (!control.validation(element)) {
element.addClass("is-invalid");
element.siblings(".invalid-feedback").text(control.errorMessage(element));
valid = false;
}
else {
element.addClass("is-valid");
}
});
return valid;
}
$("#ticketModal form").on("submit", function(event) {
event.preventDefault();
if (!validateForm()) {
return;
}
$.ajax({
url: URL_NewTicket,
type: "POST",
dataType: "json",
data: {
csrfmiddlewaretoken: CSRFMiddlewareToken,
title: $("#newTitle").val(),
description: editor.getData(),
author_id: CurrentUserID,
priority_id: $("#newPriority").val(),
tag_ids: $("#newTags").val()
},
success: function(data) {
loadAllTickets();
loadFilterCounts();
},
error: function(data) {
alert(JSON.stringify(data, null, 4))
}
});
});
function getOrdinalSuffix(day) {
if (day >= 11 && day <= 13) {
return day + 'th';
@ -159,6 +97,20 @@ function getOrdinalSuffix(day) {
}
}
function timestampToHumanDate(timestamp, wasYesterday) {
if (wasYesterday) {
var day = getOrdinalSuffix(timestamp.getDate());
var month = timestamp.toLocaleString('en-GB', { month: 'short' });
var year = timestamp.toLocaleString('en-GB', { year: 'numeric' });
var time = timestamp.toLocaleString('en-GB', { hour: 'numeric', minute: 'numeric' });
return time + ', ' + day + ' ' + month + ' ' + year;
}
var hours = timestamp.getUTCHours();
var minutes = timestamp.getUTCMinutes();
return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0');
}
function updateFilterCounts(filterType, data) {
$("#filterSidebar .filter-" + filterType).each(function() {
var uuid = $(this).find("input[type=checkbox],input[type=radio]").val();
@ -178,7 +130,7 @@ function loadFilterCounts() {
$("#filterPriorityAll .badge").text(data.tickets);
$("#filterDepartmentAll .badge").text(data.tickets)
$("#ticketCounts .total").text(data.tickets)
// $("#ticketCounts .total").text(data.tickets)
},
error: function(data) {
console.error(JSON.stringify(data, null, 4))
@ -186,107 +138,36 @@ function loadFilterCounts() {
});
}
function timestampToHumanDate(timestamp, wasYesterday) {
if (wasYesterday) {
var day = getOrdinalSuffix(timestamp.getDate());
var month = timestamp.toLocaleString('en-GB', { month: 'short' });
var year = timestamp.toLocaleString('en-GB', { year: 'numeric' });
var time = timestamp.toLocaleString('en-GB', { hour: 'numeric', minute: 'numeric' });
return time + ', ' + day + ' ' + month + ' ' + year;
}
var hours = timestamp.getUTCHours();
var minutes = timestamp.getUTCMinutes();
return hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0');
}
function loadAllTickets() {
if (loadingTickets === true) {
return;
}
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").show();
loadingTickets = true;
// alert(JSON.stringify(filters, null, 4));
$.ajax({
url: URL_Tickets,
type: "GET",
dataType: "json",
data: $.param(filters, true),
success: function(data) {
loadingTickets = false;
// console.log(JSON.stringify(data, null, 4))
$("#ticketCounts .current").text(data.results.length);
$("#ticketsContainer .loading").hide();
if (data.results.length === 0) $("#ticketsContainer .none-found").show();
else $("#ticketsContainer .none-found").hide();
data.results.forEach(function(ticket) {
var timestamp = new Date(ticket.timestamp);
var formattedTime = timestampToHumanDate(timestamp, ticket.was_yesterday);
if (ticket.is_edited) {
formattedTime += " • edited";
}
var template = $($("#ticketItemTemplate").html());
template.find(".ticket-item-author").text(`${ticket.author.forename} ${ticket.author.surname}`);
template.find(".ticket-item-datetime").text(formattedTime);
template.find(".ticket-item-title").text(ticket.title);
template.find(".ticket-item-desc").text(ticket.description);
template.find(".ticket-item-icon").attr("src", ticket.author.icon);
template.attr("data-uuid", ticket.uuid);
$("#ticketsContainer .content").append(template);
});
applyTicketClickFunction();
},
error: function(data) {
loadingTickets = false;
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").hide();
if (data.status === 429) {
alert(`HTTP ${data.status} - ${data.statusText}\n${data.responseJSON.detail}`)
}
}
});
}
function applyTicketClickFunction() {
$(".ticket-item").on("click", function(e) {
e.preventDefault();
displayTicket(this);
loadTicketContent($(this).data("uuid"));
$('.email-app').removeClass('side-active');
$('.email-content').toggleClass('open');
});
}
function reloadCurrentTicket() {
displayTicket($(".ticket-item.bgc-grey-100"));
loadTicketContent($(".ticket-item.bgc-grey-100").data("uuid"));
}
function changeTicket(next=true) {
var selectedTicket = $(".ticket-item.bgc-grey-100");
var uuid;
if (!selectedTicket.length) {
displayTicket($(".ticket-item").first());
uuid = $(".ticket-item").first().data("uuid");
loadTicketContent(uuid);
return;
}
if (next) {
displayTicket(selectedTicket.next());
uuid = selectedTicket.next().data("uuid");
loadTicketContent(uuid);
}
else {
displayTicket(selectedTicket.prev());
uuid = selectedTicket.prev().data("uuid");
loadTicketContent(uuid);
}
if (!$('.email-content').hasClass('open')) {
@ -294,80 +175,133 @@ function changeTicket(next=true) {
}
}
function displayTicket(ticketElement) {
ticket = $(ticketElement);
ticketID = ticket.data("uuid");
function changeItemsPage(next) {
$("#ticketItemsNextPage").prop("disabled", true);
$("#ticketItemsPrevPage").prop("disabled", true);
// $(".back-to-mailbox").off("click").on("click", function(event) {
// event.preventDefault();
// $('.email-content').toggleClass('open');
// displayTicket(ticketElement);
// });
var page = pagination.page;
if (next && pagination.next) page ++;
else if (!next && pagination.prev) page --;
else return;
filters["page"] = page;
loadTicketItems();
}
function loadTicketItems() {
updateInterfaceState("loading");
fetchTicketsPromise(filters).then((response) => {
// Update the counts to show how many tickets were found
$("#ticketCounts .current").text(response.results.length);
$("#ticketCounts .total").text(response.count);
// If there are no tickets
if (!response.count) {
updateInterfaceState("no-content");
return;
}
const ticketHasNextPage = typeof response.next === "string";
const ticketHasPrevPage = typeof response.previous === "string";
$("#ticketItemsNextPage").prop("disabled", !ticketHasNextPage);
$("#ticketItemsPrevPage").prop("disabled", !ticketHasPrevPage);
const pageNumber = filters["page"] || 1;
pagination = {
"page": pageNumber,
"next": ticketHasNextPage,
"prev": ticketHasPrevPage
}
// Iterate over and handle each ticket
response.results.forEach(function(ticket) {
if (displayedTicketID === ticketID) {
// displayedTicketID = -1;
// Create a formatted version of the ticket's timestamp
const timestamp = new Date(ticket.timestamp);
var formattedTime = timestampToHumanDate(timestamp, ticket.was_yesterday);
// Mark the ticket if it is edited
if (ticket.is_edited) formattedTime += " • edited";
// Create a copy of the template using the ticket data
var template = $($("#ticketItemTemplate").html());
template.find(".ticket-item-author").text(`${ticket.author.forename} ${ticket.author.surname}`);
template.find(".ticket-item-datetime").text(formattedTime);
template.find(".ticket-item-title").text(ticket.title);
template.find(".ticket-item-desc").text(ticket.description);
template.find(".ticket-item-icon").attr("src", ticket.author.icon);
template.attr("data-uuid", ticket.uuid);
// Add the content to the interface
$("#ticketsContainer .content").append(template);
});
// Make tickets clickable
applyTicketClickFunction();
updateInterfaceState("content");
});
}
function loadTicketContent(uuid) {
// updateInterfaceState("loading-content");
if (global_loadingTickets) {
console.debug("Spam prevention\nStopped loadTicketContent because already loading.");
return;
}
ticket.siblings().removeClass("bgc-grey-100");
ticket.addClass("bgc-grey-100");
$("#ticketContent").empty();
$("#ticketTitle").text("")
$("#ticketDesc").empty();
$("#ticketAuthor").text("");
$("#ticketAuthorImg").hide();
$("#ticketAuthorImg").prop("src", "");
$("#ticketTimestamp").text("");
$("#btnGroupDrop2").hide();
$("#ticketBadges").empty().hide();
fetchTicketsPromise({uuid: uuid}).then((response) => {
ticket = response.results[0];
displayedTicketID = ticketID;
// Create a formatted version of the ticket's timestamp
const timestamp = new Date(ticket.timestamp);
var formattedTime = timestampToHumanDate(timestamp, ticket.was_yesterday);
$.ajax({
url: URL_Tickets,
type: 'get',
dataType: 'json',
data: $.param({uuid: ticketID}, true),
success: function (data) {
console.log(JSON.stringify(data, null, 4));
// Mark the ticket if it is edited
if (ticket.is_edited) formattedTime += " • edited";
var ticket = data.results[0];
var author = ticket.author;
var department = author.department;
var priority = ticket.priority;
// Create a copy of the template using the ticket data
var template = $($("#ticketContentTemplate").html())
template.find(".ticket-content-author").text(`${ticket.author.forename} ${ticket.author.surname}`);
template.find(".ticket-content-datetime").text(formattedTime);
template.find(".ticket-content-title").text(ticket.title);
template.find(".ticket-content-desc").text(ticket.description);
template.find(".ticket-content-icon").attr("src", ticket.author.icon);
$("#ticketTitle").text(ticket.title);
$("#ticketDesc").append($(`<div class="w-100">${ticket.description}</div>`));
$("#ticketAuthor").text(`${author.forename} ${author.surname}`);
$("#ticketAuthorImg").show();
$("#ticketAuthorImg").prop("src", author.icon);
$("#btnGroupDrop2").show();
$("#ticketBadges").show();
$("#ticketContent").append(template);
});
$("#ticketBadges").append($(`<div class="badge me-1" style="color: ${priority.colour}; background-color: ${priority.backgroundcolour};">${priority.title} Priority <i class="ti-control-record "></i></div>`));
// $("#ticketContent").empty();
if (department != null) {
$("#ticketBadges").append($(`<div class="badge bgc-deep-purple-500 me-1">${department.title}</div>`));
// updateInterfaceState("showing-content");
}
function fetchTicketsPromise(queryFilters) {
return new Promise(function(resolve, reject) {
global_loadingTickets = true;
$.ajax({
url: URL_Tickets,
type: "GET",
dataType: "JSON",
data: $.param(queryFilters, true),
success: function(response) {
global_loadingTickets = false;
resolve(response);
},
error: function(response) {
global_loadingTickets = false;
if (response.status === 429) {
alert(`
HTTP ${response.status} - ${response.statusText}\n
${response.responseJSON.detail}
`);
}
reject(response);
}
ticket.tags.forEach(function(tag) {
$("#ticketBadges").append($(`<div class="badge me-1" style="color: ${tag.colour}; background-color: ${tag.backgroundcolour};">${tag.title} <i class="ti-tag"></i></div>`));
});
// timestamp
var timestamp = new Date(ticket.timestamp);
var formattedTime = timestampToHumanDate(timestamp, ticket.was_yesterday);
if (ticket.is_edited) {
formattedTime += " • edited";
}
$("#ticketTimestamp").text(formattedTime);
},
error: function(message) {
alert(JSON.stringify(message, null, 4));
}
});
});
}

View File

@ -175,24 +175,23 @@
<div class="bg-body-tertiary peers ai-c p-20 fxw-nw">
<div class="peer me-auto">
<div class="btn-group" role="group">
<button type="button" class="email-side-toggle d-n@md+ btn bgc-white bdrs-2 mR-3 cur-p">
<button type="button" class="email-side-toggle d-n@md+ btn bg-body bdrs-2 mR-3">
<i class="ti-menu"></i>
</button>
<!-- <button type="button" class="btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-tag"></i>
</button> -->
<button type="button" class="btn bgc-white bdrs-2 mR-3 cur-p" onclick="javascript:loadAllTickets();">
<button type="button" class="btn bg-body bdrs-2 mR-3" onclick="javascript:loadTicketItems();">
<i class="fa fa-refresh"></i>
</button>
</div>
</div>
<div class="peer">
<div class="btn-group" role="group">
<button type="button" class="fsz-xs btn bgc-white bdrs-2 mR-3 cur-p" onclick="javascript:changeTicket(false);">
<button type="button" id="ticketItemsPrevPage" class="btn bg-body bdrs-2 mR-3" onclick="javascript: changeItemsPage(false);" disabled>
<i class="ti-angle-left"></i>
</button>
<button type="button" class="fsz-xs btn bgc-white bdrs-2 mR-3 cur-p" onclick="javascript:changeTicket(true);">
<button type="button" id="ticketItemsNextPage" class="btn bg-body bdrs-2 mR-3" onclick="javascript: changeItemsPage(true);" disabled>
<i class="ti-angle-right"></i>
</button>
</div>
@ -313,55 +312,7 @@
</div>
</div>
</div>
<div class="email-content-wrapper">
<!-- Header -->
<div class="peers ai-c jc-sb pX-40 pY-30">
<div class="peers peer-greed">
<div class="peer mR-20">
<img id="ticketAuthorImg" class="bdrs-50p w-3r h-3r" alt="" src="" style="display: none; object-fit: cover;">
</div>
<div class="peer">
<small id="ticketTimestamp"></small>
<h5 id="ticketAuthor" class="c-grey-900 mB-5"></h5>
<div id="ticketBadges" style="display: none;"></div>
</div>
</div>
<!-- <div class="peer">
<div class="btn-group" role="group">
<button id="btnGroupDrop2" class="btn btn-danger c-white bdrs-50p p-15 lh-0" style="display: none;" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="ti-menu"></i>
</button>
<ul class="dropdown-menu fsz-sm" aria-labelledby="btnGroupDrop2">
test
</ul>
</div>
</div> -->
</div>
<!-- Content -->
<div class="bdT pX-40 pY-30">
<h4 id="ticketTitle"></h4>
<div id="ticketDesc"></div>
<!-- <h4>Title of this email goes here</h4>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
</p> -->
</div>
<div id="ticketContent" class="email-content-wrapper">
</div>
</div>
</div>
@ -428,23 +379,57 @@
<!-- Ticket Item Template -->
<script id="ticketItemTemplate" type="text/template">
<div class="ticket-item peers fxw-nw p-20 bdB bgcH-grey-100" data-uuid="-1">
<div class="peer mR-10">
<img src="" alt="" class="ticket-item-icon me-2">
</div>
<div class="peer peer-greed ov-h">
<div class="peers ai-c">
<div class="peer peer-greed">
<h6 class="ticket-item-author"></h6>
</div>
<div class="peer">
<small class="ticket-item-datetime"></small>
</div>
<div class="peer mR-10">
<img src="" alt="" class="ticket-item-icon me-2">
</div>
<div class="peer peer-greed ov-h">
<div class="peers ai-c">
<div class="peer peer-greed">
<h6 class="ticket-item-author"></h6>
</div>
<div class="peer">
<small class="ticket-item-datetime"></small>
</div>
</div>
<h5 class="ticket-item-title c-grey-900"></h5>
<div class="ticket-item-desc"></div>
</div>
</div>
</script>
<!-- Ticket Content Template -->
<script id="ticketContentTemplate" type="text/template">
<!-- Header -->
<div class="ticket-content">
<div class="peers ai-c jc-sb pX-40 pY-30">
<div class="peers peer-greed">
<div class="peer mR-20">
<img class="ticket-content-icon" src="" alt="">
</div>
<div class="peer">
<small class="ticket-content-datetime"></small>
<h5 class="ticket-content-author c-grey-900"></h5>
<div class="ticket-content-badges"></div>
</div>
<h5 class="ticket-item-title c-grey-900"></h5>
<div class="ticket-item-desc"></div>
</div>
</div>
<!-- Content -->
<div class="bdT pX-40 pY-30">
<h4 class="ticket-content-title"></h4>
<div class="ticket-content-desc w-100"></div>
</div>
</div>
</script>
<!-- Ticket Content Badge Template -->
<script id="ticketContentBadgeTemplate" type=text/template>
<div class="ticket-content-badge badge me-1">
<span class="ticket-content-badge-text"></span>
<i class="ticket-content-badge-icon"></i>
</div>
</script>
<!-- Define Variables -->
<script>
const URL_Tickets = "{% url 'api:tickets' %}";