diff --git a/apps/static/js/home/content.js b/apps/static/js/home/content.js index d4b946f..aa94517 100644 --- a/apps/static/js/home/content.js +++ b/apps/static/js/home/content.js @@ -77,16 +77,14 @@ async function initContentTable() { data: "creation_datetime", className: "text-nowrap", render: function(data, type) { - // return new Date(data).toISOString().split("T")[0]; let dateTime = new Date(data); - let dateTimeString = formatDate(dateTime); return $(` - ${dateTime.toISOString().split("T")[0]} + data-bs-html="true" + data-bs-custom-class="text-center" + data-bs-toggle="popover" + data-bs-content="${formatStringDate(dateTime, "%a, %D %B, %Y
%H:%M:%S")}"> + ${formatStringDate(dateTime, "%D, %b %Y")}
`).popover()[0]; } diff --git a/apps/static/js/home/index.js b/apps/static/js/home/index.js index 1460901..4ddecd6 100644 --- a/apps/static/js/home/index.js +++ b/apps/static/js/home/index.js @@ -21,42 +21,6 @@ $(document).on("selectedServerChange", function() { $("#subscriptionsTab").click(); }); -function formatDate(date) { - - // Array of weekday names - const weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - - // Array of month names - const months = [ - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" - ]; - - // Get individual components - let hours = String(date.getHours()).padStart(2, '0'); - let minutes = String(date.getMinutes()).padStart(2, '0'); - let seconds = String(date.getSeconds()).padStart(2, '0'); - let dayOfWeek = weekdays[date.getDay()]; - let dayOfMonth = date.getDate(); - let month = months[date.getMonth()]; - let year = date.getFullYear(); - - // Format day with ordinal suffix - let dayOfMonthSuffix; - if (dayOfMonth % 10 === 1 && dayOfMonth !== 11) { - dayOfMonthSuffix = dayOfMonth + "st"; - } else if (dayOfMonth % 10 === 2 && dayOfMonth !== 12) { - dayOfMonthSuffix = dayOfMonth + "nd"; - } else if (dayOfMonth % 10 === 3 && dayOfMonth !== 13) { - dayOfMonthSuffix = dayOfMonth + "rd"; - } else { - dayOfMonthSuffix = dayOfMonth + "th"; - } - - // `${hours}:${minutes}:${seconds} ยท ` - return `${dayOfWeek}, ${dayOfMonthSuffix} ${month}, ${year}
${hours}:${minutes}:${seconds}`; -} - function genHexString(len) { let output = ''; for (let i = 0; i < len; ++i) { @@ -65,6 +29,61 @@ function genHexString(len) { return output; } +// my clone of python's datetime.strftime +function formatStringDate(date, format) { + const padZero = (num, len) => String(num).padStart(len, "0"); + const abbreviate = (str) => str.slice(0, 3); + const ordSuffix = day => [,"st","nd","rd"][day % 10] || "th"; + + const formatters = { + "%a": date => abbreviate(date.toLocaleString("en-GB", { weekday: "short" })), + "%A": date => date.toLocaleString("en-GB", { weekday: "long" }), + "%w": date => date.getDay(), + "%d": date => padZero(date.getDate(), 2), + "%-d": date => date.getDate(), + "%b": date => abbreviate(date.toLocaleString("en-GB", { month: "short" })), + "%B": date => date.toLocaleString("en-GB", { month: "long" }), + "%m": date => padZero(date.getMonth() + 1, 2), + "%-m": date => date.getMonth() + 1, + "%y": date => padZero(date.getFullYear() % 100, 2), + "%-y": date => date.getFullYear() % 100, + "%Y": date => date.getFullYear(), + "%H": date => padZero(date.getHours(), 2), + "%-H": date => date.getHours(), + "%I": date => padZero(date.getHours() % 12 || 12, 2), + "%-I": date => date.getHours() % 12 || 12, + "%p": date => date.getHours() >= 12 ? "PM" : "AM", + "%M": date => padZero(date.getMinutes(), 2), + "%-M": date => date.getMinutes(), + "%S": date => padZero(date.getSeconds(), 2), + "%-S": date => date.getSeconds(), + "%f": date => padZero(date.getMilliseconds() * 1000, 6), + "%z": date => { + const offset = date.getTimezoneOffset(); + const sign = offset > 0 ? "-" : "+"; + const absOffset = Math.abs(offset); + const hours = padZero(Math.floor(absOffset / 60), 2); + const minutes = padZero(absOffset % 60, 2); + return `${sign}${hours}${minutes}`; + }, + "%Z": date => { + const match = date.toTimeString().match(/\((.*)\)/); + return match ? match[1] : ""; + }, + "%j": date => padZero(Math.ceil((date - new Date(date.getFullYear(), 0, 1)) / 86400000) + 1, 3), + "%-j": date => Math.ceil((date - new Date(date.getFullYear(), 0, 1)) / 86400000) + 1, + "%U": date => padZero(Math.floor((date - new Date(date.getFullYear(), 0, 1) + (86400000 * (date.getDay() || 7 - 1))) / (86400000 * 7)), 2), + "%W": date => padZero(Math.floor((date - new Date(date.getFullYear(), 0, 1) + (86400000 * (date.getDay() || 7))) / (86400000 * 7)), 2), + "%c": date => date.toLocaleString(), + "%x": date => date.toLocaleDateString(), + "%X": date => date.toLocaleTimeString(), + "%D": date => date.getDate() + ordSuffix(date.getDate()), + "%%": () => "%" + }; + + return format.replace(/%[a-zA-Z%-]/g, match => formatters[match] ? formatters[match](date) : match); +} + // #region Colour Controls $(".colour-control-picker").on("change", function() { $(this).closest(".colour-control-group").find(".colour-control-text").val($(this).val()); @@ -123,4 +142,5 @@ $(document).ready(function() { updateColourInput(id, "#" + defaultColour) $(`#${id} [data-bs-toggle="tooltip"]`).tooltip(); }); -}); \ No newline at end of file +}); + diff --git a/apps/static/js/home/subscriptions.js b/apps/static/js/home/subscriptions.js index eb022a7..058d9ff 100644 --- a/apps/static/js/home/subscriptions.js +++ b/apps/static/js/home/subscriptions.js @@ -57,6 +57,7 @@ async function initSubscriptionTable() { { title: "Channels", data: "channels_count", + className: "text-center", render: function(data) { return `${data}`; } @@ -66,14 +67,13 @@ async function initSubscriptionTable() { data: "creation_datetime", render: function(data, type) { let dateTime = new Date(data); - let dateTimeString = formatDate(dateTime); return $(` - ${dateTime.toISOString().split("T")[0]} + data-bs-content="${formatStringDate(dateTime, "%a, %D %B, %Y
%H:%M:%S")}"> + ${formatStringDate(dateTime, "%D, %b %Y")}
`).popover()[0]; } @@ -431,7 +431,6 @@ async function loadChannelOptions(guildId) { $("#subChannels").val("").change(); try { const channels = await loadChannels(guildId); - channels.sort((a, b) => a.position - b.position); // If we have reached the discord API rate limit if (channels.message && channels.message.includes("rate limit")) { @@ -457,6 +456,9 @@ async function loadChannelOptions(guildId) { ); } + // Sort by the specified position of each channel object + channels.sort((a, b) => a.position - b.position); + discordChannels = []; channels.forEach(channel => {