server side filters
This commit is contained in:
parent
dede2ee06e
commit
ae53457344
@ -917,6 +917,11 @@ video {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.mx-\[1px\] {
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
@ -1075,6 +1080,11 @@ video {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.size-16 {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
}
|
||||
|
||||
.size-2\.5 {
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
@ -1254,14 +1264,14 @@ video {
|
||||
min-width: 15rem;
|
||||
}
|
||||
|
||||
.min-w-\[40px\] {
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.min-w-full {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.max-w-\[120rem\] {
|
||||
max-width: 120rem;
|
||||
}
|
||||
|
||||
.max-w-\[28rem\] {
|
||||
max-width: 28rem;
|
||||
}
|
||||
@ -1286,6 +1296,10 @@ video {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@ -1396,6 +1410,10 @@ video {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.gap-5 {
|
||||
gap: 1.25rem;
|
||||
}
|
||||
|
||||
.gap-x-1 {
|
||||
-moz-column-gap: 0.25rem;
|
||||
column-gap: 0.25rem;
|
||||
@ -1525,6 +1543,10 @@ video {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.rounded-2xl {
|
||||
border-radius: 1rem;
|
||||
}
|
||||
|
||||
.rounded-full {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
@ -1587,6 +1609,10 @@ video {
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.border-none {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
.\!border-gray-200 {
|
||||
--tw-border-opacity: 1 !important;
|
||||
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1)) !important;
|
||||
@ -1774,6 +1800,10 @@ video {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.\!pb-1 {
|
||||
padding-bottom: 0.25rem !important;
|
||||
}
|
||||
|
||||
.pb-1 {
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
@ -1834,6 +1864,10 @@ video {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.pt-5 {
|
||||
padding-top: 1.25rem;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
@ -2449,6 +2483,16 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
inset-inline-start: 0px;
|
||||
}
|
||||
|
||||
.before\:top-0::before {
|
||||
content: var(--tw-content);
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.before\:-z-10::before {
|
||||
content: var(--tw-content);
|
||||
z-index: -10;
|
||||
}
|
||||
|
||||
.before\:z-\[1\]::before {
|
||||
content: var(--tw-content);
|
||||
z-index: 1;
|
||||
@ -2470,6 +2514,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.before\:h-\[200px\]::before {
|
||||
content: var(--tw-content);
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.before\:w-full::before {
|
||||
content: var(--tw-content);
|
||||
width: 100%;
|
||||
@ -2964,6 +3013,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.sm\:size-20 {
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
}
|
||||
|
||||
.sm\:grid-cols-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
@ -2972,6 +3026,10 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sm\:items-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sm\:gap-6 {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
@ -3001,6 +3059,10 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
|
||||
}
|
||||
|
||||
.sm\:rounded-3xl {
|
||||
border-radius: 1.5rem;
|
||||
}
|
||||
|
||||
.sm\:p-5 {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
@ -3100,6 +3162,11 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.md\:text-3xl {
|
||||
font-size: 1.875rem;
|
||||
line-height: 2.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
@ -3499,13 +3566,3 @@ hs-accordion-toggle w-full text-start flex items-center gap-x-3.5 py-2 px-2.5 te
|
||||
.\[\&\:\:-webkit-scrollbar\]\:w-2::-webkit-scrollbar {
|
||||
width: 0.5rem;
|
||||
}
|
||||
|
||||
.\[\&\>\.active\]\:bg-gray-100>.active {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.dark\:\[\&\>\.active\]\:bg-neutral-700>.active:where(.dark, .dark *) {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(64 64 64 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
// const { dataTable } = HSDataTable.getInstance("#table");
|
||||
|
||||
// // Filter by status
|
||||
// (function () {
|
||||
// const radioButtons = document.querySelectorAll('input[type="radio"][name="filter"]');
|
||||
// const { dataTable } = new HSDataTable('#table');
|
||||
|
||||
// dataTable.search.fixed('status', function (searchStr, data, index) {
|
||||
// const status = data[2].trim().toLowerCase(); // Adjust index based on your dataset
|
||||
@ -17,7 +18,6 @@
|
||||
// });
|
||||
// })();
|
||||
|
||||
// const { dataTable } = HSDataTable.getInstance("#table");
|
||||
|
||||
// dataTable.on("draw.dt", () => {
|
||||
// console.log("Table redrawn")
|
||||
@ -34,17 +34,24 @@ const formatTimestamp = timestamp => {
|
||||
: `${d.getDate()} ${d.toLocaleString("en-GB", { month: "short" })} ${d.getFullYear()}`;
|
||||
}
|
||||
|
||||
var table;
|
||||
const defineTable = () => {
|
||||
new HSDataTable("#table", {
|
||||
table = new HSDataTable("#table", {
|
||||
ajax: {
|
||||
url: `/guild/${guild}/subscriptions/api/datatable`,
|
||||
dataSrc: "data"
|
||||
dataSrc: "data",
|
||||
data: (d) => {
|
||||
d.filters = {};
|
||||
|
||||
const active = $("input[name='filterActive']:checked").val();
|
||||
d.filters.active = active;
|
||||
}
|
||||
},
|
||||
serverSide: true,
|
||||
processing: true,
|
||||
selecting: true,
|
||||
pagingOptions: {
|
||||
pageBtnClasses: "min-w-[40px] flex justify-center items-center text-gray-800 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 py-2.5 text-sm rounded-full disabled:opacity-50 disabled:pointer-events-none dark:text-white dark:focus:bg-neutral-700 dark:hover:bg-neutral-700"
|
||||
pageBtnClasses: "hidden"
|
||||
},
|
||||
rowSelectingOptions: {
|
||||
selectAllSelector: "#selectAllBox"
|
||||
@ -63,7 +70,7 @@ const defineTable = () => {
|
||||
</p>
|
||||
|
||||
<div class="mt-5 flex flex-col sm:flex-row gap-2">
|
||||
<button type="button" class="openSubModal-js py-2 px-3 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
|
||||
<button type="button" class="openSubModal-js py-2 px-3 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#subModal">
|
||||
<svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
|
||||
Create a subscription
|
||||
</button>
|
||||
@ -135,9 +142,9 @@ const defineTable = () => {
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
render: (data, type, row) => {
|
||||
// ${data.length} channels
|
||||
return `
|
||||
<span class="block px-6 py-4 text-nowrap">
|
||||
${data.length} channels
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
@ -226,7 +233,6 @@ $(window).ready(() => {
|
||||
|
||||
const submitForm = async event => {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData($("#subForm"));
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<nav class="bg-white dark:bg-neutral-900 border dark:border-none m-4 sm:m-6 !mb-0 rounded-md">
|
||||
<!-- <nav class="bg-white dark:bg-neutral-900 border dark:border-none m-4 sm:m-6 !mb-0 rounded-md">
|
||||
<div class="w-full mx-auto md:flex md:flex-row md:justify-between md:items-center sm:gap-x-3 py-3 sm:py-5 px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex justify-between items-center gap-x-3">
|
||||
<div class="grow flex items-center gap-x-4">
|
||||
@ -34,4 +34,58 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</nav> -->
|
||||
|
||||
<!-- bg-neutral-100 dark:bg-neutral-900 -->
|
||||
<div class="max-w-[120rem]">
|
||||
<div class="relative pt-5 before:w-full before:h-[200px] before:-z-10 before:top-0 before:start-0 before:absolute">
|
||||
<div class="flex sm:items-center gap-5 p-4 sm:p-6 !pb-1">
|
||||
|
||||
<div class="flex-shrink-0">
|
||||
<div class="relative">
|
||||
<% if (guild.icon) { %>
|
||||
<img src="<%= guild.iconURL() %>" class="rounded-2xl sm:rounded-3xl size-16 sm:size-20" alt="">
|
||||
<% } else { %>
|
||||
<div class="size-16 sm:size-20 rounded-2xl sm:rounded-3xl flex shrink-0 justify-center items-center bg-white dark:bg-neutral-800">
|
||||
<span class="text-2xl"><%= guild.nameAcronym %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grow">
|
||||
<h1 class="text-2xl md:text-3xl font-semibold text-gray-800 dark:text-neutral-200">
|
||||
<%= guild.name %>
|
||||
</h1>
|
||||
<ul class="flex flex-wrap items-center gap-3 mt-2">
|
||||
<li class="relative">
|
||||
<span class="text-sm">ID:</span>
|
||||
<span class="text-sm inline-flex items-center gap-2 text-gray-800 dark:text-neutral-200"><%= guild.id %></span>
|
||||
</li>
|
||||
<li class="relative">
|
||||
<span class="text-sm">Members:</span>
|
||||
<span class="text-sm inline-flex items-center gap-2 text-gray-800 dark:text-neutral-200"><%= guild.memberCount %></span>
|
||||
</li>
|
||||
<li class="relative">
|
||||
<span class="text-sm">Channels:</span>
|
||||
<span class="text-sm inline-flex items-center gap-2 text-gray-800 dark:text-neutral-200"><%= guild.channels.channelCountWithoutThreads %></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center items-center mx-auto p-4 sm:p-6">
|
||||
<div class="flex flex-row w-full pb-1 whitespace-nowrap overflow-x-auto overflow-y-hidden">
|
||||
<!-- <a href="/guild/<%= guild.id %>" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 <%= !isNaN(+guildPage) ? 'bg-white dark:bg-neutral-800 dark:!border-neutral-700 border shadow-sm' : 'mx-[1px]' %>">Overview</a> -->
|
||||
<a href="/guild/<%= guild.id %>/subscriptions" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 <%= guildPage === 'subscriptions' ? 'bg-white dark:bg-neutral-800 dark:!border-neutral-700 border shadow-sm' : 'mx-[1px]' %>">Subscriptions</a>
|
||||
<a href="/guild/<%= guild.id %>/filters" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 <%= guildPage === 'filters' ? 'bg-white dark:bg-neutral-800 dark:!border-neutral-700 border shadow-sm' : 'mx-[1px]' %>">Filters</a>
|
||||
<a href="/guild/<%= guild.id %>/styles" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 <%= guildPage === 'styles' ? 'bg-white dark:bg-neutral-800 dark:!border-neutral-700 border shadow-sm' : 'mx-[1px]' %>">Styles</a>
|
||||
<a href="/guild/<%= guild.id %>/content" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 <%= guildPage === 'content' ? 'bg-white dark:bg-neutral-800 dark:!border-neutral-700 border shadow-sm' : 'mx-[1px]' %>">Content</a>
|
||||
<a href="#" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400">Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -2,23 +2,15 @@
|
||||
|
||||
<%- include("guildHeader") -%>
|
||||
|
||||
<div class="flex flex-col justify-center items-center mx-auto px-4 sm:px-6">
|
||||
<div class="flex flex-row w-full pb-1 whitespace-nowrap overflow-x-auto overflow-y-hidden">
|
||||
<a href="#" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400 bg-white dark:bg-neutral-800 dark:!border-neutral-700 border shadow-sm">Subscriptions</a>
|
||||
<a href="#" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400">Filters</a>
|
||||
<a href="#" class="inline-flex items-center gap-2 whitespace-nowrap rounded-md px-3 py-2 text-sm text-gray-800 dark:text-neutral-200 dark:hover:text-neutral-400 dark:focus:text-neutral-400">Style</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table Section -->
|
||||
<div id="table" class="max-w-full overflow-hidden p-4 sm:p-6"> <!-- px-4 py-10 sm:px-6 lg:px-8 lg:py-14 -->
|
||||
<div id="table" class="--prevent-on-load-init max-w-full overflow-hidden px-4 sm:px-6"> <!-- px-4 py-10 sm:px-6 lg:px-8 lg:py-14 -->
|
||||
<!-- Card -->
|
||||
<div class="flex flex-col">
|
||||
<div class="-m-1.5">
|
||||
<div class="max-w-full p-1.5 min-w-full inline-block align-middle">
|
||||
<div class="bg-white border border-gray-200 rounded-md shadow-sm overflow-hidden dark:bg-neutral-900 dark:border-neutral-700">
|
||||
<!-- Header -->
|
||||
<div class="px-6 py-4 gap-3 flex flex-nowrap justify-between items-center border-gray-200 dark:border-neutral-700">
|
||||
<div class="px-6 py-4 gap-3 flex flex-nowrap justify-between items-center border-b border-gray-200 dark:border-neutral-700">
|
||||
<!-- Input -->
|
||||
<div class="hidden sm:block sm:col-span-1">
|
||||
<label for="search" class="sr-only">Search</label>
|
||||
@ -53,22 +45,22 @@
|
||||
<div class="hs-dropdown-menu transition-[opacity,margin] duration hs-dropdown-open:opacity-100 opacity-0 hidden divide-y divide-gray-200 min-w-48 z-10 bg-white shadow-md rounded-md mt-2 dark:divide-neutral-700 dark:bg-neutral-800 dark:border dark:border-neutral-700" role="menu" aria-orientation="vertical" aria-labelledby="hs-as-table-table-filter-dropdown">
|
||||
<div class="divide-y divide-gray-200 dark:divide-neutral-700">
|
||||
<label for="hs-as-filters-dropdown-all" class="flex py-2.5 px-3">
|
||||
<input type="radio" name="filter" class="shrink-0 mt-0.5 border-gray-200 rounded-full text-blue-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800" id="hs-as-filters-dropdown-all" checked>
|
||||
<input type="radio" name="filterActive" class="shrink-0 mt-0.5 border-gray-200 rounded-full text-blue-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800" id="hs-as-filters-dropdown-all" checked value="1">
|
||||
<span class="ms-3 text-sm text-gray-800 dark:text-neutral-200">All</span>
|
||||
</label>
|
||||
<label for="hs-as-filters-dropdown-published" class="flex py-2.5 px-3">
|
||||
<input type="radio" name="filter" class="shrink-0 mt-0.5 border-gray-200 rounded-full text-blue-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800" id="hs-as-filters-dropdown-published">
|
||||
<span class="ms-3 text-sm text-gray-800 dark:text-neutral-200">Enabled</span>
|
||||
<input type="radio" name="filterActive" class="shrink-0 mt-0.5 border-gray-200 rounded-full text-blue-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800" id="hs-as-filters-dropdown-published" value="1">
|
||||
<span class="ms-3 text-sm text-gray-800 dark:text-neutral-200">Active</span>
|
||||
</label>
|
||||
<label for="hs-as-filters-dropdown-pending" class="flex py-2.5 px-3">
|
||||
<input type="radio" name="filter" class="shrink-0 mt-0.5 border-gray-200 rounded-full text-blue-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800" id="hs-as-filters-dropdown-pending">
|
||||
<span class="ms-3 text-sm text-gray-800 dark:text-neutral-200">Disabled</span>
|
||||
<input type="radio" name="filterActive" class="shrink-0 mt-0.5 border-gray-200 rounded-full text-blue-600 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:checked:bg-blue-500 dark:checked:border-blue-500 dark:focus:ring-offset-gray-800" id="hs-as-filters-dropdown-pending" value="0">
|
||||
<span class="ms-3 text-sm text-gray-800 dark:text-neutral-200">Inactive</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-md border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#hs-scale-animation-modal">
|
||||
<button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-md border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" data-hs-overlay="#subModal">
|
||||
<svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
|
||||
<span>
|
||||
Add
|
||||
@ -84,7 +76,7 @@
|
||||
<div class="min-w-full overflow-x-auto">
|
||||
<!-- Table -->
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-neutral-700">
|
||||
<thead class="bg-gray-50 dark:bg-neutral-800">
|
||||
<thead class="bg-gray-50 dark:bg-neutral-800 border-none">
|
||||
<tr>
|
||||
<th scope="col" class="ps-6 py-3 text-start --exclude-from-ordering">
|
||||
<label for="hs-at-with-checkboxes-main" class="flex ml-[1px]">
|
||||
@ -240,7 +232,7 @@
|
||||
<!-- End Table Section -->
|
||||
|
||||
<!-- Popup -->
|
||||
<div id="hs-scale-animation-modal" class="hs-overlay hidden size-full fixed top-0 start-0 z-[80] overflow-x-hidden overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-scale-animation-modal-label">
|
||||
<div id="subModal" class="hs-overlay hidden size-full fixed top-0 start-0 z-[80] overflow-x-hidden overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-scale-animation-modal-label">
|
||||
<div class="hs-overlay-animation-target hs-overlay-open:scale-100 hs-overlay-open:opacity-100 scale-95 opacity-0 ease-in-out transition-all duration-200 lg:max-w-4xl lg:w-full m-3 lg:mx-auto min-h-[calc(100%-3.5rem)] flex items-center">
|
||||
<div class="w-full p-4 sm:p-7 flex flex-col bg-white border shadow-sm rounded-md pointer-events-auto dark:bg-neutral-800 dark:border-neutral-700 dark:shadow-neutral-700/70">
|
||||
<div class="mb-8">
|
||||
@ -371,7 +363,7 @@
|
||||
<button type="button" class="me-auto py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-md border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700">
|
||||
Templates
|
||||
</button>
|
||||
<button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-md border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700" data-hs-overlay="#hs-scale-animation-modal">
|
||||
<button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-md border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 focus:outline-none focus:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-800 dark:border-neutral-700 dark:text-white dark:hover:bg-neutral-700 dark:focus:bg-neutral-700" data-hs-overlay="#subModal">
|
||||
Close
|
||||
</button>
|
||||
<button type="submit" form="subForm" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-md border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none">
|
||||
|
@ -3,17 +3,21 @@ import { client as bot } from "@bot/bot";
|
||||
|
||||
export const get = async (request: Request, response: Response) => {
|
||||
const guildId = request.params.guildId;
|
||||
const guild = bot.guilds.cache.get(guildId);
|
||||
|
||||
if (!guild) {
|
||||
response.status(404).send("404: guild not found");
|
||||
return;
|
||||
}
|
||||
response.redirect(`/guild/${guildId}/subscriptions`);
|
||||
return
|
||||
|
||||
response.render("guild/overview", {
|
||||
title: `${guild.name} - Relay`,
|
||||
guild: guild,
|
||||
});
|
||||
// const guild = bot.guilds.cache.get(guildId);
|
||||
|
||||
// if (!guild) {
|
||||
// response.status(404).send("404: guild not found");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// response.render("guild/overview", {
|
||||
// title: `${guild.name} - Relay`,
|
||||
// guild: guild,
|
||||
// });
|
||||
};
|
||||
|
||||
export default { get };
|
@ -1,39 +1,43 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { Request, Response } from "express";
|
||||
import { buildDatatableQuery } from "@utils/datatable";
|
||||
import { db } from "@db/db";
|
||||
import { client as bot } from "@bot/bot";
|
||||
|
||||
const isPostgres = db.client.config.client === "pg";
|
||||
const TABLE = "subscriptions";
|
||||
|
||||
export const datatable = async (request: Request, response: Response) => {
|
||||
try {
|
||||
const { query, recordsTotal, recordsFiltered } = await buildDatatableQuery(
|
||||
request as any,
|
||||
"subscriptions"
|
||||
);
|
||||
|
||||
query.select("subscriptions.*")
|
||||
.leftJoin("channels", "subscriptions.id", "=", "channels.subscription_id")
|
||||
.select(db.raw(isPostgres
|
||||
? "json_agg(channels.channel_id) as channels"
|
||||
:"JSON_GROUP_ARRAY(channels.channel_id) as channels"
|
||||
))
|
||||
.groupBy("subscriptions.id")
|
||||
let query = db(TABLE).where({ guild_id: request.params.guildId });
|
||||
// query.select("subscriptions.*")
|
||||
// .leftJoin("channels", "subscriptions.id", "=", "channels.subscription_id")
|
||||
// .select(db.raw(isPostgres
|
||||
// ? "json_agg(channels.channel_id) as channels"
|
||||
// :"JSON_GROUP_ARRAY(channels.channel_id) as channels"
|
||||
// ))
|
||||
// .groupBy("subscriptions.id")
|
||||
|
||||
const data = await query.where({ guild_id: request.params.guildId });
|
||||
const datatableQuery = await buildDatatableQuery(request as any, query, TABLE);
|
||||
const { recordsTotal, recordsFiltered } = datatableQuery;
|
||||
query = datatableQuery.query;
|
||||
|
||||
const data = await query;
|
||||
|
||||
data.forEach((item: any) => {
|
||||
item.channels = item.channels === "[null]"
|
||||
? []
|
||||
: JSON.parse(item.channels);
|
||||
console.log(`total: ${recordsTotal} filtered: ${recordsFiltered} filtered+paged: ${data.length}`);
|
||||
|
||||
// data.forEach((item: any) => {
|
||||
// item.channels = item.channels === "[null]"
|
||||
// ? []
|
||||
// : JSON.parse(item.channels);
|
||||
|
||||
// item.channels.forEach((channel: any) => {
|
||||
// channel = {
|
||||
// "channel_id": channel,
|
||||
// "name": bot.channels.cache.filter(a => a.id === id).first().name;
|
||||
// }
|
||||
// })
|
||||
});
|
||||
// // item.channels.forEach((channel: any) => {
|
||||
// // channel = {
|
||||
// // "channel_id": channel,
|
||||
// // "name": bot.channels.cache.filter(a => a.id === id).first().name;
|
||||
// // }
|
||||
// // })
|
||||
// });
|
||||
|
||||
response.json({
|
||||
data,
|
||||
|
@ -7,6 +7,7 @@ export interface RequestQuery {
|
||||
order: { column: string; dir: string }[];
|
||||
columns: { [key: string]: { data: string; searchable: string } };
|
||||
search: { value: string };
|
||||
filters: { [key: string]: any };
|
||||
}
|
||||
|
||||
export interface ResponseQuery {
|
||||
@ -15,7 +16,11 @@ export interface ResponseQuery {
|
||||
recordsFiltered: number | string;
|
||||
}
|
||||
|
||||
export const buildDatatableQuery = async (request: { query: RequestQuery }, tableName: string): Promise<ResponseQuery> => {
|
||||
type FilterConfig = {
|
||||
[key: string]: (value: any) => Knex.QueryBuilder;
|
||||
};
|
||||
|
||||
export const buildDatatableQuery = async (request: { query: RequestQuery }, query: Knex.QueryBuilder, tableName: string): Promise<ResponseQuery> => {
|
||||
const size: number = parseInt(request.query.length) || 10;
|
||||
const start: number = parseInt(request.query.start);
|
||||
const order: string = (
|
||||
@ -25,7 +30,18 @@ export const buildDatatableQuery = async (request: { query: RequestQuery }, tabl
|
||||
const direction: string = (request.query.order && request.query.order[0].dir) || "asc";
|
||||
const search: string = request.query.search.value;
|
||||
|
||||
let query = db(tableName);
|
||||
const filterConfig: FilterConfig = {
|
||||
active: (value: number) => query.where('active', '=', value),
|
||||
};
|
||||
|
||||
if (request.query.filters) {
|
||||
Object.keys(request.query.filters).forEach((filterName: any) => {
|
||||
const filterValue = request.query.filters[filterName];
|
||||
if (filterConfig[filterName] && filterValue) {
|
||||
query = filterConfig[filterName](filterValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (search) {
|
||||
console.log("applying search: " + search)
|
||||
@ -39,7 +55,6 @@ export const buildDatatableQuery = async (request: { query: RequestQuery }, tabl
|
||||
: builder.orWhere(`${tableName}.${col.data}`, "like", `%${search}%`)
|
||||
);
|
||||
});
|
||||
console.log(query.toSQL());
|
||||
}
|
||||
|
||||
const recordsTotalResult = await db(tableName).count("* as count").first();
|
||||
@ -48,6 +63,9 @@ export const buildDatatableQuery = async (request: { query: RequestQuery }, tabl
|
||||
const recordsFilteredResult = await query.clone().count("* as count").first();
|
||||
const recordsFiltered = recordsFilteredResult ? recordsFilteredResult.count : 0;
|
||||
|
||||
console.log(query.toSQL())
|
||||
console.log(query.clone().count("* as count").toSQL())
|
||||
|
||||
query = query.orderBy(`${tableName}.${order}`, direction).limit(size).offset(start);
|
||||
|
||||
return {
|
||||
|
Loading…
x
Reference in New Issue
Block a user