Add filters in statistics view
This commit is contained in:
@@ -366,6 +366,17 @@ document.getElementById("keypass-form").addEventListener("submit", async e => {
|
||||
async function loadGates() {
|
||||
const rows = await api("GET", "/api/admin/gates");
|
||||
_allGates = rows; // cache for keypass modal
|
||||
// Populate the stats gate filter dropdown
|
||||
const filterGate = document.getElementById("filter-gate");
|
||||
const prevGateVal = filterGate.value;
|
||||
filterGate.innerHTML = '<option value="">Any</option>';
|
||||
for (const g of rows) {
|
||||
const opt = document.createElement("option");
|
||||
opt.value = g.id;
|
||||
opt.textContent = g.name;
|
||||
filterGate.appendChild(opt);
|
||||
}
|
||||
filterGate.value = prevGateVal; // restore selection if still valid
|
||||
const isAdmin = _tokenPayload().scope === "admin";
|
||||
const tbody = document.getElementById("gates-body");
|
||||
tbody.innerHTML = "";
|
||||
@@ -521,16 +532,47 @@ document.getElementById("credentials-form").addEventListener("submit", async e =
|
||||
});
|
||||
|
||||
// ── Statistics ───────────────────────────────────────────────────────────────
|
||||
const STATS_PAGE_SIZE = 50;
|
||||
let _statsPage = 1;
|
||||
let _statsTotal = 0;
|
||||
|
||||
function _buildStatsParams() {
|
||||
const params = new URLSearchParams();
|
||||
const keypass = document.getElementById("filter-keypass").value.trim();
|
||||
if (keypass) params.set("keypass_code", keypass.toUpperCase());
|
||||
const gate = document.getElementById("filter-gate").value;
|
||||
if (gate) params.set("gate_id", gate);
|
||||
const success = document.getElementById("filter-success").value;
|
||||
if (success !== "") params.set("success", success);
|
||||
const from = document.getElementById("filter-from").value;
|
||||
if (from) params.set("date_from", new Date(from).toISOString());
|
||||
const to = document.getElementById("filter-to").value;
|
||||
if (to) params.set("date_to", new Date(to).toISOString());
|
||||
params.set("page", _statsPage);
|
||||
params.set("page_size", STATS_PAGE_SIZE);
|
||||
return params;
|
||||
}
|
||||
|
||||
async function loadStats() {
|
||||
try {
|
||||
const rows = await api("GET", "/api/admin/stats");
|
||||
const data = await api("GET", `/api/admin/stats?${_buildStatsParams()}`);
|
||||
_statsTotal = data.total;
|
||||
const totalPages = Math.max(1, Math.ceil(_statsTotal / STATS_PAGE_SIZE));
|
||||
|
||||
document.getElementById("stats-total-label").textContent =
|
||||
`${_statsTotal} record${_statsTotal !== 1 ? "s" : ""}`;
|
||||
document.getElementById("stats-page-label").textContent =
|
||||
`Page ${_statsPage} of ${totalPages}`;
|
||||
document.getElementById("btn-stats-prev").disabled = _statsPage <= 1;
|
||||
document.getElementById("btn-stats-next").disabled = _statsPage >= totalPages;
|
||||
|
||||
const tbody = document.getElementById("stats-body");
|
||||
tbody.innerHTML = "";
|
||||
if (!rows.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="6" style="color:var(--text-muted);text-align:center;padding:2rem">No access logs yet</td></tr>';
|
||||
if (!data.items.length) {
|
||||
tbody.innerHTML = '<tr><td colspan="6" style="color:var(--text-muted);text-align:center;padding:2rem">No records match the current filters</td></tr>';
|
||||
return;
|
||||
}
|
||||
for (const r of rows) {
|
||||
for (const r of data.items) {
|
||||
const badge = r.success
|
||||
? '<span class="badge badge-green">OK</span>'
|
||||
: `<span class="badge badge-red" title="${esc(r.error || '')}">Fail</span>`;
|
||||
@@ -547,9 +589,24 @@ async function loadStats() {
|
||||
} catch (e) { showToast(e.message, true); }
|
||||
}
|
||||
|
||||
document.getElementById("btn-refresh-stats").addEventListener("click", loadStats);
|
||||
|
||||
document.getElementById("btn-refresh-stats").addEventListener("click", loadStats);
|
||||
document.getElementById("btn-refresh-stats").addEventListener("click", () => { _statsPage = 1; loadStats(); });
|
||||
document.getElementById("btn-stats-filter").addEventListener("click", () => { _statsPage = 1; loadStats(); });
|
||||
document.getElementById("btn-stats-reset").addEventListener("click", () => {
|
||||
document.getElementById("filter-keypass").value = "";
|
||||
document.getElementById("filter-gate").value = "";
|
||||
document.getElementById("filter-success").value = "";
|
||||
document.getElementById("filter-from").value = "";
|
||||
document.getElementById("filter-to").value = "";
|
||||
_statsPage = 1;
|
||||
loadStats();
|
||||
});
|
||||
document.getElementById("btn-stats-prev").addEventListener("click", () => {
|
||||
if (_statsPage > 1) { _statsPage--; loadStats(); }
|
||||
});
|
||||
document.getElementById("btn-stats-next").addEventListener("click", () => {
|
||||
const totalPages = Math.max(1, Math.ceil(_statsTotal / STATS_PAGE_SIZE));
|
||||
if (_statsPage < totalPages) { _statsPage++; loadStats(); }
|
||||
});
|
||||
|
||||
// ── Admin users ───────────────────────────────────────────────────────────────
|
||||
async function loadAdmins() {
|
||||
|
||||
Reference in New Issue
Block a user