Skip to content

Commit

Permalink
Merge pull request #87 from sheldor1510/sortable-filterable-tables
Browse files Browse the repository at this point in the history
Made admin panel tables sortable and filterable
  • Loading branch information
hakasapl authored May 29, 2024
2 parents dbe4bb4 + 58af24c commit dcd4409
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 12 deletions.
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();
}

0 comments on commit dcd4409

Please sign in to comment.