v0.26.0
This commit is contained in:
1 parent
d168ee2afa
commit
ddc5c6593f
70 files changed
+2293
-594
No files matched your search
@@ -0,0 +1,91 @@
|
||||
(() => {
|
||||
let inventory = null, offset = 0, lastTotal = 0, busy = false;
|
||||
const sourceSelect = () => $("file-log-source");
|
||||
const currentLimit = () => Math.max(1, Math.min(500, Number($("file-log-limit").value) || 100));
|
||||
function sourceOption(source) {
|
||||
const label = `${source.label} · ${source.format} · ${bytes(source.size || 0)}${source.enabled ? ` · ${t("enabled")}` : ""}`;
|
||||
const option = el("option", label); option.value = source.id; return option;
|
||||
}
|
||||
function renderInventory(value) {
|
||||
inventory = value;
|
||||
const selected = sourceSelect().value || "all";
|
||||
const sources = Array.isArray(value?.sources) ? value.sources : [];
|
||||
const options = [Object.assign(el("option", t("fileLogsAllSources")), { value: "all" }), ...sources.map(sourceOption)];
|
||||
sourceSelect().replaceChildren(...options);
|
||||
sourceSelect().value = ["all", ...sources.map(source => source.id)].includes(selected) ? selected : "all";
|
||||
$("file-log-inventory").textContent = sources.length
|
||||
? sources.map(source => `${source.label}: ${source.path} (${bytes(source.size || 0)})`).join(" · ")
|
||||
: t("fileLogsNoSources");
|
||||
}
|
||||
async function loadInventory() {
|
||||
const value = await api("/api/file-logs"); renderInventory(value); return value;
|
||||
}
|
||||
function entryTime(entry) {
|
||||
if (entry.time_ms) return new Date(Number(entry.time_ms)).toLocaleString(locale());
|
||||
if (entry.timestamp) return String(entry.timestamp);
|
||||
return "—";
|
||||
}
|
||||
function entrySummary(entry) {
|
||||
if (entry.protocol_error) return entry.protocol_error;
|
||||
if (entry.method || entry.path) return `${entry.method || ""} ${entry.host || ""}${entry.path || ""}`.trim();
|
||||
if (entry.message) return entry.message;
|
||||
if (entry.raw) return entry.raw;
|
||||
return entry.outcome || "—";
|
||||
}
|
||||
function entryStatus(entry) {
|
||||
const status = Number(entry.status) || 0;
|
||||
return status ? String(status) : "—";
|
||||
}
|
||||
function renderRows(entries) {
|
||||
const rows = entries.map(entry => {
|
||||
const row = el("tr"); row.tabIndex = 0;
|
||||
for (const value of [entryTime(entry), entry.event || "—", entryStatus(entry), entry.client_ip || "—", entry.vhost || "—", entrySummary(entry), entry._source || "—"]) {
|
||||
const cell = el("td", String(value)); cell.title = String(value); row.append(cell);
|
||||
}
|
||||
const show = () => { $("file-log-detail").textContent = JSON.stringify(entry, null, 2); };
|
||||
row.addEventListener("click", show); row.addEventListener("keydown", event => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); show(); } });
|
||||
return row;
|
||||
});
|
||||
$("file-log-rows").replaceChildren(...rows);
|
||||
$("file-logs-empty").hidden = rows.length !== 0;
|
||||
if (!rows.length) $("file-log-detail").textContent = t("fileLogsSelectRecord");
|
||||
}
|
||||
function queryString() {
|
||||
const params = new URLSearchParams();
|
||||
params.set("source", sourceSelect().value || "all");
|
||||
for (const [id, name] of [["file-log-q", "q"], ["file-log-event", "event"], ["file-log-status", "status_class"], ["file-log-client", "client_ip"], ["file-log-vhost", "vhost"]]) {
|
||||
const value = $(id).value.trim(); if (value && value !== "all") params.set(name, value);
|
||||
}
|
||||
params.set("offset", String(offset)); params.set("limit", String(currentLimit()));
|
||||
return params.toString();
|
||||
}
|
||||
async function refresh(reset = false) {
|
||||
if (!authenticated || busy) return;
|
||||
if (reset) offset = 0;
|
||||
busy = true; $("file-logs-refresh").disabled = true;
|
||||
try {
|
||||
if (!inventory) await loadInventory();
|
||||
const value = await api(`/api/file-logs/query?${queryString()}`);
|
||||
lastTotal = Number(value.total) || 0; renderRows(Array.isArray(value.entries) ? value.entries : []);
|
||||
const from = lastTotal ? offset + 1 : 0, to = Math.min(offset + currentLimit(), lastTotal);
|
||||
$("file-log-summary").textContent = t("fileLogsSummary")
|
||||
.replace("{from}", fmt(from)).replace("{to}", fmt(to)).replace("{total}", fmt(lastTotal))
|
||||
.replace("{bytes}", bytes(Number(value.scanned_bytes) || 0)).replace("{lines}", fmt(Number(value.scanned_lines) || 0))
|
||||
+ (value.truncated ? ` · ${t("fileLogsTruncated")}` : "");
|
||||
$("file-logs-prev").disabled = offset === 0;
|
||||
$("file-logs-next").disabled = offset + currentLimit() >= lastTotal;
|
||||
} catch (error) { toast(error.message, true); }
|
||||
finally { busy = false; $("file-logs-refresh").disabled = false; }
|
||||
}
|
||||
function reset() {
|
||||
inventory = null; offset = 0; lastTotal = 0; $("file-log-rows").replaceChildren(); $("file-log-detail").textContent = "";
|
||||
}
|
||||
$("file-logs-open").addEventListener("click", () => setPanel("filelogs"));
|
||||
$("settings-file-logs-open").addEventListener("click", () => setPanel("filelogs"));
|
||||
$("file-logs-refresh").addEventListener("click", () => refresh(true));
|
||||
$("file-logs-filter").addEventListener("submit", event => { event.preventDefault(); void refresh(true); });
|
||||
$("file-logs-prev").addEventListener("click", () => { offset = Math.max(0, offset - currentLimit()); void refresh(); });
|
||||
$("file-logs-next").addEventListener("click", () => { if (offset + currentLimit() < lastTotal) { offset += currentLimit(); void refresh(); } });
|
||||
sourceSelect().addEventListener("change", () => refresh(true));
|
||||
window.rustProxyFileLogs = { refresh: () => refresh(false), reset, inventory: loadInventory };
|
||||
})();
|
||||
Reference in new issue
Block a user