mirror of
https://github.com/anten-ka/gotelegram_pro.git
synced 2026-05-19 10:26:05 +00:00
v2.5.0: add admin auto refresh toggle
This commit is contained in:
@@ -11,6 +11,10 @@ const i18n = {
|
||||
navLogs: "Logs",
|
||||
navSettings: "Settings",
|
||||
refresh: "Refresh",
|
||||
autoRefresh: "Auto refresh every 5 seconds",
|
||||
autoRefreshOn: "Auto refresh is on",
|
||||
autoRefreshOff: "Auto refresh is off",
|
||||
autoRefreshOffShort: "off",
|
||||
themeDark: "Dark",
|
||||
themeLight: "Light",
|
||||
metricMode: "Mode",
|
||||
@@ -234,6 +238,10 @@ const i18n = {
|
||||
navLogs: "Логи",
|
||||
navSettings: "Настройки",
|
||||
refresh: "Обновить",
|
||||
autoRefresh: "Автообновление каждые 5 секунд",
|
||||
autoRefreshOn: "Автообновление включено",
|
||||
autoRefreshOff: "Автообновление выключено",
|
||||
autoRefreshOffShort: "выкл",
|
||||
themeDark: "Тёмная",
|
||||
themeLight: "Светлая",
|
||||
metricMode: "Режим",
|
||||
@@ -469,11 +477,15 @@ const state = {
|
||||
backupSchedule: null,
|
||||
qrLink: "",
|
||||
pendingUsers: new Set(),
|
||||
refreshingAll: false,
|
||||
autoRefreshEnabled: localStorage.getItem("gotelegram-auto-refresh") !== "0",
|
||||
};
|
||||
|
||||
const t = (key) => (i18n[state.lang] && i18n[state.lang][key]) || i18n.en[key] || key;
|
||||
|
||||
const trafficRanges = ["15m", "1h", "24h", "month"];
|
||||
const AUTO_REFRESH_MS = 5000;
|
||||
let autoRefreshTimer = null;
|
||||
|
||||
const fmtBytes = (value = 0) => {
|
||||
const units = ["B", "KB", "MB", "GB", "TB"];
|
||||
@@ -527,6 +539,34 @@ const addEvent = (title, detail = "") => {
|
||||
renderEvents();
|
||||
};
|
||||
|
||||
function updateAutoRefreshToggle() {
|
||||
const button = $("#autoRefreshToggle");
|
||||
if (!button) return;
|
||||
button.classList.toggle("active", state.autoRefreshEnabled);
|
||||
button.setAttribute("aria-pressed", String(state.autoRefreshEnabled));
|
||||
button.title = state.autoRefreshEnabled ? t("autoRefreshOn") : t("autoRefreshOff");
|
||||
const label = button.querySelector(".auto-refresh-state");
|
||||
if (label) label.textContent = state.autoRefreshEnabled ? "5s" : t("autoRefreshOffShort");
|
||||
}
|
||||
|
||||
function syncAutoRefreshTimer() {
|
||||
if (autoRefreshTimer) {
|
||||
clearInterval(autoRefreshTimer);
|
||||
autoRefreshTimer = null;
|
||||
}
|
||||
if (!state.autoRefreshEnabled) return;
|
||||
autoRefreshTimer = setInterval(() => {
|
||||
refreshAll().catch((err) => toast(err.message));
|
||||
}, AUTO_REFRESH_MS);
|
||||
}
|
||||
|
||||
function setAutoRefresh(enabled) {
|
||||
state.autoRefreshEnabled = Boolean(enabled);
|
||||
localStorage.setItem("gotelegram-auto-refresh", state.autoRefreshEnabled ? "1" : "0");
|
||||
updateAutoRefreshToggle();
|
||||
syncAutoRefreshTimer();
|
||||
}
|
||||
|
||||
async function api(path, options = {}) {
|
||||
const headers = {
|
||||
"Accept": "application/json",
|
||||
@@ -564,6 +604,7 @@ function applyI18n() {
|
||||
updateUserTrafficControls();
|
||||
renderBackupSchedule();
|
||||
updatePageTitle();
|
||||
updateAutoRefreshToggle();
|
||||
}
|
||||
|
||||
function setTheme(theme) {
|
||||
@@ -1271,6 +1312,8 @@ function renderConfig() {
|
||||
}
|
||||
|
||||
async function refreshAll() {
|
||||
if (state.refreshingAll) return;
|
||||
state.refreshingAll = true;
|
||||
const btn = $("#refreshBtn");
|
||||
btn.disabled = true;
|
||||
try {
|
||||
@@ -1305,6 +1348,8 @@ async function refreshAll() {
|
||||
toast(err.message);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
state.refreshingAll = false;
|
||||
updateAutoRefreshToggle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1684,6 +1729,7 @@ document.addEventListener("submit", (eventObj) => {
|
||||
});
|
||||
|
||||
$("#refreshBtn").addEventListener("click", refreshAll);
|
||||
$("#autoRefreshToggle").addEventListener("click", () => setAutoRefresh(!state.autoRefreshEnabled));
|
||||
$("#languageSelect").addEventListener("change", (eventObj) => setLanguage(eventObj.target.value));
|
||||
$("#promoClose").addEventListener("click", () => {
|
||||
$("#promoModal").hidden = true;
|
||||
@@ -1703,6 +1749,7 @@ window.addEventListener("hashchange", () => setPage((location.hash || "#dashboar
|
||||
setPage((location.hash || "#dashboard").slice(1), false);
|
||||
setTheme(state.theme);
|
||||
renderEvents();
|
||||
syncAutoRefreshTimer();
|
||||
refreshAll();
|
||||
loadLogs();
|
||||
maybeShowPromo();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
document.documentElement.dataset.theme = theme;
|
||||
}());
|
||||
</script>
|
||||
<link rel="stylesheet" href="/styles.css?v=2.5.0-admin8">
|
||||
<link rel="stylesheet" href="/styles.css?v=2.5.0-admin18">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-shell">
|
||||
@@ -54,6 +54,11 @@
|
||||
</select>
|
||||
<button id="themeToggle" class="ghost" type="button">Theme</button>
|
||||
<button id="refreshBtn" type="button" data-i18n="refresh">Refresh</button>
|
||||
<button id="autoRefreshToggle" class="auto-refresh-toggle" type="button" aria-pressed="true" data-i18n-title="autoRefresh" title="Auto refresh">
|
||||
<span class="auto-refresh-icon" aria-hidden="true">↻</span>
|
||||
<span class="auto-refresh-track" aria-hidden="true"><span></span></span>
|
||||
<span class="auto-refresh-state">5s</span>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -388,6 +393,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/app.js?v=2.5.0-admin17" type="module"></script>
|
||||
<script src="/app.js?v=2.5.0-admin18" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -228,6 +228,65 @@ h2 {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.auto-refresh-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-height: 42px;
|
||||
padding: 7px 10px;
|
||||
border: 1px solid var(--line);
|
||||
background: var(--panel-strong);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.auto-refresh-toggle:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.auto-refresh-icon {
|
||||
color: var(--blue);
|
||||
font-size: 17px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.auto-refresh-track {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: 38px;
|
||||
height: 22px;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--muted) 28%, transparent);
|
||||
transition: background .16s ease;
|
||||
}
|
||||
|
||||
.auto-refresh-track span {
|
||||
position: absolute;
|
||||
left: 3px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 999px;
|
||||
background: var(--panel);
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, .18);
|
||||
transition: transform .16s ease;
|
||||
}
|
||||
|
||||
.auto-refresh-toggle.active .auto-refresh-track {
|
||||
background: color-mix(in srgb, var(--green) 58%, transparent);
|
||||
}
|
||||
|
||||
.auto-refresh-toggle.active .auto-refresh-track span {
|
||||
transform: translateX(16px);
|
||||
}
|
||||
|
||||
.auto-refresh-state {
|
||||
min-width: 22px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.language-select {
|
||||
width: 78px;
|
||||
min-width: 78px;
|
||||
|
||||
@@ -199,6 +199,19 @@ class AdminFeatureTests(unittest.TestCase):
|
||||
self.assertIn('class="keys-list" id="usersTable"', index)
|
||||
self.assertNotIn('class="keys-table"', index)
|
||||
|
||||
def test_topbar_has_five_second_auto_refresh_toggle(self):
|
||||
app_js = (ROOT / "admin-web" / "static" / "app.js").read_text(encoding="utf-8")
|
||||
styles = (ROOT / "admin-web" / "static" / "styles.css").read_text(encoding="utf-8")
|
||||
index = (ROOT / "admin-web" / "static" / "index.html").read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn('id="autoRefreshToggle"', index)
|
||||
self.assertIn('data-i18n-title="autoRefresh"', index)
|
||||
self.assertIn("gotelegram-auto-refresh", app_js)
|
||||
self.assertIn("AUTO_REFRESH_MS = 5000", app_js)
|
||||
self.assertIn("setInterval", app_js)
|
||||
self.assertIn("clearInterval", app_js)
|
||||
self.assertIn(".auto-refresh-toggle", styles)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user