All checks were successful
Build and Push Docker Image / build (push) Successful in 14s
not finished for saving, editing existing subscriptions. Only appears as option under 'advanced' at the minute, choices have no affect.
192 lines
7.7 KiB
JavaScript
192 lines
7.7 KiB
JavaScript
$(document).ready(async function() {
|
|
await initSubscriptionTable();
|
|
await initFiltersTable();
|
|
await initContentTable();
|
|
|
|
$("#subscriptionsTab").click();
|
|
|
|
await loadSavedGuilds();
|
|
await loadServerOptions();
|
|
});
|
|
|
|
$(document).on("selectedServerChange", function() {
|
|
$("#subscriptionsTab").click();
|
|
});
|
|
|
|
function genHexString(len=6) {
|
|
let output = '';
|
|
for (let i = 0; i < len; ++i) {
|
|
output += (Math.floor(Math.random() * 16)).toString(16);
|
|
}
|
|
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 => (day % 100 >= 11 && day % 100 <= 13) ? "th" : ["th", "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());
|
|
});
|
|
|
|
$(".colour-control-text").on("change", function() {
|
|
$(this).closest(".colour-control-group").find(".colour-control-picker").val($(this).val());
|
|
});
|
|
|
|
function updateColourInput(id, hexString) {
|
|
hexString = normaliseHexString(hexString.toUpperCase());
|
|
$(`#${id} .colour-picker`).val(hexString);
|
|
$(`#${id} .colour-text`).val(hexString);
|
|
}
|
|
|
|
function getColourInputVal(id, includeHashtag=true) {
|
|
const hexString = $(`#${id}Text`).val();
|
|
return normaliseHexString(hexString, includeHashtag);
|
|
}
|
|
|
|
function normaliseHexString(hexString, includeHashtag=true) {
|
|
console.debug(`normalising hex string '${hexString}' include hashtag '${includeHashtag}'`);
|
|
|
|
// Remove any non-hex characters (e.g., additional hashtags)
|
|
hexString = hexString.replace(/[^A-F0-9]/gi, '');
|
|
|
|
// Ensure the hex string has a valid length of either 3, 6, or 8 characters
|
|
if (![3, 6, 8].includes(hexString.length)) {
|
|
throw new Error(`Invalid hex string length. Must be 3, 6, or 8 characters. hexString=${hexString}`);
|
|
}
|
|
|
|
return includeHashtag ? `#${hexString}` : hexString;
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
$(".colour-input").each(function() {
|
|
let id = $(this).attr("data-id")
|
|
label = $(this).attr("data-label");
|
|
helpText = $(this).attr("data-helptext");
|
|
tabIndex = parseInt($(this).attr("data-tabindex"));
|
|
defaultColour = $(this).attr("data-defaultcolour");
|
|
defaultColour = defaultColour ? defaultColour : "#3498db"
|
|
|
|
$(this).replaceWith(`
|
|
<label for="${id}Picker" class="form-label">${label}</label>
|
|
<div id="${id}" class="input-group">
|
|
<input type="color" name="${id}Picker" id="${id}Picker" class="form-control-color input-group-text colour-picker rounded-start-1" tabindex="${tabIndex}">
|
|
<input type="text" name="${id}Text" id="${id}Text" class="form-control colour-text" tabindex="${tabIndex + 1}">
|
|
<button type="button" class="btn btn-secondary colour-reset" data-bs-toggle="tooltip" data-bs-title="Reset Colour" data-defaultcolour="${defaultColour}" tabindex="${tabIndex + 2}">
|
|
<i class="bi bi-arrow-clockwise"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-secondary rounded-end-1 colour-random" data-bs-toggle="tooltip" data-bs-title="Random Colour" tabindex="${tabIndex + 3}">
|
|
<i class="bi bi-dice-5"></i>
|
|
</button>
|
|
</div>
|
|
<div class="form-text">${helpText}</div>
|
|
`);
|
|
|
|
$(`#${id} .colour-picker`).on("change", function() {
|
|
updateColourInput(id, $(this).val());
|
|
});
|
|
|
|
$(`#${id} .colour-text`).on("change", function() {
|
|
updateColourInput(id, $(this).val());
|
|
});
|
|
|
|
$(`#${id} .colour-reset`).on("click", function() {
|
|
updateColourInput(id, $(this).attr("data-defaultcolour"));
|
|
});
|
|
|
|
$(`#${id} .colour-random`).on("click", function() {
|
|
updateColourInput(id, "#" + genHexString(6));
|
|
});
|
|
|
|
updateColourInput(id, "#" + defaultColour)
|
|
$(`#${id} [data-bs-toggle="tooltip"]`).tooltip();
|
|
});
|
|
});
|
|
|
|
async function confirmationModal(title, bodyText, style, acceptFunc, declineFunc) {
|
|
let $modal = $("#confirmationModal");
|
|
|
|
// Ensure valid style and apply it to the confirm button
|
|
if (!["danger", "success", "warning", "info", "primary", "secondary"].includes(style)) {
|
|
throw new Error(`${style} is not a valid style`);
|
|
}
|
|
$modal.find(".modal-confirm-btn").addClass(`btn-${style}`);
|
|
|
|
$modal.find(".modal-title").text(title);
|
|
$modal.find(".modal-body > p").html(bodyText);
|
|
|
|
$modal.find(".modal-confirm-btn").off("click").on("click", async function(e) {
|
|
await acceptFunc()
|
|
$modal.modal("hide");
|
|
});
|
|
|
|
$modal.find(".modal-dismiss-btn").off("click").on("click", async function(e) {
|
|
if (declineFunc) await declineFunc();
|
|
$modal.modal("hide");
|
|
});
|
|
|
|
$modal.modal("show");
|
|
}
|
|
|
|
function arrayToHtmlList(array, bold=false) {
|
|
$ul = $("<ul>").addClass("mb-0");
|
|
|
|
array.forEach(item => {
|
|
let $li = $("<li>");
|
|
$ul.append(bold ? $li.append($("<b>").text(item)) : $li.text(item));
|
|
});
|
|
|
|
return $ul;
|
|
} |