This commit is contained in:
Mateusz Gruszczyński committed 2026-10-07 13:40:21 +02:00
1 parent 3a2eb4fe79
commit e0194fbaff
63 files changed
+1553 -379

No files matched your search

+38 -5
View File
@@ -1,6 +1,8 @@
const poolColumns = ["vhost", "backend", "status", "active", "requests", "errors", "latency", "traffic", "generation", "generationRequests", "generationAge", "rotations", "lastFailure", "lastRecovery"];
const vhostSortColumns = ["id", "hostname", "status", "listeners", "certificate", "backends"];
const defaultPoolTablePrefs = () => ({ sort: "vhost", descending: false, columns: [...poolColumns] });
let poolTablePrefs = defaultPoolTablePrefs(), poolPreferenceSaveRunning = false, poolPreferenceSaveQueued = false;
const defaultVhostListPrefs = () => ({ sort: "id", descending: false });
let poolTablePrefs = defaultPoolTablePrefs(), vhostListPrefs = defaultVhostListPrefs(), poolPreferenceSaveRunning = false, poolPreferenceSaveQueued = false;
function normalizePoolTablePrefs(preferences) {
const selected = Array.isArray(preferences?.backend_table_columns) ? preferences.backend_table_columns.filter(key => poolColumns.includes(key)) : [];
return {
@@ -9,10 +11,27 @@
columns: selected.length ? selected : [...poolColumns],
};
}
function applyPoolPreferences(preferences) {
function normalizeVhostListPrefs(preferences) {
return { sort: vhostSortColumns.includes(preferences?.vhost_list_sort) ? preferences.vhost_list_sort : "id", descending: preferences?.vhost_list_descending === true };
}
function syncVhostSortDirection() {
const control = $("vhost-sort-direction"); if (!control) return;
control.textContent = vhostListPrefs.descending ? "↓" : "↑";
control.setAttribute("aria-label", t(vhostListPrefs.descending ? "backendSortDescending" : "backendSortAscending"));
}
function applyPreferences(preferences) {
poolTablePrefs = normalizePoolTablePrefs(preferences);
const sort = $("pool-sort"); if (sort) sort.value = poolTablePrefs.sort;
syncPoolColumns(); syncPoolSortDirection(); applyPoolTableView();
vhostListPrefs = normalizeVhostListPrefs(preferences);
const poolSort = $("pool-sort"); if (poolSort) poolSort.value = poolTablePrefs.sort;
const vhostSort = $("vhost-sort"); if (vhostSort) vhostSort.value = vhostListPrefs.sort;
syncPoolColumns(); syncPoolSortDirection(); syncVhostSortDirection(); applyPoolTableView(); render();
}
async function saveVhostListPrefs() {
if (!authenticated) return;
try {
const saved = await window.rustProxyPreferences.update({ vhost_list_sort: vhostListPrefs.sort, vhost_list_descending: vhostListPrefs.descending });
vhostListPrefs = normalizeVhostListPrefs(saved); const sort = $("vhost-sort"); if (sort) sort.value = vhostListPrefs.sort; syncVhostSortDirection();
} catch (error) { if (error.status !== 401) toast(error.message, true); }
}
async function savePoolTablePrefs() {
if (!authenticated) return;
@@ -103,6 +122,18 @@
].filter(Boolean).join(" ").toLowerCase();
return haystack.includes(query);
});
const sortValue = v => ({
id: String(v.id || "").toLowerCase(),
hostname: String(v.frontend?.hosts?.[0] || "").toLowerCase(),
status: v.enabled === false ? 1 : 0,
listeners: (v.frontend?.listener_ids || []).join(" ").toLowerCase(),
certificate: String(v.certificate_id || "").toLowerCase(),
backends: Number(v.backends?.length || 0),
}[vhostListPrefs.sort]);
visibleVhosts.sort((left, right) => {
const a = sortValue(left), b = sortValue(right); const result = typeof a === "number" && typeof b === "number" ? a - b : String(a).localeCompare(String(b), locale(), { numeric: true, sensitivity: "base" });
return vhostListPrefs.descending ? -result : result;
});
const cards = visibleVhosts.map(v => {
const box = el("article", undefined, "vhost-card"); box.dataset.vhostCard = v.id;
const head = el("div", undefined, "vhost-card-head"), identity = el("div", undefined, "vhost-card-identity");
@@ -324,6 +355,8 @@
});
$("vhost-new").addEventListener("click", () => { window.rustProxyDrafts.prepare(); load(); });
$("vhost-search").addEventListener("input", render);
$("vhost-sort")?.addEventListener("change", event => { vhostListPrefs.sort = event.target.value; void saveVhostListPrefs(); render(); });
$("vhost-sort-direction")?.addEventListener("click", () => { vhostListPrefs.descending = !vhostListPrefs.descending; syncVhostSortDirection(); void saveVhostListPrefs(); render(); });
$("vhost-reset").addEventListener("click", async () => {
if (!(await allowDiscard())) return;
const saved = editing ? (envelope?.config.vhosts || []).find(item => item.id === editing) : null;
@@ -333,5 +366,5 @@
initPoolTableTools();
$("location-help-close")?.addEventListener("click", () => $("location-help-dialog")?.close());
window.rustProxyDrafts.register("vhost", { labelKey: "vhosts", isOpen: () => dialog.open, isDirty: () => dirty, suspend: suspendDraft, restore: restoreDraft, close: () => { dirty = false; if (dialog.open) dialog.close(); } });
window.rustProxyVhosts = { render, renderStatus, applyPreferences: applyPoolPreferences, reset() { dialog.close(); draftEpoch++; stagedCertificates = []; uploading = false; editing = null; revision = null; dirty = false; initialized = false; poolTablePrefs = defaultPoolTablePrefs(); poolPreferenceSaveRunning = false; poolPreferenceSaveQueued = false; chartHistory.clear(); backendTrafficHistory.clear(); vhostTrafficHistory.clear(); container.replaceChildren(); $("vhost-search").value = ""; if ($("pool-search")) $("pool-search").value = ""; $("vhost-list").replaceChildren(); $("pool-rows").replaceChildren(); const sort = $("pool-sort"); if (sort) sort.value = poolTablePrefs.sort; applyPoolTableView(); } };
window.rustProxyVhosts = { render, renderStatus, applyPreferences, reset() { dialog.close(); draftEpoch++; stagedCertificates = []; uploading = false; editing = null; revision = null; dirty = false; initialized = false; poolTablePrefs = defaultPoolTablePrefs(); vhostListPrefs = defaultVhostListPrefs(); poolPreferenceSaveRunning = false; poolPreferenceSaveQueued = false; chartHistory.clear(); backendTrafficHistory.clear(); vhostTrafficHistory.clear(); container.replaceChildren(); $("vhost-search").value = ""; if ($("pool-search")) $("pool-search").value = ""; $("vhost-list").replaceChildren(); $("pool-rows").replaceChildren(); const sort = $("pool-sort"); if (sort) sort.value = poolTablePrefs.sort; const vhostSort = $("vhost-sort"); if (vhostSort) vhostSort.value = vhostListPrefs.sort; syncVhostSortDirection(); applyPoolTableView(); } };
if (envelope) render(); if (latestStatus) renderStatus(latestStatus);