This commit is contained in:
Mateusz Gruszczyński committed 2026-10-04 23:13:27 +02:00
1 parent e6604e41fc
commit 1dea7f55c8
49 files changed
+4499 -4025

No files matched your search

+32 -1
View File
@@ -1,4 +1,4 @@
let configHistoryEntries = [];
let configHistoryEntries = [], configHistorySelectedRevision = null;
function historyDate(value, options = {}) {
try { return new Intl.DateTimeFormat(locale(), options).format(new Date(Number(value) * 1000)); }
catch { return new Date(Number(value) * 1000).toLocaleString(); }
@@ -13,6 +13,12 @@ function historyValue(value) {
const text = JSON.stringify(value, null, 2);
return text.length > 6000 ? `${text.slice(0, 6000)}\n...` : text;
}
function syncConfigHistoryRestoreButton() {
const button = $("config-history-restore"), revision = Number(configHistorySelectedRevision);
if (!button) return;
button.hidden = configHistorySelectedRevision === null;
button.disabled = busy || !envelope || !Number.isSafeInteger(revision) || revision >= Number(envelope.revision);
}
function configDiff(before, after, path = "$", output = [], depth = 0) {
if (output.length >= 200) return output;
if (Object.is(before, after)) return output;
@@ -29,8 +35,10 @@ function configDiff(before, after, path = "$", output = [], depth = 0) {
function renderConfigRevisionDetail(detail) {
const entry = detail?.revision;
if (!entry) return;
configHistorySelectedRevision = Number(entry.revision);
$("config-history-detail-title").textContent = `${t("configHistoryRevision")} ${entry.revision}`;
$("config-history-detail-meta").textContent = `${historyDate(entry.time, { dateStyle: "medium", timeStyle: "short" })} · ${entry.actor}`;
syncConfigHistoryRestoreButton();
document.querySelectorAll(".config-history-revision").forEach(button => button.classList.toggle("active", Number(button.dataset.revision) === Number(entry.revision)));
const diff = configDiff(entry.previous_config, entry.config);
const box = $("config-history-diff"); box.replaceChildren();
@@ -95,7 +103,29 @@ function renderConfigHistory() {
}
if (!months.length) calendar.append(el("p", t("configHistoryEmpty"), "empty"));
}
async function restoreConfigRevision() {
const revision = Number(configHistorySelectedRevision);
if (!envelope || busy || !Number.isSafeInteger(revision) || revision >= Number(envelope.revision)) return;
const expectedRevision = Number(envelope.revision);
const message = t("configHistoryRestoreConfirm").replace("{revision}", revision).replace("{current}", expectedRevision);
if (!(await appConfirm(message, { danger: true, confirmLabel: t("configHistoryRestoreAction") }))) return;
const button = $("config-history-restore"), epoch = authEpoch;
busy = true; syncConfigHistoryRestoreButton();
try {
const value = await api("/api/config/history/restore", { method: "POST", body: JSON.stringify({ revision, expected_revision: expectedRevision }) });
if (!authenticated || epoch !== authEpoch) return;
envelope = value;
await refreshCertificateInventory();
if (!authenticated || epoch !== authEpoch) return;
renderConfig();
toast(t("configHistoryRestored").replace("{revision}", revision).replace("{new_revision}", value.revision));
await refresh(true);
if (authenticated && epoch === authEpoch) await loadConfigHistory();
} catch (error) { toast(error.message, true); if (error.status === 401) lock(); }
finally { busy = false; if (button?.isConnected) syncConfigHistoryRestoreButton(); }
}
async function loadConfigHistory() {
configHistorySelectedRevision = null; syncConfigHistoryRestoreButton();
$("config-history-summary").textContent = t("configHistoryLoading");
try {
const result = await api("/api/config/history?limit=512"); configHistoryEntries = result.revisions || []; renderConfigHistory();
@@ -105,3 +135,4 @@ async function loadConfigHistory() {
$("config-history-open").addEventListener("click", () => { const dialog = $("config-history-dialog"); if (!dialog.open) dialog.showModal(); void loadConfigHistory(); });
$("config-history-close").addEventListener("click", () => $("config-history-dialog").close());
$("config-history-reload").addEventListener("click", () => void loadConfigHistory());
$("config-history-restore").addEventListener("click", () => void restoreConfigRevision());
+1 -1
View File
@@ -6,7 +6,7 @@ function renderSettings() {
if (!settingsDirty.has("response-form")) {
const server = config.server_header || {}, compression = config.compression || {}, diagnostics = config.diagnostic_headers || {};
$("expose-request-id").checked = !!diagnostics.request_id;
$("server-mode").value = server.mode || "preserve"; $("server-value").value = server.value || "RustProxy/v0.25.3";
$("server-mode").value = server.mode || "preserve"; $("server-value").value = server.value || "RustProxy/v0.25.4";
for (const name of ["gzip", "br", "zstd", "deflate"]) $(`compress-${name}`).checked = !!compression[name];
$("compress-min").value = compression.min_bytes ?? 1024; syncServerMode();
}
+3 -3
View File
@@ -1472,7 +1472,7 @@
<option data-i18n="serverCustom" value="custom">Replace / add custom value</option>
</select>
<label data-i18n="serverValue" for="server-value">Custom Server value</label><input
id="server-value" maxlength="256" placeholder="RustProxy/v0.25.3"
id="server-value" maxlength="256" placeholder="RustProxy/v0.25.4"
spellcheck="false" />
<h3 class="subheading" data-i18n="diagnosticHeaders">Diagnostic headers</h3>
<div class="switch-grid">
@@ -2218,7 +2218,7 @@
</section>
</div>
</section>
<footer class="page-footer"><span>RustProxy <b>0.25.3</b></span><span id="footer-status">API - /
<footer class="page-footer"><span>RustProxy <b>0.25.4</b></span><span id="footer-status">API - /
dropped: 0</span></footer>
</div>
</main>
@@ -2370,7 +2370,7 @@
<aside class="card config-history-detail">
<div class="config-history-detail-head">
<div><span class="small-label" data-i18n="configHistoryChanges">CHANGES</span><h3 id="config-history-detail-title">-</h3></div>
<span class="fine" id="config-history-detail-meta"></span>
<div class="config-history-detail-actions"><span class="fine" id="config-history-detail-meta"></span><button class="outline" data-i18n="configHistoryRestoreAction" id="config-history-restore" type="button" hidden disabled>Restore revision</button></div>
</div>
<div class="config-history-revisions" id="config-history-revisions"></div>
<div class="config-history-diff" id="config-history-diff"><p class="empty" data-i18n="configHistorySelectDay">Select a day.</p></div>
+14
View File
@@ -7734,6 +7734,18 @@ button.config-history-day.is-selected {
margin: 3px 0 0;
}
.config-history-detail-actions {
display: flex;
flex-direction: column;
gap: 7px;
align-items: flex-end;
text-align: right;
}
.config-history-detail-actions button {
white-space: nowrap;
}
.config-history-revisions {
display: flex;
flex-wrap: wrap;
@@ -7788,4 +7800,6 @@ button.config-history-day.is-selected {
.config-history-layout { grid-template-columns: 1fr; overflow: auto; }
.config-history-browser, .config-history-detail { overflow: visible; }
.config-history-change-values { grid-template-columns: 1fr; }
.config-history-detail-head { flex-direction: column; }
.config-history-detail-actions { align-items: flex-start; text-align: left; }
}