diff --git a/frontend/src/UptimeMonitorPage.jsx b/frontend/src/UptimeMonitorPage.jsx index 70019e2..cfdf76b 100644 --- a/frontend/src/UptimeMonitorPage.jsx +++ b/frontend/src/UptimeMonitorPage.jsx @@ -90,6 +90,8 @@ export default function UptimeMonitorPage() { const [historyMap, setHistoryMap] = useState(loadHistoryFromStorage); const [selectedServerId, setSelectedServerId] = useState(null); const [checkIntervalSeconds, setCheckIntervalSeconds] = useState(DEFAULT_CHECK_INTERVAL_SEC); + /** serverId, для которого сейчас идёт проверка — показываем «Проверка…» в строке */ + const [currentCheckingServerId, setCurrentCheckingServerId] = useState(null); const intervalRef = useRef(null); const checkingRef = useRef(false); @@ -133,11 +135,10 @@ export default function UptimeMonitorPage() { if (checkingRef.current) return; checkingRef.current = true; setChecking(true); - const results = {}; - const newHistory = {}; for (const server of jumphosts) { const serverId = server.id || server.dns || server.ip; if (!serverId) continue; + setCurrentCheckingServerId(serverId); const t0 = Date.now(); let ok = false; let ms = null; @@ -148,24 +149,19 @@ export default function UptimeMonitorPage() { } catch (_) { ms = Date.now() - t0; } - results[serverId] = { ok, lastCheckTs: Date.now() }; - newHistory[serverId] = [{ ts: Date.now(), ok, ms }]; + const lastCheckTs = Date.now(); + const entry = { ts: lastCheckTs, ok, ms }; + // Обновляем UI сразу после каждой проверки — результат виден по мере прохождения тестов + setStatusMap((prev) => ({ ...prev, [serverId]: { ok, lastCheckTs } })); + setHistoryMap((prev) => { + const list = Array.isArray(prev[serverId]) ? prev[serverId] : []; + const merged = [...list, entry].slice(-HISTORY_MAX); + return { ...prev, [serverId]: merged }; + }); + setCurrentCheckingServerId(null); await new Promise((r) => setTimeout(r, DELAY_BETWEEN_CHECKS_MS)); } - setStatusMap((prev) => { - const next = { ...prev }; - for (const [id, v] of Object.entries(results)) next[id] = v; - return next; - }); - setHistoryMap((prev) => { - const next = { ...prev }; - for (const [id, one] of Object.entries(newHistory)) { - const list = Array.isArray(next[id]) ? next[id] : []; - const merged = [...list, ...one].slice(-HISTORY_MAX); - next[id] = merged; - } - return next; - }); + setCurrentCheckingServerId(null); checkingRef.current = false; setChecking(false); }, [jumphosts]); @@ -282,24 +278,32 @@ export default function UptimeMonitorPage() { - {status == null && ( + {currentCheckingServerId === id && ( + + + )} + {currentCheckingServerId !== id && status == null && ( )} - {status?.ok === true && ( + {currentCheckingServerId !== id && status?.ok === true && ( Доступен )} - {status?.ok === false && ( + {currentCheckingServerId !== id && status?.ok === false && ( Недоступен )} - {status?.lastCheckTs - ? formatRelative(status.lastCheckTs) - : '—'} + {currentCheckingServerId === id + ? '…' + : status?.lastCheckTs + ? formatRelative(status.lastCheckTs) + : '—'} );