fix(ui): сохранить данные дашборда при сбоях и гонках запросов
This commit is contained in:
1 parent
0d418e2e39
commit
6a726b13b4
6 files changed
+316
-94
No files matched your search
@@ -24,9 +24,9 @@ import { DashboardEventsTimeline } from "@/components/dashboard/dashboard-events
|
||||
import { InternetPathPanel } from "@/components/dashboard/internet-path-panel"
|
||||
import { DashboardActiveProbesDataGrid } from "@/components/data-grids/dashboard-active-probes-data-grid"
|
||||
import { EmptyState } from "@/components/empty-state"
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/reui/alert"
|
||||
import { DashboardDataStatus } from "@/components/dashboard/dashboard-data-status"
|
||||
import { Badge } from "@/components/reui/badge"
|
||||
import { Button, buttonVariants } from "@/components/ui/button"
|
||||
import { buttonVariants } from "@/components/ui/button"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { fmtRate } from "@/lib/fmt-rate"
|
||||
import { useDashboardLive, type AttentionRow } from "@/hooks/use-dashboard-live"
|
||||
@@ -69,17 +69,7 @@ export default function DashboardPage() {
|
||||
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
<div className="flex flex-col gap-4 px-4 py-4 md:gap-6 md:px-6 md:py-5">
|
||||
{dash.error && !dash.loading ? (
|
||||
<Alert variant="destructive">
|
||||
<AlertTitle>Не удалось обновить дашборд</AlertTitle>
|
||||
<AlertDescription className="flex flex-wrap items-center gap-2">
|
||||
<span>{dash.error}</span>
|
||||
<Button variant="outline" size="sm" onClick={dash.retry}>
|
||||
Повторить
|
||||
</Button>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
) : null}
|
||||
{dash.isLive && <DashboardDataStatus sources={dash.sources} refreshing={dash.refreshing} onRefresh={dash.retry} />}
|
||||
|
||||
<KpiStatGrid
|
||||
aria-label="Сводка дашборда"
|
||||
@@ -88,8 +78,8 @@ export default function DashboardPage() {
|
||||
{
|
||||
id: "fleet",
|
||||
label: "Флот",
|
||||
value: `${dash.onlineCount} / ${dash.totalServers}`,
|
||||
hint: !dash.isLive
|
||||
value: dash.availability.servers ? `${dash.onlineCount} / ${dash.totalServers}` : "—",
|
||||
hint: !dash.availability.servers ? "нет данных" : !dash.isLive
|
||||
? "демо"
|
||||
: offline > 0
|
||||
? `${offline} offline`
|
||||
@@ -104,8 +94,8 @@ export default function DashboardPage() {
|
||||
{
|
||||
id: "overlay",
|
||||
label: "Оверлей",
|
||||
value: String(dash.overlay.up),
|
||||
hint: dash.overlay.total > 0 ? `${dash.overlay.down} down` : "нет туннелей",
|
||||
value: dash.availability.overlay ? String(dash.overlay.up) : "—",
|
||||
hint: !dash.availability.overlay ? "не все источники доступны" : dash.overlay.total > 0 ? `${dash.overlay.down} down` : "нет туннелей",
|
||||
href: "/gre",
|
||||
icon: <CableIcon />,
|
||||
iconClassName: "text-info",
|
||||
@@ -123,8 +113,8 @@ export default function DashboardPage() {
|
||||
{
|
||||
id: "health",
|
||||
label: "Здоровье",
|
||||
value: String(health),
|
||||
hint: `${dash.probeDown} down · ${dash.probeWarn} warn`,
|
||||
value: dash.availability.probes ? String(health) : "—",
|
||||
hint: dash.availability.probes ? `${dash.probeDown} down · ${dash.probeWarn} warn` : "нет данных",
|
||||
href: "/uptime",
|
||||
icon: <BellIcon />,
|
||||
iconClassName: health > 0 ? "text-destructive" : "text-muted-foreground",
|
||||
@@ -268,8 +258,8 @@ export default function DashboardPage() {
|
||||
icon: ServerIcon,
|
||||
count: dash.attentionServers.length,
|
||||
countVariant: "warning-light",
|
||||
emptyTitle: "Все online",
|
||||
emptyDescription: "Нет офлайн или degraded узлов.",
|
||||
emptyTitle: dash.reliable.servers ? "Все online" : "Состояние не подтверждено",
|
||||
emptyDescription: dash.reliable.servers ? "Нет офлайн или degraded узлов." : "Проверьте состояние источников выше.",
|
||||
children: <AttentionRows rows={dash.attentionServers} />,
|
||||
},
|
||||
{
|
||||
@@ -279,8 +269,8 @@ export default function DashboardPage() {
|
||||
iconClassName: "text-info",
|
||||
count: dash.attentionOverlay.length,
|
||||
countVariant: "destructive-light",
|
||||
emptyTitle: "Туннели up",
|
||||
emptyDescription: "GRE и WireGuard в норме.",
|
||||
emptyTitle: dash.reliable.overlay ? "Туннели up" : "Состояние не подтверждено",
|
||||
emptyDescription: dash.reliable.overlay ? "GRE и WireGuard в норме." : "Проверьте состояние источников выше.",
|
||||
children: <AttentionRows rows={dash.attentionOverlay} />,
|
||||
},
|
||||
{
|
||||
@@ -290,8 +280,8 @@ export default function DashboardPage() {
|
||||
iconClassName: "text-destructive",
|
||||
count: dash.attentionProbes.length,
|
||||
countVariant: "destructive-light",
|
||||
emptyTitle: "Пробы up",
|
||||
emptyDescription: "Нет down или warn.",
|
||||
emptyTitle: dash.reliable.probes ? "Пробы up" : "Состояние не подтверждено",
|
||||
emptyDescription: dash.reliable.probes ? "Нет down или warn." : "Проверьте состояние источников выше.",
|
||||
children: <AttentionRows rows={dash.attentionProbes} />,
|
||||
},
|
||||
]}
|
||||
@@ -319,8 +309,8 @@ export default function DashboardPage() {
|
||||
{dash.activeProbes.length === 0 && !dash.probesLoading ? (
|
||||
<EmptyState
|
||||
className="py-10"
|
||||
title="Нет проб на дашборде"
|
||||
description="Включите пробу и отметьте ★ на странице мониторинга."
|
||||
title={dash.availability.probes ? "Нет проб на дашборде" : "Данные проб недоступны"}
|
||||
description={dash.availability.probes ? "Включите пробу и отметьте ★ на странице мониторинга." : "Повторите обновление данных."}
|
||||
action={
|
||||
<Link href="/uptime" className={cn(buttonVariants({ variant: "outline", size: "sm" }))}>
|
||||
Открыть мониторинг
|
||||
|
||||
Reference in new issue
Block a user