feat(UptimeMonitorPage): add current checking server ID state to improve UI feedback during uptime checks
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m56s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m56s
This commit is contained in:
@@ -90,6 +90,8 @@ export default function UptimeMonitorPage() {
|
|||||||
const [historyMap, setHistoryMap] = useState(loadHistoryFromStorage);
|
const [historyMap, setHistoryMap] = useState(loadHistoryFromStorage);
|
||||||
const [selectedServerId, setSelectedServerId] = useState(null);
|
const [selectedServerId, setSelectedServerId] = useState(null);
|
||||||
const [checkIntervalSeconds, setCheckIntervalSeconds] = useState(DEFAULT_CHECK_INTERVAL_SEC);
|
const [checkIntervalSeconds, setCheckIntervalSeconds] = useState(DEFAULT_CHECK_INTERVAL_SEC);
|
||||||
|
/** serverId, для которого сейчас идёт проверка — показываем «Проверка…» в строке */
|
||||||
|
const [currentCheckingServerId, setCurrentCheckingServerId] = useState(null);
|
||||||
const intervalRef = useRef(null);
|
const intervalRef = useRef(null);
|
||||||
const checkingRef = useRef(false);
|
const checkingRef = useRef(false);
|
||||||
|
|
||||||
@@ -133,11 +135,10 @@ export default function UptimeMonitorPage() {
|
|||||||
if (checkingRef.current) return;
|
if (checkingRef.current) return;
|
||||||
checkingRef.current = true;
|
checkingRef.current = true;
|
||||||
setChecking(true);
|
setChecking(true);
|
||||||
const results = {};
|
|
||||||
const newHistory = {};
|
|
||||||
for (const server of jumphosts) {
|
for (const server of jumphosts) {
|
||||||
const serverId = server.id || server.dns || server.ip;
|
const serverId = server.id || server.dns || server.ip;
|
||||||
if (!serverId) continue;
|
if (!serverId) continue;
|
||||||
|
setCurrentCheckingServerId(serverId);
|
||||||
const t0 = Date.now();
|
const t0 = Date.now();
|
||||||
let ok = false;
|
let ok = false;
|
||||||
let ms = null;
|
let ms = null;
|
||||||
@@ -148,24 +149,19 @@ export default function UptimeMonitorPage() {
|
|||||||
} catch (_) {
|
} catch (_) {
|
||||||
ms = Date.now() - t0;
|
ms = Date.now() - t0;
|
||||||
}
|
}
|
||||||
results[serverId] = { ok, lastCheckTs: Date.now() };
|
const lastCheckTs = Date.now();
|
||||||
newHistory[serverId] = [{ ts: Date.now(), ok, ms }];
|
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));
|
await new Promise((r) => setTimeout(r, DELAY_BETWEEN_CHECKS_MS));
|
||||||
}
|
}
|
||||||
setStatusMap((prev) => {
|
setCurrentCheckingServerId(null);
|
||||||
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;
|
|
||||||
});
|
|
||||||
checkingRef.current = false;
|
checkingRef.current = false;
|
||||||
setChecking(false);
|
setChecking(false);
|
||||||
}, [jumphosts]);
|
}, [jumphosts]);
|
||||||
@@ -282,24 +278,32 @@ export default function UptimeMonitorPage() {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{status == null && (
|
{currentCheckingServerId === id && (
|
||||||
|
<span className="badge bg-blue-lt text-blue">
|
||||||
|
<span className="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true" />
|
||||||
|
Проверка…
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{currentCheckingServerId !== id && status == null && (
|
||||||
<span className="badge bg-secondary">—</span>
|
<span className="badge bg-secondary">—</span>
|
||||||
)}
|
)}
|
||||||
{status?.ok === true && (
|
{currentCheckingServerId !== id && status?.ok === true && (
|
||||||
<span className="badge bg-success-lt text-success">
|
<span className="badge bg-success-lt text-success">
|
||||||
<IconCircleCheck size={14} /> Доступен
|
<IconCircleCheck size={14} /> Доступен
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{status?.ok === false && (
|
{currentCheckingServerId !== id && status?.ok === false && (
|
||||||
<span className="badge bg-danger-lt text-danger">
|
<span className="badge bg-danger-lt text-danger">
|
||||||
<IconCircleX size={14} /> Недоступен
|
<IconCircleX size={14} /> Недоступен
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-muted">
|
<td className="text-muted">
|
||||||
{status?.lastCheckTs
|
{currentCheckingServerId === id
|
||||||
? formatRelative(status.lastCheckTs)
|
? '…'
|
||||||
: '—'}
|
: status?.lastCheckTs
|
||||||
|
? formatRelative(status.lastCheckTs)
|
||||||
|
: '—'}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user