").addClass("px-6 py-4");
- const badge = $("
").addClass("py-1 px-2 inline-flex items-center text-xs font-medium rounded-full");
- const label = $("");
-
- if (data) {
- badge.addClass("bg-teal-100 text-teal-800 dark:bg-teal-500/10 dark:text-teal-500");
- badge.append(label.text("Whitelist"));
- } else {
- badge.addClass("bg-red-100 text-red-800 dark:bg-red-500/10 dark:text-red-500");
- badge.append(label.text("Blacklist"));
+ if (data) {
+ badge.text("Whitelist");
+ badge.addClass("bg-teal-100 text-teal-800 dark:bg-teal-500/10 dark:text-teal-500");
+ } else {
+ badge.text("Blacklist");
+ badge.addClass("bg-red-100 text-red-800 dark:bg-red-500/10 dark:text-red-500");
+ }
+
+ wrapper.append(badge);
+ return wrapper.get(0);
}
-
- wrapper.append(badge);
- return wrapper.get(0);
- }
- },
- {
- target: 6,
- data: "created_at",
- orderable: true,
- searchable: false,
- render: (data: string) => { return `
-
+ },
+ {
+ target: 6,
+ data: "created_at",
+ orderable: true,
+ searchable: false,
+ className: "size-px whitespace-nowrap",
+ render: (data: string) => { return `
${formatTimestamp(data)}
- |
- `}
- }
+ `}
+ },
+
];
const ajaxSettings: AjaxSettings = {
- url: `/guild/${1204426362794811453}/filters/api/datatable`,
+ url: `/guild/${guildId}/filters/api/datatable`,
type: "POST",
contentType: "application/json",
dataSrc: "data",
@@ -202,6 +179,10 @@ const tableOptions: IDataTableOptions = {
ajax: ajaxSettings,
serverSide: true,
processing: true,
+ select: {
+ style: "multi",
+ selector: "td:first-child input[type='checkbox']"
+ },
columnDefs: columnDefs,
pagingOptions: { pageBtnClasses: "hidden" },
rowSelectingOptions: { selectAllSelector: "#selectAllBox" },
@@ -210,20 +191,60 @@ const tableOptions: IDataTableOptions = {
emptyTable: emptyTableHtml,
loadingRecords: "Placeholder loading message..."
},
+ drawCallback: () => HSDropdown.autoInit(),
rowCallback: (row: HTMLTableRowElement) => {
$(row).addClass("bg-white dark:bg-neutral-900");
}
};
-const table: HSDataTable = new HSDataTable(
- $("#table").get(0),
+const table = new HSDataTable(
+ $("#table").get(0) as HTMLElement,
tableOptions
-);
+)
+
+const onTableSelectChange = () => {
+ const selectedRowsCount = (table as any).dataTable.rows({ selected: true }).count();
+ $("#deleteRowsBtn").prop("disabled", selectedRowsCount === 0);
+ $(".rows-selected-count-js").text(selectedRowsCount);
+
+ const $elem = $(".rows-selected-count-js.zero-empty-js");
+ selectedRowsCount === 0 ? $elem.hide() : $elem.show();
+};
+
+(table as any).dataTable
+ .on("select", onTableSelectChange)
+ .on("deselect", onTableSelectChange)
+ .on("draw", onTableSelectChange);
+
+$("#selectAllBox").on("change", function() {
+ (this as HTMLInputElement).checked
+ ? (table as any).dataTable.rows().select()
+ : (table as any).dataTable.rows().deselect();
+});
+
+$("#deleteRowsBtn").on("click", async () => {
+ const dt: Api = (table as any).dataTable;
+ const rowsData = dt.rows({ selected: true }).data().toArray();
+ const rowIds = rowsData.map((row: prisma.Filter) => row.id);
+
+ await $.ajax({
+ url: `/guild/${guildId}/filters/api`,
+ method: "delete",
+ dataType: "json",
+ data: { ids: rowIds },
+ success: () => {
+ dt.draw();
+ dt.rows().deselect();
+ },
+ error: error => {
+ alert(typeof error === "object" ? JSON.stringify(error, null, 4) : error);
+ }
+ });
+});
// #endregion
// #region Page Size Select
-// https://preline.co/plugins/html/advanced-select.html
(window as any).$hsSelectCollection = [];
(window as any)["FloatingUIDOM"] = {
@@ -232,13 +253,19 @@ const table: HSDataTable = new HSDataTable(
offset: offset
};
+// Close on click.
+window.addEventListener('click', (evt) => {
+ const evtTarget = evt.target;
+ HSSelect.closeCurrentlyOpened(evtTarget as HTMLElement);
+});
+
const pageSelectOptions: ISelectOptions = {
- toggleTag: "
",
+ toggleTag: '
',
optionTemplate: `
-
+
`,
toggleClasses: "cj-table-paging-select-toggle",
@@ -251,8 +278,134 @@ const pageSelectOptions: ISelectOptions = {
};
const pageSizeSelect: HSSelect = new HSSelect(
- $("#selectPageSize-js").get(0),
+ $("#selectPageSize-js").get(0) as HTMLElement,
pageSelectOptions
);
+// #endregion
+
+// #region Edit Modal
+
+(window as any).$hsOverlayCollection = [];
+
+const editModalOptions: IOverlayOptions = {};
+
+const editModal: HSOverlay = new HSOverlay(
+ $("#editModal").get(0) as HTMLElement,
+ editModalOptions
+);
+
+$(document).on("click", ".open-edit-modal-js", async event => {
+ await openEditModal($(event.target).data("id"));
+});
+
+const clearEditModalData = () => {
+ $(editModal.el).removeData("id");
+
+ $("#formName").val("");
+ $("#formValue").val("");
+ $("#formInsensitive").prop("checked", false);
+ $("#formWhitelist").prop("checked", false);
+
+ algorithmSelect.setValue("");
+};
+
+const loadEditModalData = async (id: number) => {
+ const filter: prisma.Filter = await $.ajax({
+ url: `/guild/${guildId}/filters/api?id=${id}`,
+ method: "get"
+ });
+
+ $(editModal.el).data("id", filter.id);
+
+ $("#formName").val(filter.name);
+ $("#formValue").val(filter.value);
+ $("#formInsensitive").prop("checked", filter.is_insensitive);
+ $("#formWhitelist").prop("checked", filter.is_whitelist);
+
+ // BUG:
+ // Breaks the appearance & functionality of the select
+ algorithmSelect.setValue(filter.matching_algorithm);
+}
+
+const openEditModal = async (id: number | undefined) => {
+ $("#editForm").removeClass("submitted");
+ editModal.open();
+
+ id === undefined
+ ? clearEditModalData()
+ : loadEditModalData(id);
+};
+
+const closeEditModal = () => {
+ editModal.close();
+};
+
+const algorithmSelectOptions: ISelectOptions = {
+ toggleTag: '
',
+ optionTemplate: `
+
`,
+ toggleClasses: "cj-select-toggle select-input",
+ optionClasses: "cj-select-option",
+ dropdownClasses: "cj-select-dropdown",
+ wrapperClasses: "peer",
+ dropdownSpace: 10,
+ dropdownScope: "parent",
+ dropdownPlacement: "top",
+ dropdownVerticalFixedPlacement: null
+};
+
+const algorithmSelect = new HSSelect(
+ $("#formAlgorithm").get(0),
+ algorithmSelectOptions
+);
+
+// Add options to algorithm select
+Object.entries(matchingAlgorithms).forEach(([key, description]) => {
+ algorithmSelect.addOption({
+ title: description,
+ val: key
+ } as ISingleOption)
+})
+
+$("#editForm").on("submit", async event => {
+ event.preventDefault();
+
+ const form = $(event.target).get(0) as HTMLFormElement;
+ $(form).addClass("submitted");
+
+ if (!form.checkValidity()) return;
+
+ let method = "post";
+ const data = $(event.target).serializeArray();
+ const id: number | undefined = $(editModal.el).data("id");
+
+ if (id !== undefined) {
+ data.push({
+ name: "id",
+ value: `${id}`
+ })
+ method = "patch";
+ }
+
+ await $.ajax({
+ url: `/guild/${guildId}/filters/api`,
+ dataType: "json",
+ method: method,
+ data: data,
+ success: () => {
+ (table as any).dataTable.draw();
+ closeEditModal();
+ },
+ error: error => {
+ alert(JSON.stringify(error, null, 4));
+ }
+ });
+});
+
// #endregion
\ No newline at end of file
diff --git a/src/client/views/guild/filters.ejs b/src/client/views/guild/filters.ejs
index 0cda4bf..ec255c0 100644
--- a/src/client/views/guild/filters.ejs
+++ b/src/client/views/guild/filters.ejs
@@ -22,6 +22,13 @@
+
@@ -156,17 +142,72 @@