var subTable = null; discordChannels = []; subSearchTimeout = null; subOptions = null; // Create subscription table async function initSubscriptionTable() { subOptions = await getSubscriptionOptions(); await initTable("#subscriptionsTabPane", "subTable", loadSubscriptions, showEditSubModal, deleteSelectedSubscriptions, subOptions); subTable = $("#subTable").DataTable({ info: false, paging: false, ordering: false, searching: false, autoWidth: false, order: [], select: { style: "multi+shift", selector: 'th:first-child input[type="checkbox"]' }, columnDefs: [ { orderable: false, targets: "no-sort" }, { targets: 0, checkboxes: { selectRow: true } }, ], columns: [ { // Select row checkbox column title: '', data: null, orderable: false, className: "text-center col-switch-width", render: function() { return '' } }, { title: "ID", data: "id", visible: false }, { title: "Name", data: "name", className: "text-truncate", render: function(data, type, row) { const name = sanitise(data); return ``; } }, { title: "URL", data: "url", className: "text-truncate", render: function(data, type) { const url = sanitise(data); return `${url}`; } }, { title: "Channels", data: "channels_count", className: "text-center", render: function(data) { const channelsCount = sanitise(data); return `${channelsCount}`; } }, { title: "Created", data: "creation_datetime", render: function(data, type) { let dateTime = new Date(data); return $(` %H:%M:%S")}"> ${formatStringDate(dateTime, "%D, %b %Y")} `).popover()[0]; } }, { title: "Notes", data: "extra_notes", orderable: false, className: "text-center", render: function(data, type) { if (!data) { return "" } const extraNotes = sanitise(data); return $(` `).popover()[0]; } }, { title: "Active", data: "active", orderable: false, className: "text-center form-switch", render: function(data, type) { return `` } }, { orderable: false, className: "p-0", render: function(data, type, row) { const embedColour = sanitise(row.embed_colour); return `
${error}
`
);
}
finally {
// Re-enable toggles after 500ms
setTimeout(() => {
$(".sub-toggle-active").prop("disabled", false); },
500
);
}
});
// Open new subscription modal
$("#addSubscriptionBtn").on("click", async function() {
await showEditSubModal(-1);
});
async function showEditSubModal(subId) {
if (subId === -1) {
$("#subFormModal .form-create, #subAdvancedModal .form-create").show();
$("#subFormModal .form-edit, #subAdvancedModal .form-edit").hide();
$("#subFormModal input, #subFormModal textarea").val("");
$("#subChannels").val("").change();
$("#subFilters").val("").change();
$("#subTitleMutators").val("").change();
$("#subDescMutators").val("").change();
$("#subActive").prop("checked", true);
$("#subEmbedColour .colour-reset").click();
$("#subArticleFetchImage").prop("checked", true);
$("#subPubThreshold").val(getCurrentDateTime());
}
else {
$("#subFormModal .form-create, #subAdvancedModal .form-create").hide();
$("#subFormModal .form-edit, #subAdvancedModal .form-edit").show();
const subscription = subTable.row(function(idx, data, node) {
return data.id === subId;
}).data();
$("#subName").val(subscription.name);
$("#subUrl").val(subscription.url);
$("#subExtraNotes").val(subscription.extra_notes);
$("#subActive").prop("checked", subscription.active);
$("#subTitleMutators").val("").change();
$("#subTitleMutators").val(subscription.article_title_mutators.map(mutator => mutator.id)).change();
$("#subDescMutators").val("").change();
$("#subDescMutators").val(subscription.article_desc_mutators.map(mutator => mutator.id)).change();
const channels = await getSubChannels(subscription.id);
$("#subChannels").val("").change();
$("#subChannels").val(channels.results.map(channel => channel.channel_id)).change();
$("#subFilters").val("").change();
$("#subFilters").val(subscription.filters).change();
updateColourInput("subEmbedColour", `#${subscription.embed_colour}`);
$("#subArticleFetchImage").prop("checked", subscription.article_fetch_image);
$("#subPubThreshold").val(subscription.published_threshold.split('+')[0]);
}
$("#subId").val(subId);
$("#subFormModal").modal("show");
}
function getValueFromField(elem) {
const tagName = elem.tagName.toLowerCase();
const $elem = $(elem);
if (tagName) { return $elem.val() }
switch ($elem.attr("type")) {
case "checkbox":
return $elem.prop("checked");
default:
return $elem.val();
}
}
$("#subForm").on("submit", async function(event) {
event.preventDefault();
let subId = $("#subId").val();
let guildId = getCurrentlyActiveServer().guild_id;
// TODO: move this into a function, so I can fix the active toggle switches which are broken due to this change
let formData = new FormData();
formData.append("guild_id", guildId);
// Populate formdata with [data-field] control values
$('#subForm [data-field], #subAdvancedModal [data-field]').each(function() {
const value = getValueFromField(this);
formData.append($(this).data("field"), value);
});
// Add title mutators to formdata
$("#subTitleMutators option:selected").toArray().map(mutator => parseInt(mutator.value)).forEach(
mutator => formData.append("article_title_mutators", mutator)
);
// Add description mutator to formdata
$("#subDescMutators option:selected").toArray().map(mutator => parseInt(mutator.value)).forEach(
mutator => formData.append("article_desc_mutators", mutator)
);
// Add Filters to formdata
$("#subFilters option:selected").toArray().forEach(
filter => formData.append("filters", parseInt(filter.value))
);
// This field is constructed differently, so needs to be specifically added
formData.append("embed_colour", getColourInputVal("subEmbedColour", false));
subId = await saveSubscription(subId, formData);
if (subId) {
showToast("success", "Subscription Saved", `Subscription ID ${subId}`);
}
else {
showToast("danger", "Error Saving Subscription", "");
return;
}
await deleteSubChannels(subId);
$("#subChannels option:selected").each(async function() {
let $channel = $(this);
let channelFormData = new FormData();
channelFormData.append("channel_id", $channel.val());
channelFormData.append("channel_name", $channel.data("name"));
channelFormData.append("subscription", subId);
await newSubChannel(channelFormData);
});
await loadSubscriptions(guildId);
$("#subFormModal").modal("hide");
});
async function saveSubscription(id, formData, handleErrorMsg=true) {
let response
try {
response = id === "-1" ? await newSubscription(formData) : await editSubscription(id, formData);
}
catch (err) {
console.error(err);
if (handleErrorMsg) {
showToast("danger", "Subscription Error", err.responseText, 18000);
}
return false;
}
return response.id;
}
async function saveSubChannel(formData) {
var response
try {
response = await newSubChannel(formData);
}
catch (error) {
console.log(error);
showToast("danger", "Failed to save subchannel", error, 18000);
return false
}
return response.id
}
function clearExistingSubRows() {
$("#subTable thead .table-select-all").prop("checked", false).prop("indeterminate", false);
subTable.clear().draw(false);
}
$("#subscriptionsTabPane").on("click", ".table-refresh-btn", async function() {
loadSubscriptions(getCurrentlyActiveServer().guild_id);
});
async function loadSubscriptions(guildId) {
if (!guildId)
return;
setTableFilter("subTable", "guild_id", guildId);
ensureTablePagination("subTable");
$("#subscriptionsTabPane .table-del-btn").prop("disabled", true);
clearExistingSubRows();
try {
var subs = await getSubscriptions(tableFilters["subTable"], tableSorts["subTable"]);
subTable.rows.add(subs.results).draw(false);
}
catch (err) {
console.error(err)
showToast("danger", `Error Loading Subscriptions: HTTP ${err.status}`, err, 15000);
return;
}
updateTableContainer(
"subscriptionsTabPane",
tableFilters["subTable"]["page"],
tableFilters["subTable"]["page_size"],
subs.results.length,
subs.count,
subs.next,
subs.previous
);
$("#subTable thead .table-select-all").prop("disabled", subs.results.length === 0);
console.debug("loading subs, " + subs.results.length + " found");
}
// #region Server Change Event Handler
$(document).on("selectedServerChange", async function() {
let server = getCurrentlyActiveServer();
guildId = server.guild_id;
await updateDefaultSubEmbedColour();
await loadSubscriptions(guildId);
await loadChannelOptions(guildId);
await loadFilterOptions(guildId);
await loadMutatorOptions();
})
async function updateDefaultSubEmbedColour(settings=null) {
if (!settings){
settings = (await getGuildSettings(guildId)).results[0]
}
$("#subEmbedColour .colour-reset").attr("data-defaultcolour", "#" + settings.default_embed_colour);
}
// #endregion
// #region Delete Subscriptions
// Delete button on the 'edit subscription' modal
$("#deleteEditSub").on("click", async function() {
const subId = parseInt($("#subId").val());
const sub = subTable.row(function(idx, row) { return row.id === subId }).data();
const subName = sanitise(sub.name);
$("#subFormModal").modal("hide");
await confirmationModal(
"Delete a Subscription",
`Do you wish to permanently delete ${subName}?`,
"danger",
async () => {
await deleteSubscription(subId);
await loadSubscriptions(getCurrentlyActiveServer().guild_id);
showToast(
"danger",
"Deleted a Subscription",
subName,
12000
);
},
async () => {
$("#subFormModal").modal("show");
}
);
});
async function deleteSelectedSubscriptions() {
const rows = subTable.rows(".selected").data().toArray();
const names = rows.map(row => row.name);
const namesString = arrayToHtmlList(names, true).prop("outerHTML");
const isMany = names.length > 1;
await confirmationModal(
`Delete ${isMany ? "Many Subscriptions" : "a Subscription"}`,
`Do you wish to permanently delete ${isMany ? "these" : "this"} ${names.length} subscription${isMany ? "s" : ""}?