working on functionality and layout design
This commit is contained in:
parent
79384ff737
commit
12e358df29
@ -56,17 +56,23 @@
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
color: var(--bs-text-body);
|
||||
background-color: var(--bg-tertiary-bg);
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.server-item-selector:hover {
|
||||
.server-item-selector .font-monospace {
|
||||
color: var(--bs-secondary-color)
|
||||
}
|
||||
|
||||
.server-item-selector:hover,
|
||||
.server-item-selector:focus,
|
||||
.server-item-selector:active,
|
||||
.server-item-selector.active {
|
||||
background-color: var(--bs-tertiary-bg);
|
||||
}
|
||||
|
||||
.server-item-selector:active, .server-item-selector.active {
|
||||
background-color: var(--bs-tertiary-bg) !important;
|
||||
}
|
||||
|
||||
|
||||
/* widths */
|
||||
|
||||
|
@ -25,6 +25,18 @@ td > .btn-link { padding-left: 0; }
|
||||
}
|
||||
|
||||
|
||||
/* Empty Table */
|
||||
|
||||
.table .dt-empty {
|
||||
padding: 2rem 0;
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.table tr:hover > .dt-empty {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* Table Search */
|
||||
|
||||
.table-search-group {
|
||||
@ -76,3 +88,31 @@ td > .btn-link { padding-left: 0; }
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/* Button Controls */
|
||||
|
||||
.table-search-buttons > div {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.table-search-buttons > div {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.table-search-buttons > div:first-of-type {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
/* Table Border Colour */
|
||||
|
||||
table.dataTable > thead > tr > th, table.dataTable > thead > tr > td {
|
||||
border-bottom: 1px solid var(--bs-border-color);
|
||||
}
|
||||
|
||||
div.dt-container.dt-empty-footer tbody > tr:last-child > * {
|
||||
border-bottom: 1px solid var(--bs-border-color);
|
||||
}
|
@ -9,6 +9,9 @@ function initializeDataTable(tableId, columns) {
|
||||
searching: false,
|
||||
autoWidth: false,
|
||||
order: [],
|
||||
language: {
|
||||
emptyTable: "No results found"
|
||||
},
|
||||
select: {
|
||||
style: "multi+shift",
|
||||
selector: 'th:first-child input[type="checkbox"]'
|
||||
@ -39,6 +42,7 @@ function initializeDataTable(tableId, columns) {
|
||||
bindTablePageSizer(tableId);
|
||||
bindTableSearch(tableId);
|
||||
bindRefreshButton(tableId);
|
||||
bindDeleteButton(tableId);
|
||||
bindTableSelectColumn(tableId);
|
||||
}
|
||||
|
||||
@ -263,12 +267,19 @@ function bindTableSearch(tableId) {
|
||||
// region Button Controls
|
||||
|
||||
function bindRefreshButton(tableId) {
|
||||
let $tableFilters = $(tableId).closest('.js-tableBody').siblings('.js-tableFilters');
|
||||
const $tableFilters = $(tableId).closest('.js-tableBody').siblings('.js-tableFilters');
|
||||
$tableFilters.on("click", ".table-refresh-btn", function() {
|
||||
$(tableId).trigger("doDataLoad");
|
||||
})
|
||||
}
|
||||
|
||||
function bindDeleteButton(tableId) {
|
||||
const $tableFilters = $(tableId).closest(".js-tableBody").siblings(".js-tableFilters");
|
||||
$tableFilters.on("click", ".table-del-btn", function() {
|
||||
alert("delete");
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// region Select Checkboxes
|
||||
|
||||
@ -395,9 +406,53 @@ async function loadModalData($modal, url) {
|
||||
});
|
||||
}
|
||||
|
||||
async function onModalSubmit($modal, $table, url) {
|
||||
if (!selectedServer) {
|
||||
return;
|
||||
}
|
||||
|
||||
let data = { server: selectedServer.id };
|
||||
|
||||
$modal.find("[data-field]").each(function() {
|
||||
const type = $(this).attr("type");
|
||||
const key = $(this).attr("data-field");
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value;
|
||||
if (type === "checkbox") {
|
||||
value = $(this).prop("checked");
|
||||
}
|
||||
else {
|
||||
value = $(this).val();
|
||||
}
|
||||
|
||||
data[key] = value;
|
||||
});
|
||||
|
||||
const formData = objectToFormData(data);
|
||||
const id = $modal.data("primary-key");
|
||||
const isNewItem = parseInt(id) !== -1;
|
||||
const method = isNewItem ? "PATCH" : "POST";
|
||||
url = isNewItem ? url + `${id}/` : url;
|
||||
|
||||
ajaxRequest(url, method, formData)
|
||||
.then(response => {
|
||||
$modal.modal("hide");
|
||||
$table.trigger("doDataLoad");
|
||||
})
|
||||
.catch(error => logError(error));
|
||||
}
|
||||
|
||||
|
||||
// region Table Column Types
|
||||
|
||||
function renderEditColumn(data) {
|
||||
const name = sanitise(data);
|
||||
return `<button type="button" class="btn btn-link text-start text-decoration-none edit-modal">${name}</button>`;
|
||||
}
|
||||
|
||||
function renderBooleanColumn(data) {
|
||||
const iconClass = data ? "bi-check-circle-fill text-success" : "bi-x-circle-fill text-danger";
|
||||
return `<i class="bi ${iconClass}"></i>`;
|
||||
|
@ -10,7 +10,8 @@ function initFiltersModule() {
|
||||
[
|
||||
{
|
||||
title: "Name",
|
||||
data: "name"
|
||||
data: "name",
|
||||
render: renderEditColumn
|
||||
},
|
||||
{
|
||||
title: "Match",
|
||||
@ -79,3 +80,32 @@ $(filterTableId).on("click", ".edit-modal", async function() {
|
||||
const id = $(filterTableId).DataTable().row($(this).closest("tr")).data().id;
|
||||
await openDataModal(filterModalId, id, `/api/filters/${id}/`);
|
||||
});
|
||||
|
||||
$(filterModalId).on("submit", async function(event) {
|
||||
event.preventDefault();
|
||||
await onModalSubmit(
|
||||
$(filterModalId),
|
||||
$(filterTableId),
|
||||
"/api/filters/"
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// region Load Modal Options
|
||||
|
||||
$(document).ready(async function() {
|
||||
await loadMatchingAlgorithms();
|
||||
});
|
||||
|
||||
async function loadMatchingAlgorithms() {
|
||||
const data = await ajaxRequest("/api/filters/", "OPTIONS");
|
||||
data.actions.GET.matching_algorithm.choices.forEach(algorithm => {
|
||||
$(filterModalId).find('[data-field="matching_algorithm"]').append($(
|
||||
"<option>",
|
||||
{
|
||||
text: algorithm.display_name,
|
||||
value: algorithm.value > 0 ? algorithm.value : ""
|
||||
}
|
||||
));
|
||||
});
|
||||
}
|
||||
|
@ -11,10 +11,7 @@ function initMessageStylesModule() {
|
||||
{
|
||||
title: "Name",
|
||||
data: "name",
|
||||
render: function(data) {
|
||||
const name = sanitise(data);
|
||||
return `<button type="button" class="btn btn-link text-start text-decoration-none edit-modal">${name}</button>`;
|
||||
}
|
||||
render: renderEditColumn
|
||||
},
|
||||
{
|
||||
title: "Is Embed",
|
||||
@ -98,50 +95,11 @@ $(styleTableId).on("click", ".edit-modal", async function() {
|
||||
|
||||
$(styleModalId).on("submit", async function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!selectedServer) {
|
||||
throw new Error("Cannot submit form while no server is selected");
|
||||
}
|
||||
|
||||
let data = { server: selectedServer.id };
|
||||
|
||||
$(this).find("[data-field]").each(function() {
|
||||
const type = $(this).attr("type");
|
||||
const key = $(this).attr("data-field");
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value;
|
||||
if (type === "checkbox") {
|
||||
value = $(this).prop("checked");
|
||||
}
|
||||
else {
|
||||
value = $(this).val();
|
||||
}
|
||||
|
||||
data[key] = value;
|
||||
});
|
||||
|
||||
const formData = objectToFormData(data);
|
||||
const id = $(this).data("primary-key");
|
||||
|
||||
if (parseInt(id) !== -1) {
|
||||
ajaxRequest(`/api/message-styles/${id}/`, "PATCH", formData)
|
||||
.then(response => {
|
||||
$(this).modal("hide");
|
||||
$(styleTableId).trigger("doDataLoad");
|
||||
})
|
||||
.catch(error => logError(error))
|
||||
}
|
||||
else {
|
||||
ajaxRequest("/api/message-styles/", "POST", formData)
|
||||
.then(response => {
|
||||
$(this).modal("hide");
|
||||
$(styleTableId).trigger("doDataLoad");
|
||||
})
|
||||
.catch(error => logError(error));
|
||||
}
|
||||
await onModalSubmit(
|
||||
$(styleModalId),
|
||||
$(styleTableId),
|
||||
"/api/message-styles/"
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
@ -13,10 +13,7 @@ function initSubscriptionsModule() {
|
||||
title: "Name",
|
||||
data: "name",
|
||||
className: "text-truncate col-3",
|
||||
render: function(data, type, row) {
|
||||
const name = sanitise(data);
|
||||
return `<button type="button" class="btn btn-link text-start text-decoration-none edit-modal">${name}</button>`;
|
||||
}
|
||||
render: renderEditColumn
|
||||
},
|
||||
{
|
||||
title: "URL",
|
||||
@ -112,56 +109,17 @@ $(subTableId).closest('.js-tableBody').siblings('.js-tableFilters').on("click",
|
||||
});
|
||||
|
||||
$(subTableId).on("click", ".edit-modal", async function() {
|
||||
let id = $(subTableId).DataTable().row($(this).closest("tr")).data().id;
|
||||
const id = $(subTableId).DataTable().row($(this).closest("tr")).data().id;
|
||||
await openDataModal(subModalId, id, `/api/subscriptions/${id}/`);
|
||||
})
|
||||
|
||||
$(subModalId).on("submit", async function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!selectedServer) {
|
||||
throw new Error("Cannot submit form while no server is selected");
|
||||
}
|
||||
|
||||
let data = { server: selectedServer.id };
|
||||
|
||||
$(this).find("[data-field]").each(function() {
|
||||
const type = $(this).attr("type");
|
||||
const key = $(this).attr("data-field");
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value;
|
||||
if (type === "checkbox") {
|
||||
value = $(this).prop("checked");
|
||||
}
|
||||
else {
|
||||
value = $(this).val();
|
||||
}
|
||||
|
||||
data[key] = value;
|
||||
});
|
||||
|
||||
const formData = objectToFormData(data);
|
||||
const id = $(this).data("primary-key");
|
||||
|
||||
if (parseInt(id) !== -1) {
|
||||
ajaxRequest(`/api/subscriptions/${id}/`, "PATCH", formData)
|
||||
.then(response => {
|
||||
$(this).modal("hide");
|
||||
$(subTableId).trigger("doDataLoad");
|
||||
})
|
||||
.catch(error => logError(error))
|
||||
}
|
||||
else {
|
||||
ajaxRequest("/api/subscriptions/", "POST", formData)
|
||||
.then(response => {
|
||||
$(this).modal("hide");
|
||||
$(subTableId).trigger("doDataLoad");
|
||||
})
|
||||
.catch(error => logError(error));
|
||||
}
|
||||
await onModalSubmit(
|
||||
$(subModalId),
|
||||
$(subTableId),
|
||||
"/api/subscriptions/"
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
|
@ -80,31 +80,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="selectedServerContainer" class="row" style="display: none;">
|
||||
<div class="col-12 bg-body-tertiary px-4 py-3 py-sm-4">
|
||||
<div class="row d-none">
|
||||
<div class="col-sm-7 col-md-6 d-flex align-items-center d-none">
|
||||
<img alt="Server Icon" class="resolve-to-server-icon rounded-3 d-none d-sm-block">
|
||||
<div class="ms-sm-3" style="min-width: 0">
|
||||
<h3 class="mb-0 resolve-to-server-name text-truncate"></h3>
|
||||
<h5 class="mb-0 resolve-to-server-id text-truncate text-body-secondary text-monospace"></h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-5 col-md-6 d-flex justify-content-sm-end align-items-center d-none">
|
||||
<div class="mt-3 mt-sm-0">
|
||||
<button type="button" id="serverSettingsBtn" class="btn btn-outline-secondary rounded-1 me-3">
|
||||
<i class="bi bi-gear"></i>
|
||||
</button>
|
||||
<button type="button" id="deleteSelectedServerBtn" class="btn btn-outline-danger rounded-1">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
<button type="button" id="backToSelectServer" class="btn btn-outline-secondary rounded-1 ms-3">
|
||||
<i class="bi bi-box-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="serverJoinAlert" class="col-12 m-0">
|
||||
<div class="alert alert-warning rounded-1 px-sm-3 mt-2 mt-sm-4 mx-sm-2">
|
||||
<div class="row">
|
||||
@ -138,18 +113,18 @@
|
||||
Content Filters
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button id="contentTab" class="nav-link rounded-1" data-bs-toggle="tab" data-bs-target="#contentTabPane" type="button" aria-controls="contentTabPane" aria-selected="false">
|
||||
<i class="bi bi-archive me-2"></i>
|
||||
Tracked Content
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button id="stylesTab" class="nav-link rounded-1" data-bs-toggle="tab" data-bs-target="#stylesTabPane" type="button" aria-controls="stylesTabPane" aria-selected="false">
|
||||
<i class="bi bi-border-style me-2"></i>
|
||||
Message Styles
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button id="contentTab" class="nav-link rounded-1" data-bs-toggle="tab" data-bs-target="#contentTabPane" type="button" aria-controls="contentTabPane" aria-selected="false">
|
||||
<i class="bi bi-archive me-2"></i>
|
||||
Tracked Content
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item ms-auto">
|
||||
<div class="dropdown">
|
||||
<button class="nav-link rounded-1 dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
@ -157,7 +132,10 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<button type="button" class="dropdown-item">-- todo --</button>
|
||||
<button type="button" class="dropdown-item">Delete Server Data</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item">Exit Server View</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -173,12 +151,12 @@
|
||||
<div id="filtersTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="filtersTab" tabindex="0">
|
||||
{% include "home/tabs/filters.html" %}
|
||||
</div>
|
||||
<div id="contentTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="contentTab" tabindex="0">
|
||||
{% include "home/tabs/content.html" %}
|
||||
</div>
|
||||
<div id="stylesTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="stylesTab" tabindex="0">
|
||||
{% include "home/tabs/styles.html" %}
|
||||
</div>
|
||||
<div id="contentTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="contentTab" tabindex="0">
|
||||
{% include "home/tabs/content.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -199,8 +177,8 @@
|
||||
<div class="d-flex justify-content-start align-items-center w-100">
|
||||
<img src="" alt="Guild Icon" class="rounded-1 small" width="45" height="45">
|
||||
<div class="server-item-labels small text-start ps-2 w-100 flex-shrink-1 overflow-hidden">
|
||||
<div class="js-guildName text-body fw-bold text-truncate"></div>
|
||||
<div class="js-guildId text-body-secondary text-truncate font-monospace"></div>
|
||||
<div class="js-guildName fw-bold text-truncate"></div>
|
||||
<div class="js-guildId text-truncate font-monospace"></div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
@ -7,6 +7,7 @@
|
||||
<h5 class="modal-title ms-2">
|
||||
<span class="form-create">Add</span>
|
||||
<span class="form-edit">Edit</span>
|
||||
Content Filter
|
||||
</h5>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
@ -14,38 +15,36 @@
|
||||
<div class="col-12">
|
||||
<div class="mb-4">
|
||||
<label for="filterName" class="form-label">Name</label>
|
||||
<input type="text" name="filterName" id="filterName" class="form-control" data-field="name" tabindex="1">
|
||||
<div class="form-text"></div>
|
||||
<input type="text" name="filterName" id="filterName" class="form-control rounded-1" data-field="name" tabindex="1">
|
||||
<div class="form-text">Human-readable name for this entry.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="mb-4">
|
||||
<label for="filterMatchingAlgorithm" class="form-label"></label>
|
||||
<select name="filterMatchingAlgorithm" id="filterMatchingAlgorithm" class="select-2" data-field="matching_algorithm" tabindex="2">
|
||||
<option value="">-----</option>
|
||||
</select>
|
||||
<div class="form-text"></div>
|
||||
<label for="filterMatchingAlgorithm" class="form-label">Matching Algorithm</label>
|
||||
<select name="filterMatchingAlgorithm" id="filterMatchingAlgorithm" class="select-2" data-dropdownparent="#filterFormModal" data-field="matching_algorithm" tabindex="2"></select>
|
||||
<div class="form-text">The algorithm used to match against.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="mb-4">
|
||||
<label for="filterMatch" class="form-label">Match</label>
|
||||
<input type="text" name="filterMatch" id="filterMatch" class="form-control" data-field="match" tabindex="3">
|
||||
<div class="form-text"></div>
|
||||
<input type="text" name="filterMatch" id="filterMatch" class="form-control rounded-1" data-field="match" tabindex="3">
|
||||
<div class="form-text">The value to match against.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch mb-4">
|
||||
<label for="filterIsInsensitive" class="form-check-label"></label>
|
||||
<label for="filterIsInsensitive" class="form-check-label">Case-Insensitive</label>
|
||||
<input type="checkbox" name="filterIsInsensitive" id="filterIsInsensitive" class="form-check-input" data-field="is_insensitive" tabindex="4">
|
||||
<div class="form-text"></div>
|
||||
<div class="form-text">Should case-sensitivity be ignored?</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch">
|
||||
<label for="filterIsWhitelist" class="form-check-label"></label>
|
||||
<label for="filterIsWhitelist" class="form-check-label">Whitelist Mode</label>
|
||||
<input type="checkbox" name="filterIsWhitelist" id="filterIsWhitelist" class="form-check-input" data-field="is_whitelist" tabindex="5">
|
||||
<div class="form-text"></div>
|
||||
<div class="form-text">Overrides the default blacklist behaviour.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -75,27 +75,3 @@
|
||||
.w-xxl-100 { width: 100%; }
|
||||
.w-xxl-auto { width: auto; }
|
||||
}
|
||||
|
||||
.table-search-buttons > div {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.table-search-buttons > div {
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.table-search-buttons > div:first-of-type {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
/* Table Border Colour */
|
||||
|
||||
table.dataTable > thead > tr > th, table.dataTable > thead > tr > td {
|
||||
border-bottom: 1px solid var(--bs-border-color) !important;
|
||||
}
|
||||
|
||||
div.dt-container.dt-empty-footer tbody > tr:last-child > * {
|
||||
border-bottom: 1px solid var(--bs-border-color) !important;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user