CI / changes (push) Successful in 11s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 49s
CI / go (push) Successful in 1m2s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 3m57s
Added the AnalyticsDashboardSkeleton component to improve loading states in the dashboard and monitoring pages. Refactored the dashboard to utilize the new skeleton for initial loading, replacing the previous SectionCardsSkeleton. Updated the overview queries to increase job limit from 10 to 100 for better data handling. Enhanced the network and operations components to incorporate new analytics cards, streamlining the user experience and improving data presentation.
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
import { AnalyticsCardShell } from '@/components/analytics/analytics-card-shell'
|
||
import { AnalyticsKpiRow } from '@/components/analytics/analytics-kpi-row'
|
||
import { ChartDonutMetric } from '@/components/analytics/chart-donut-metric'
|
||
import { jobStatusBreakdown } from '@/lib/metrics'
|
||
import type { JobRow, RevisionRow } from '@/types/api'
|
||
|
||
export function OperationsAnalyticsCard({
|
||
jobs,
|
||
revisions,
|
||
loading,
|
||
}: {
|
||
jobs: JobRow[]
|
||
revisions: RevisionRow[]
|
||
loading?: boolean
|
||
}) {
|
||
const running = jobs.filter((j) => ['running', 'queued'].includes(j.status.toLowerCase())).length
|
||
const failed = jobs.filter((j) =>
|
||
['failed', 'error', 'cancelled'].includes(j.status.toLowerCase()),
|
||
).length
|
||
const slices = jobStatusBreakdown(jobs)
|
||
const total = slices.reduce((sum, slice) => sum + slice.count, 0)
|
||
|
||
return (
|
||
<AnalyticsCardShell
|
||
title="Операции и задачи"
|
||
description="Статистика ревизий и фоновых jobs"
|
||
info="Данные из GET /v1/jobs и /v1/revisions."
|
||
>
|
||
<AnalyticsKpiRow
|
||
items={[
|
||
{
|
||
label: 'Ревизий',
|
||
value: loading ? '—' : String(revisions.length),
|
||
delta: { direction: 'neutral', label: 'в выборке', tone: 'muted' },
|
||
},
|
||
{
|
||
label: 'Активных задач',
|
||
value: loading ? '—' : String(running),
|
||
delta: {
|
||
direction: running > 0 ? 'up' : 'neutral',
|
||
label: running > 0 ? 'выполняются' : 'очередь пуста',
|
||
tone: (running > 0 ? 'warning' : 'muted') as 'warning' | 'muted',
|
||
},
|
||
},
|
||
{
|
||
label: 'С ошибкой',
|
||
value: loading ? '—' : String(failed),
|
||
delta: {
|
||
direction: failed > 0 ? 'down' : 'up',
|
||
label: failed > 0 ? 'требуют внимания' : 'в норме',
|
||
tone: failed > 0 ? 'destructive' : 'success',
|
||
},
|
||
},
|
||
]}
|
||
/>
|
||
{loading ? (
|
||
<div className="flex h-48 items-center justify-center text-sm text-muted-foreground">
|
||
Загрузка…
|
||
</div>
|
||
) : (
|
||
<ChartDonutMetric slices={slices} centerLabel="Задачи" centerValue={total} />
|
||
)}
|
||
</AnalyticsCardShell>
|
||
)
|
||
}
|