From 3909c081132692760be22eb5f3473045036002d6 Mon Sep 17 00:00:00 2001 From: Corban-Lee Date: Tue, 30 Jul 2024 20:39:25 +0100 Subject: [PATCH] working on filters/sorts --- apps/static/js/api.js | 19 ++++- apps/static/js/home/filters.js | 38 +++++---- apps/static/js/home/subscriptions.js | 47 +++++------ apps/static/js/table.js | 81 ++++++++++++++----- apps/templates/home/includes/settingstab.html | 15 +--- 5 files changed, 122 insertions(+), 78 deletions(-) diff --git a/apps/static/js/api.js b/apps/static/js/api.js index 4004998..9f6da92 100644 --- a/apps/static/js/api.js +++ b/apps/static/js/api.js @@ -23,6 +23,15 @@ async function ajaxRequest(url, method, data) { } } +function makeQuerystring(filters, sort) { + let querystring = "?"; + console.log(JSON.stringify(filters), null, 4) + for (key in filters) { + querystring += `${key}=${filters[key]}&`; + } + return querystring += `ordering=${sort}`; +} + // Saved Guilds async function getSavedGuilds() { @@ -54,8 +63,9 @@ async function loadChannels(guildId) { // Subscriptions -async function getSubscriptions(guildId, page=1, pageSize=10, search="") { - const url = `/api/subscription/?guild_id=${guildId}&page=${page}&page_size=${pageSize}&search=${search}`; +async function getSubscriptions(filters, sort) { + let querystring = makeQuerystring(filters, sort); + url = `/api/subscription/${querystring}`; return await ajaxRequest(url, "GET"); } @@ -105,8 +115,9 @@ async function deleteSubChannels(subscriptionId) { // Filters -async function getFilters(guildId, page=1, pageSize=10, search="") { - const url = `/api/filter/?guild_id=${guildId}&page=${page}&page_size=${pageSize}&search=${search}`; +async function getFilters(filters, sort) { + let querystring = makeQuerystring(filters, sort); + url = `/api/filter/${querystring}`; return await ajaxRequest(url, "GET"); } diff --git a/apps/static/js/home/filters.js b/apps/static/js/home/filters.js index 092eacc..d7449be 100644 --- a/apps/static/js/home/filters.js +++ b/apps/static/js/home/filters.js @@ -172,34 +172,40 @@ $("#filtersTabPane").on("click", ".table-refresh-btn", async function() { loadFilters(getCurrentlyActiveServer().guild_id); }); -async function loadFilters(guildId, page=1, pageSize=null, search=null) { - +async function loadFilters(guildId) { if (!guildId) return; - if (!pageSize) - pageSize = $("#filtersTablePageSize").val(); - - if (!search) - search = $("#filtersTabPane .table-searchbar").val(); + setTableFilter("filtersTable", "guild_id", guildId); $("#filtersTabPane .table-del-btn").prop("disabled", true); clearExistingFilterRows(); try { - const filters = await getFilters(guildId, page, pageSize, search); - filtersTable.rows.add(filters.results).draw(false); - - updateTablePagination("#filtersTabPane .table-pagination", page, pageSize, filters.count, filters.next, filters.previous); - updateTablePaginationInfo("#filtersTabPane .table-page-info", filters.results.length, filters.count); - - $("#filtersTable thead .table-select-all").prop("disabled", filters.results.length === 0); + alert(JSON.stringify(tableFilters["filtersTable"], null, 4)) + var contentFilters = await getFilters(tableFilters["filtersTable"], tableSorts["filtersTable"]); + filtersTable.rows.add(contentFilters.results).draw(false); } catch (err) { console.error(err) - console.error(JSON.stringify(err, null, 4)); - showToast("danger", `Error Loading Filters: HTTP ${err.status}`, err.responseJSON.message, 15000); + showToast("danger", `Error Loading Filters: HTTP ${err.status}`, err, 15000); + return; } + + // shorthand + let filters = tableFilters["filtersTable"]; + + updateTablePagination( + "#filtersTabPane .table-pagination", + filters["page"], filters["page_size"], contentFilters.count, contentFilters.next, contentFilters.previous + ); + updateTablePaginationInfo( + "#filtersTabPane .table-page-info", + contentFilters.results.length, contentFilters.count + ); + + $("#filtersTable thead .table-select-all").prop("disabled", contentFilters.results.length === 0); + console.debug(`loaded filters, ${contentFilters.results.length} found`); } $(document).ready(async function() { diff --git a/apps/static/js/home/subscriptions.js b/apps/static/js/home/subscriptions.js index 781e784..a1a6394 100644 --- a/apps/static/js/home/subscriptions.js +++ b/apps/static/js/home/subscriptions.js @@ -11,6 +11,7 @@ async function initSubscriptionTable() { subTable = $("#subTable").DataTable({ info: false, paging: false, + ordering: false, searching: false, autoWidth: false, order: [], @@ -60,18 +61,10 @@ async function initSubscriptionTable() { return `${data}`; } }, - // { - // title: "Content", - // data: "channels_count", - // render: function(data, type) { - - // } - // }, { title: "Created", data: "creation_datetime", render: function(data, type) { - // return new Date(data).toISOString().split("T")[0]; let dateTime = new Date(data); let dateTimeString = formatDate(dateTime); return $(` @@ -341,35 +334,37 @@ $("#subscriptionsTabPane").on("click", ".table-refresh-btn", async function() { loadSubscriptions(getCurrentlyActiveServer().guild_id); }); -async function loadSubscriptions(guildId, page=1, pageSize=null, search=null) { - - if (!guildId) +async function loadSubscriptions(guildId) { + if (!guildId) return; - if (!pageSize) - pageSize = $("#subTablePageSize").val(); - - if (!search) - search = $("#subscriptionsTabPane .table-searchbar").val(); + setTableFilter("subTable", "guild_id", guildId); $("#subscriptionsTabPane .table-del-btn").prop("disabled", true); clearExistingSubRows(); try { - const subscriptions = await getSubscriptions(guildId, page, pageSize, search); - subTable.rows.add(subscriptions.results).draw(false); - - updateTablePagination("#subscriptionsTabPane .table-pagination", page, pageSize, subscriptions.count, subscriptions.next, subscriptions.previous); - updateTablePaginationInfo("#subscriptionsTabPane .table-page-info", subscriptions.results.length, subscriptions.count); - - $("#subTable thead .table-select-all").prop("disabled", subscriptions.results.length === 0); - console.debug("loading subs, " + subscriptions.results.length + " found"); + alert(JSON.stringify(tableFilters["subTable"], null, 4)) + var subs = await getSubscriptions(tableFilters["subTable"], tableSorts["subTable"]); + subTable.rows.add(subs.results).draw(false); } catch (err) { console.error(err) - console.error(JSON.stringify(err, null, 4)); - showToast("danger", `Error Loading Subscriptions: HTTP ${err.status}`, err.responseJSON.message, 15000); + showToast("danger", `Error Loading Subscriptions: HTTP ${err.status}`, err, 15000); + return; } + + updateTableContainer( + 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 diff --git a/apps/static/js/table.js b/apps/static/js/table.js index 61341ee..d5bd0c5 100644 --- a/apps/static/js/table.js +++ b/apps/static/js/table.js @@ -1,4 +1,23 @@ var timeouts = {}; + tableFilters = {}; + tableSorts = {}; + +$(document).on("selectedServerChange", async function() { + // Clear filters and sorts when changing server + tableFilters = {}; + tableSorts = {}; +}) + +function setTableFilter(tableId, key, value) { + if (!tableFilters[tableId]) + tableFilters[tableId] = {} + + tableFilters[tableId][key] = value; +} + +function setTableSorts(tableId, value) { + tableSorts[tableId] = value; +} async function initTable(containingSelector, tableId, loadDataFunc, newRowFunc, deleteSelectedFunc, options=null) { let pageSizeId = tableId + "PageSize"; @@ -10,11 +29,11 @@ async function initTable(containingSelector, tableId, loadDataFunc, newRowFunc, createTable(containingSelector, tableId); createTableControls(containingSelector, pageSizeId); - await bindSearchBar(searchId, loadDataFunc); - // await bindSortDropdown(sortDropdownId, loadDataFunc); - await bindFilterDropdown(filterDropdownId, loadDataFunc); - await bindTablePagination(`${containingSelector} .table-pagination`, loadDataFunc); - await bindTablePaginationResizer(`${containingSelector} .table-page-sizer`, loadDataFunc); + await bindSearchBar(tableId, searchId, loadDataFunc); + await bindSortDropdown(tableId, sortDropdownId, loadDataFunc); + await bindFilterDropdown(tableId, filterDropdownId, loadDataFunc); + await bindTablePagination(tableId, `${containingSelector} .table-pagination`, loadDataFunc); + await bindTablePaginationResizer(tableId, `${containingSelector} .table-page-sizer`, loadDataFunc); } function createSearchRow(containingSelector, searchId, sortDropdownId, filterDropdownId, options, newRowFunc, deleteSelectedFunc) { @@ -38,6 +57,7 @@ function createSearchRow(containingSelector, searchId, sortDropdownId, filterDro `); + // If there is a function that allows the creation of new rows, create a button for it if (newRowFunc) { $(`${containingSelector} .table-search-row .table-search-buttons`).prepend(`
@@ -49,6 +69,7 @@ function createSearchRow(containingSelector, searchId, sortDropdownId, filterDro $(`${containingSelector} .table-search-row .table-search-buttons .table-new-btn`).on("click", async () => {await newRowFunc(-1)}); } + // Show the sort dropdown if (options.sort) { $(`${containingSelector} .table-search-row .table-search-buttons`).append(`
@@ -66,6 +87,7 @@ function createSearchRow(containingSelector, searchId, sortDropdownId, filterDro // bindSortDropdown(sortDropdownId); } + // Show the filters dropdown if (options.filter && options.actions.GET) { $(`${containingSelector} .table-search-row .table-search-buttons`).append(`
@@ -82,6 +104,7 @@ function createSearchRow(containingSelector, searchId, sortDropdownId, filterDro populateFilterDropdown(filterDropdownId, options.actions.GET, options.filter); } + // If there is a function for deleting selected rows, create a button for it if (deleteSelectedFunc) { $(`${containingSelector} .table-search-row .table-search-buttons`).append(`
@@ -143,11 +166,18 @@ function populateFilterDropdown(filterDropdownId, options, filterKeys) { $(`#${filterDropdownId} .dropdown-menu`).append($("
  • ").append($elem)); } + + // Reset the controls + $(document).on("selectedServerChange", async function() { + $(`#${filterDropdownId} .dropdown-menu input[type="checkbox"]`).each(function() { + $(this).data("state", null); + updateCheckboxState($(this).parent()); + }); + }); } function bindFilterBoolean($elem) { - $elem.find('label').on("click", function(event) { - event.preventDefault(); + $elem.find('label').on("click", function() { let $input = $elem.find('input[type="checkbox"]'); let state = $input.data("state"); @@ -190,20 +220,29 @@ function updateCheckboxState($elem) { } } -async function bindSearchBar(searchBarSelector, loadDataFunc) { +async function bindSearchBar(tableId, searchBarSelector, loadDataFunc) { searchBar = $("#" + searchBarSelector) searchBar.on("input", async function() { clearTimeout(timeouts[searchBarSelector]); var searchString = $(this).val(); + setTableFilter(tableId, "search", searchString); timeouts[searchBarSelector] = setTimeout(async function() { - await loadDataFunc(getCurrentlyActiveServer().guild_id, 1, null, searchString); + await loadDataFunc(getCurrentlyActiveServer().guild_id); }, 300); }); } -async function bindFilterDropdown(filterDropdownId, loadDataFunc) { - $(`#${filterDropdownId} input`).on("change", function() { - alert($(this).attr("data-key")); +async function bindFilterDropdown(tableId, filterDropdownId, loadDataFunc) { + $(`#${filterDropdownId} .dropdown-menu`).on("change", "input", async function() { + setTableFilter(tableId, $(this).attr("data-key"), $(this).data("state")); + await loadDataFunc(getCurrentlyActiveServer().guild_id); + }); +} + +async function bindSortDropdown(tableId, sortDropdownId, loadDataFunc) { + $(`#${sortDropdownId} .dropdown-menu`).on("click", "button", async function() { + setTableSorts(tableId, $(this).attr("data-sortkey")) + await loadDataFunc(getCurrentlyActiveServer().guild_id); }); } @@ -259,6 +298,11 @@ function createTableControls(containingSelector, pageSizeId) { }); } +function updateTableContainer(containerSelector, page, pageSize, itemsCount, totalItemsCount, nextExists, prevExists) { + updateTablePagination(containerSelector, page, pageSize, totalItemsCount, nextExists, prevExists); + updateTablePaginationInfo(containerSelector, itemsCount, totalItemsCount); +} + // Updates the pagination text for a given pageInfoId function updateTablePaginationInfo(pageInfoId, showing, total) { $(`${pageInfoId} .pageinfo-showing`).text(showing); @@ -345,7 +389,7 @@ function addEllipsis(pageControlsId) { } // Bind the table pagination buttons to control the table pagination -async function bindTablePagination(pageControlsId, dataLoadFunc) { +async function bindTablePagination(tableId, pageControlsId, dataLoadFunc) { $(`${pageControlsId} .pagination`).on("click", ".page-link", async function() { let wantedPage; let currentPage = parseInt($(pageControlsId).attr("data-page")); @@ -357,17 +401,18 @@ async function bindTablePagination(pageControlsId, dataLoadFunc) { else wantedPage = $(this).attr("data-page"); - await dataLoadFunc(getCurrentlyActiveServer().guild_id, wantedPage) + setTableFilter(tableId, "page", wantedPage); + await dataLoadFunc(getCurrentlyActiveServer().guild_id) }); } // Bind the table pagination page resizer control -async function bindTablePaginationResizer(resizerControlId, dataLoadFunc) { +async function bindTablePaginationResizer(tableId, resizerControlId, dataLoadFunc) { $(resizerControlId).on("change", async function() { - const page = 1; - const pageSize = $(this).val(); + setTableFilter(tableId, "page", 1); + setTableFilter(tableId, "page_size", $(this).val()); - await dataLoadFunc(getCurrentlyActiveServer().guild_id, page, pageSize); + await dataLoadFunc(getCurrentlyActiveServer().guild_id); }); } diff --git a/apps/templates/home/includes/settingstab.html b/apps/templates/home/includes/settingstab.html index 2b0ec81..4b004fa 100644 --- a/apps/templates/home/includes/settingstab.html +++ b/apps/templates/home/includes/settingstab.html @@ -2,7 +2,7 @@
    - +
    @@ -27,17 +27,4 @@
  • - \ No newline at end of file