398 lines
14 KiB
JavaScript

var filters = {"ordering": "-edit_timestamp"};
global_loadingTickets = false;
searchTimeout = null;
pagination = {};
complexItems = false;
$(document).ready(function() {
initSearchBar();
setupFilter("#filterSidebar .filter-department", "author__department");
setupFilter("#filterSidebar .filter-tags", "tags");
setupFilter("#filterSidebar .filter-priority", "priority");
loadFilterCounts();
loadTicketItems();
});
function updateItemsState(state) {
console.debug(`updating items state to '${state}'`);
$("#ticketsContainer").scrollTop(0);
$("#ticketsContainer").trigger("updateScrollbar");
switch (state) {
case "content":
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").hide();
$("#filterSidebar input").prop("disabled", false);
break;
case "loading":
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").hide();
$("#ticketsContainer .loading").show();
$("#filterSidebar input").prop("disabled", true);
break;
case "no-content":
$("#ticketsContainer .content").empty();
$("#ticketsContainer .none-found").show();
$("#ticketsContainer .loading").hide();
$("#filterSidebar input").prop("disabled", false);
break;
default:
throw new Error(`Invalid Items State '${state}'`);
}
}
function updateContentState(state) {
console.debug(`updating content state to '${state}'`);
switch (state) {
case "content":
$("#ticketContent .loading").hide();
break;
case "loading":
$("#ticketContent .content").empty();
$("#ticketContent .loading").show();
break;
default:
throw new Error(`Invalid Content State '${state}'`);
}
}
function initSearchBar() {
$("#searchTickets").keyup(() => {
updateItemsState("loading");
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;
}
loadTicketItems();
}, 500);
})
}
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];
const deselectOption = $(`[name='${input.prop("name")}'].deselect-radio-filters`);
if (deselectOption.length) {
if (deselectOption.prop("checked")) deselectOption.parent().hide();
else deselectOption.parent().show();
}
}
console.debug(`Filter applied '${key}' as '${uuid}'`)
loadTicketItems();
});
});
}
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 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();
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 applyTicketClickFunction() {
$(".ticket-item").on("click", function(e) {
e.preventDefault();
if ($(this).hasClass("active")) {
return;
}
loadTicketContent($(this).data("uuid"));
$(".ticket-item").removeClass("active");
$(this).addClass("active");
$('.email-app').removeClass('side-active');
$('.email-content').toggleClass('open');
});
}
$(".back-to-mailbox").on("click", function(e) {
e.preventDefault();
$(".ticket-item.active").removeClass("active");
});
function reloadCurrentTicket() {
loadTicketContent($(".ticket-item.active").data("uuid"));
}
function changeTicket(next=true) {
var selectedTicket = $(".ticket-item.active");
var uuid;
if (!selectedTicket.length) selectedTicket = $(".ticket-item").first();
else if (next) selectedTicket = selectedTicket.next();
else selectedTicket = selectedTicket.prev();
$(".ticket-item").removeClass("active");
selectedTicket.addClass("active");
uuid = selectedTicket.data("uuid");
loadTicketContent(uuid);
if (!$('.email-content').hasClass('open')) {
$('.email-content').addClass('open');
}
}
function changeItemsPage(next) {
$("#ticketItemsNextPage").prop("disabled", true);
$("#ticketItemsPrevPage").prop("disabled", true);
var page = pagination.page;
if (next && pagination.next) page ++;
else if (!next && pagination.prev) page --;
else return;
loadTicketItems(page);
}
function loadTicketItems(page=1) {
if (global_loadingTickets) {
alert("Spam prevention\nStopped loadTicketItems because already loading.");
return;
}
global_loadingTickets = true;
updateItemsState("loading");
filters["page"] = page;
var fetchFilters = { ...filters };
fetchFilters["only_fields"] = "uuid,title,short_description,author,priority,tags,timestamp,is_edited,author__forename,author__surname,author__department,author__icon,display_datetime";
fetchTicketsPromise(fetchFilters).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) {
updateItemsState("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; // If we haven't tracked the page, it's safe to assume it's 1,
pagination = { // because we always track it when it changes.
"page": pageNumber,
"next": ticketHasNextPage,
"prev": ticketHasPrevPage
}
// Update the pagination count with the current page
$("#paginationCounts .current").text(pageNumber);
// If we are on page one (which has been normalised to be the case in many intances)
// We can use the amount of results to calculate the total amount of pages.
if (pageNumber === 1) {
$("#paginationCounts .total").text(Math.ceil(response.count / response.results.length));
}
// Iterate over and handle each ticket
response.results.forEach(function(ticket) {
// 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(ticket.display_datetime);
template.find(".ticket-item-title").text(ticket.title);
template.find(".ticket-item-desc").html(ticket.short_description);
template.find(".ticket-item-icon").attr("src", ticket.author.icon);
template.attr("data-uuid", ticket.uuid);
// Add tickets using the badge template
ticket.tags.forEach(function(tag) {
var tagTemplate = $($("#ticketContentBadgeTemplate").html());
tagTemplate.find(".ticket-content-badge-text").text(tag.title);
tagTemplate.css({ "color": tag.colour, "background-color": tag.backgroundcolour });
template.find(".ticket-item-tags").append(tagTemplate);
});
var priorityElem = template.find(".ticket-item-priority");
// priorityElem.text(ticket.priority.title);
priorityElem.css("color", ticket.priority.colour);
priorityElem.css("background-color", ticket.priority.backgroundcolour);
var departmentElem = template.find(".ticket-item-department");
departmentElem.addClass("bgc-orange-100 c-orange-700")
// // Add the priority using the badge template
// var priorityTemplate = $($("#ticketContentBadgeTemplate").html());
// priorityTemplate.find(".ticket-content-badge-text").text(ticket.priority.title + " Priority");
// priorityTemplate.css({ "color": ticket.priority.colour, "background-color": ticket.priority.backgroundcolour });
// priorityTemplate.removeClass("rounded-pill").addClass("rounded-1");
// template.find(".ticket-item-priority").append(priorityTemplate);
// Add the content to the interface
$("#ticketsContainer .content").append(template);
});
// Make tickets clickable
applyTicketClickFunction();
updateItemsState("content");
global_loadingTickets = false;
});
}
function loadTicketContent(uuid) {
updateContentState("loading");
if (global_loadingTickets) {
console.debug("Spam prevention\nStopped loadTicketContent because already loading.");
return;
}
global_loadingTickets = true;
$("#ticketContent .content").empty();
fetchTicketsPromise({uuid: uuid}).then((response) => {
ticket = response.results[0];
// 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(ticket.display_datetime);
template.find(".ticket-content-title").text(ticket.title);
template.find(".ticket-content-desc").html(ticket.description);
template.find(".ticket-content-icon").attr("src", ticket.author.icon);
console.debug(ticket.description);
ticket.tags.forEach(function(tag) {
var tagTemplate = $($("#ticketContentBadgeTemplate").html());
tagTemplate.find(".ticket-content-badge-text").text(tag.title);
tagTemplate.css({ "color": tag.colour, "background-color": tag.backgroundcolour });
template.find(".ticket-content-badges").append(tagTemplate);
});
$("#ticketContent .content").append(template);
updateContentState("content");
global_loadingTickets = false;
});
// $("#ticketContent").empty();
// 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);
}
});
});
}
// Prevent certain dropdowns from closing when the user clicks.
$(".dropdown-menu.prevent-click-close").on("click", function(e) {
e.stopPropagation();
});
function toggleComplexItems() {
complexItems = !complexItems;
if (complexItems) {
$("#ticketsContainer").addClass("complex-items");
}
else {
$("#ticketsContainer").removeClass("complex-items");
}
}