fix(ui): показывать временные отметки трафика серверов
This commit is contained in:
1 parent
65241c94e9
commit
c6d146d38f
7 files changed
+56
-27
No files matched your search
@@ -782,7 +782,7 @@ export default function TrafficPage() {
|
||||
const [search, setSearch] = useState("")
|
||||
const [trafficRetry, setTrafficRetry] = useState(0)
|
||||
const trafficKey = JSON.stringify([isLive, backendUrl, range, groupMode, trafficRetry])
|
||||
const [trafficState, setTrafficState] = useState<{ key: string; status: "ready" | "error"; error?: string } | null>(null)
|
||||
const [trafficState, setTrafficState] = useState<{ key: string; status: "ready" | "error"; receivedAt?: number; error?: string } | null>(null)
|
||||
const trafficReady = trafficState?.key === trafficKey && trafficState.status === "ready"
|
||||
const trafficLoading = trafficState?.key !== trafficKey
|
||||
const trafficError = trafficState?.key === trafficKey ? trafficState.error : undefined
|
||||
@@ -791,7 +791,7 @@ export default function TrafficPage() {
|
||||
const [selectedIface, setSelectedIface] = useState("__all__")
|
||||
const [hideDisabledIfaces, setHideDisabledIfaces] = useState(true)
|
||||
const [detailRetry, setDetailRetry] = useState(0)
|
||||
const [detailResult, setDetailResult] = useState<{ key: string; server: ServerTraffic | null; error: string | null } | null>(null)
|
||||
const [detailResult, setDetailResult] = useState<{ key: string; server: ServerTraffic | null; receivedAt?: number; error: string | null } | null>(null)
|
||||
const [liveUsers, setLiveUsers] = useState<UserTraffic[]>([])
|
||||
const [liveBoundIfaces, setLiveBoundIfaces] = useState<BoundIfaceTraffic[]>([])
|
||||
const [flowScope, setFlowScope] = useState<FlowScope>("servers")
|
||||
@@ -819,7 +819,7 @@ export default function TrafficPage() {
|
||||
const detailKey = JSON.stringify([isLive, backendUrl, effectiveMode, selectedId, range, selectedIface, detailRetry])
|
||||
const currentDetail = detailResult?.key === detailKey ? detailResult : null
|
||||
const detailBusy = isLive && effectiveMode === "servers" && Boolean(selectedId) && currentDetail === null
|
||||
const { sample: liveSample, error: liveStreamError } = useTrafficLive({
|
||||
const { sample: liveSample, error: liveStreamError, receivedAt: liveReceivedAt } = useTrafficLive({
|
||||
enabled: isLive && effectiveMode === "servers" && liveServers.some((s) => s.id === selectedId),
|
||||
backendUrl,
|
||||
serverId: selectedId,
|
||||
@@ -860,7 +860,7 @@ export default function TrafficPage() {
|
||||
setLiveServers(mapped)
|
||||
setLiveUsers(mappedUsers)
|
||||
setLiveBoundIfaces(liveIfaces)
|
||||
setTrafficState({ key, status: "ready" })
|
||||
setTrafficState({ key, status: "ready", receivedAt: Date.now() })
|
||||
setSelectedId((prev) => {
|
||||
if (groupMode === "users") return mappedUsers.some((x) => x.id === prev) ? prev : (mappedUsers[0]?.id ?? "")
|
||||
if (groupMode === "ifaces") return liveIfaces.some((x) => x.id === prev) ? prev : (liveIfaces[0]?.id ?? "")
|
||||
@@ -952,7 +952,7 @@ export default function TrafficPage() {
|
||||
apiFetch<{ server: LiveTrafficServer }>(`/api/traffic/servers/${encodeURIComponent(selectedId)}?range=${encodeURIComponent(range)}&iface=${encodeURIComponent(selectedIface)}`)
|
||||
.then((res) => {
|
||||
if (cancelled) return
|
||||
setDetailResult({ key: detailKey, error: null, server: {
|
||||
setDetailResult({ key: detailKey, receivedAt: Date.now(), error: null, server: {
|
||||
...toLiveServer(res.server),
|
||||
boundIfaces: liveBoundIfaces.filter((i) => i.serverId === selectedId),
|
||||
} })
|
||||
@@ -1183,6 +1183,7 @@ export default function TrafficPage() {
|
||||
items={effectiveMode === "flows" ? flowKpiItems : counterKpiItems}
|
||||
/>}
|
||||
|
||||
{isLive && effectiveMode !== "flows" && trafficReady && <TrafficDataTime label="Получение списка трафика" receivedAt={trafficState.receivedAt} source="API" />}
|
||||
{effectiveMode === "flows" ? (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between gap-2 flex-wrap">
|
||||
@@ -1420,6 +1421,10 @@ export default function TrafficPage() {
|
||||
{detailBusy && <p role="status" className="text-sm text-muted-foreground">Загрузка выбранного периода и интерфейса…</p>}
|
||||
{currentDetail?.error && <Alert variant="destructive" role="alert"><AlertTitle>Детали трафика недоступны</AlertTitle><AlertDescription>{currentDetail.error}<Button type="button" size="sm" variant="outline" onClick={() => setDetailRetry(n => n + 1)}>Повторить загрузку деталей</Button></AlertDescription></Alert>}
|
||||
</>}
|
||||
{isLive && effectiveMode === "servers" && detailServer && <>
|
||||
<TrafficDataTime label="Получение истории сервера" receivedAt={currentDetail?.receivedAt} source="API" />
|
||||
<TrafficDataTime label="Последнее измерение сервера" receivedAt={liveReceivedAt} source="live-поток" serverAt={liveSample?.at} />
|
||||
</>}
|
||||
{effectiveMode === "servers" && detailServer && (
|
||||
<ServerDetail
|
||||
sel={detailServer}
|
||||
|
||||
Reference in new issue
Block a user