Skip to content

Made admin panel tables sortable and filterable #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions resources/templates/footer.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

</body>

<script src="<?php echo $CONFIG["site"]["prefix"]; ?>/js/filter.js"></script>
<script src="<?php echo $CONFIG["site"]["prefix"]; ?>/js/sort.js"></script>
<script src="<?php echo $CONFIG["site"]["prefix"]; ?>/js/global.js"></script>
<script src="<?php echo $CONFIG["site"]["prefix"]; ?>/js/tables.js"></script>

Expand Down
1 change: 1 addition & 0 deletions resources/templates/header.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<link rel="stylesheet" type="text/css" href="<?php echo $CONFIG["site"]["prefix"]; ?>/css/navbar.css">
<link rel="stylesheet" type="text/css" href="<?php echo $CONFIG["site"]["prefix"]; ?>/css/modal.css">
<link rel="stylesheet" type="text/css" href="<?php echo $CONFIG["site"]["prefix"]; ?>/css/tables.css">
<link rel="stylesheet" type="text/css" href="<?php echo $CONFIG["site"]["prefix"]; ?>/css/filters.css">

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="<?php echo $CONFIG["site"]["description"] ?>">
Expand Down
11 changes: 6 additions & 5 deletions webroot/admin/pi-mgmt.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
<h1>PI Management</h1>
<hr>

<input type="text" id="tableSearch" placeholder="Search...">
<!-- <input type="text" id="tableSearch" placeholder="Search..."> -->

<h5>Pending PI Requests</h5>
<table class="searchable">
Expand Down Expand Up @@ -104,11 +104,12 @@

<h5>List of PIs</h5>

<table class="searchable longTable">
<table class="searchable longTable sortable filterable">
<tr class="key">
<td>Name</td>
<td>Unity ID</td>
<td>Mail</td>
<input type="text" style="margin-right:5px;" placeholder="Filter by..." id="common-filter" class="filterSearch">
<td id="name"><span class="filter">⫧ </span>Name</td>
<td id="unityID"><span class="filter">⫧ </span>Unity ID</td>
<td id="mail"><span class="filter">⫧ </span>Mail</td>
<td>Actions</td>
</tr>

Expand Down
15 changes: 8 additions & 7 deletions webroot/admin/user-mgmt.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@
<h1>User Management</h1>
<hr>

<input type="text" id="tableSearch" placeholder="Search...">
<!-- <input type="text" id="tableSearch" placeholder="Search..."> -->

<table class="searchable longTable">
<table class="searchable longTable sortable filterable">
<tr class="key">
<td>Name</td>
<td>UID</td>
<td>Org</td>
<td>Mail</td>
<td>Groups</td>
<input type="text" style="margin-right:5px;" placeholder="Filter by..." id="common-filter" class="filterSearch">
<td id="name"><span class="filter">⫧ </span>Name</td>
<td id="uid"><span class="filter">⫧ </span>UID</td>
<td id="org"><span class="filter">⫧ </span>Org</td>
<td id="mail"><span class="filter">⫧ </span>Mail</td>
<td id="groups"><span class="filter">⫧ </span>Groups</td>
<td>Actions</td>
</tr>

Expand Down
15 changes: 15 additions & 0 deletions webroot/css/filters.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.filterSearch {
max-width: fit-content !important;
}

#uid-filter, #org-filter, #mail-filter, #groups-filter {
margin-right: 5px;
}

#name-filter, #unityID-filter {
margin-right: 100px;
}

.key td:hover {
cursor: pointer;
}
90 changes: 90 additions & 0 deletions webroot/js/filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");

if (pair[0] == variable) {
return pair[1];
}
}
return false;
}

function updateQueryStringParameter(uri, key, value) {
let currentURL = new URL(window.location.href);
let params = currentURL.searchParams;
if (params.has(key)) {
params.delete(key);
}
params.append(key, value);
window.history.pushState("object or string", "Title", currentURL.href);
}

function updateFilterInput() {
const commonFilterInputBox = document.querySelector(".filterSearch");
commonFilterInputBox.style.display = "none";
commonFilterInputBox.style.visibility = "hidden";
commonFilterInputBox.value = "";

var filter = getQueryVariable("filter");
if (filter) {
commonFilterInputBox.style.display = "inline-block";
commonFilterInputBox.style.visibility = "visible";

if (filter == "uid") {
commonFilterInputBox.placeholder = "Filter by " + filter.toUpperCase() + '...';
} else {
commonFilterInputBox.placeholder = "Filter by " + filter.charAt(0).toUpperCase() + filter.slice(1) + '...';
}

if (getQueryVariable("value") != false) {
commonFilterInputBox.value = getQueryVariable("value");
filterRows();
}

commonFilterInputBox.addEventListener("keyup", function(e) {
updateQueryStringParameter(window.location.href, "value", e.target.value);
filterRows();
});
}
}

updateFilterInput();

var filters = document.querySelectorAll("span.filter");
filters.forEach(function(filter) {
filter.addEventListener("click", function(e) {
e.preventDefault();
e.stopPropagation();
if (e.target.parentElement.id != getQueryVariable("filter")) {
updateQueryStringParameter(window.location.href, "filter", e.target.parentElement.id);
updateQueryStringParameter(window.location.href, "value", "");
filterRows();
} else {
updateQueryStringParameter(window.location.href, "filter", "");
updateQueryStringParameter(window.location.href, "value", "");
filterRows();
}
updateFilterInput();
});
});

function filterRows() {
var filter = getQueryVariable("filter");
var filterValue = getQueryVariable("value");

if (filter) {
var table = document.querySelector("table.filterable");
var rows = Array.from(table.querySelectorAll("tr:nth-child(n+2)"));
var column = table.querySelector("tr.key").querySelector("td#" + filter).cellIndex;
rows.forEach(function(row) {
if (row.cells[column].textContent.trim().toLowerCase().indexOf(filterValue.toLowerCase()) == -1) {
row.style.display = "none";
} else {
row.style.display = "";
}
}
);
}
}
73 changes: 73 additions & 0 deletions webroot/js/sort.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
var table = document.querySelector("table.sortable");
table.querySelectorAll("td").forEach(function(td) {
td.addEventListener("click", function(e) {
if (td.parentElement.classList.contains("key") && td.innerHTML != "Actions") {
if (e.target.classList.contains("filter")) {
updateQueryStringParameter(window.location.href, "filter", e.target.parentElement.id);
updateFilterInput();
} else {
var column = td.cellIndex;
var rows = Array.from(table.querySelectorAll("tr:nth-child(n+2)"));
var order = td.classList.toggle("asc") ? 1 : -1;
rows.sort(function(a, b) {
return order * (a.cells[column].textContent.trim().localeCompare(b.cells[column].textContent.trim(), undefined, {
numeric: true
}));
});
rows.forEach(function(row) {
table.appendChild(row);
});
var keys = document.querySelectorAll("tr.key");
keys.forEach(function(key) {
key.querySelectorAll("td").forEach(function(td) {
td.innerHTML = td.innerHTML.replace(/ ▲| ▼/, "");
});
});
var orderSymbol = order == 1 ? "&#x25B2;" : "&#x25BC;";
td.innerHTML = td.innerHTML + " " + orderSymbol;
updateQueryStringParameter(window.location.href, "sort", td.id);
updateQueryStringParameter(window.location.href, "order", order == 1 ? "asc" : "desc");
}
}
});
});

function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");

if (pair[0] == variable) {
return pair[1];
}
}
return false;
}

function updateQueryStringParameter(uri, key, value) {
let currentURL = new URL(window.location.href);
let params = currentURL.searchParams;
if (params.has(key)) {
params.delete(key);
}
params.append(key, value);
window.history.pushState("object or string", "Title", currentURL.href);
}

window.onload = function() {
var sort = getQueryVariable("sort");
var order = getQueryVariable("order");
if (sort) {
var sortElement = document.getElementById(sort);
if (sortElement) {
if (order == "asc") {
sortElement.click();
} else if (order == "desc") {
sortElement.click();
sortElement.click();
}
}
}
filterRows();
}