Docker images / prepare-release (push) Successful in 10s
Docker images / backend-test (push) Successful in 2m23s
Docker images / frontend-image (push) Successful in 3m30s
Docker images / updater-image (push) Successful in 52s
Docker images / backend-image (push) Successful in 3m8s
Docker images / notify-webhook (push) Skipped
Docker images / publish-release (push) Successful in 14s
Сопоставить клиентов с ifIndex как на карте трафика, чтобы KPI пользователей не обнулялся. На экране — разрез остальных измерений и сводная матрица. Co-authored-by: Cursor <cursoragent@cursor.com>
58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
"use client"
|
|
|
|
import { Frame, FrameHeader, FramePanel, FrameTitle } from "@/components/reui/frame"
|
|
import {
|
|
StatisticsBreakdownDataGrid,
|
|
type StatisticsSliceKind,
|
|
} from "@/components/data-grids/statistics-breakdown-data-grid"
|
|
import { STATISTICS_DIMS } from "@/lib/statistics-dims"
|
|
import type { StatisticsBreakdownRow, StatisticsDto } from "@mmapp/contracts/statistics"
|
|
|
|
const MINI_ROWS = 12
|
|
|
|
function rowsForKind(data: StatisticsDto, kind: StatisticsSliceKind): StatisticsBreakdownRow[] {
|
|
if (kind === "users") return data.users
|
|
if (kind === "servers") return data.servers
|
|
if (kind === "interfaces") return data.interfaces
|
|
if (kind === "countries") return data.countries
|
|
if (kind === "services") return data.services
|
|
return data.asns
|
|
}
|
|
|
|
export function BreakdownDashboard({
|
|
data,
|
|
hidden,
|
|
selectedIdFor,
|
|
onRowClick,
|
|
isLoading,
|
|
}: {
|
|
data: StatisticsDto
|
|
hidden: Set<StatisticsSliceKind>
|
|
selectedIdFor: (kind: StatisticsSliceKind) => string | undefined
|
|
onRowClick: (kind: StatisticsSliceKind, row: StatisticsBreakdownRow) => void
|
|
isLoading?: boolean
|
|
}) {
|
|
const dims = STATISTICS_DIMS.filter((d) => !hidden.has(d.id))
|
|
return (
|
|
<div className="grid grid-cols-1 gap-4 p-4 md:grid-cols-2">
|
|
{dims.map((d) => (
|
|
<Frame key={d.id} dense>
|
|
<FrameHeader className="border-b">
|
|
<FrameTitle>{d.label}</FrameTitle>
|
|
</FrameHeader>
|
|
<FramePanel className="max-h-80 overflow-auto p-0">
|
|
<StatisticsBreakdownDataGrid
|
|
rows={rowsForKind(data, d.id).slice(0, MINI_ROWS)}
|
|
kind={d.id}
|
|
selectedId={selectedIdFor(d.id)}
|
|
onRowClick={(row) => onRowClick(d.id, row)}
|
|
isLoading={isLoading}
|
|
density="mini"
|
|
/>
|
|
</FramePanel>
|
|
</Frame>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|