feat(statistics): добавить BI-разрез и сводную матрицу
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
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 <[email protected]>
This commit is contained in:
@@ -5,7 +5,7 @@ import { Flag } from "@/components/flag"
|
||||
import { Badge } from "@/components/reui/badge"
|
||||
import { fmtBps, formatBytes } from "@/lib/fmt-rate"
|
||||
import { cn } from "@/lib/utils"
|
||||
import type { StatisticsBreakdownRow } from "@mmapp/contracts/statistics"
|
||||
import { STATISTICS_UNBOUND_USER_ID, type StatisticsBreakdownRow } from "@mmapp/contracts/statistics"
|
||||
|
||||
export type StatisticsSliceKind = "users" | "servers" | "interfaces" | "countries" | "services" | "asns"
|
||||
|
||||
@@ -15,13 +15,16 @@ export function StatisticsBreakdownDataGrid({
|
||||
selectedId,
|
||||
onRowClick,
|
||||
isLoading,
|
||||
density = "full",
|
||||
}: {
|
||||
rows: StatisticsBreakdownRow[]
|
||||
kind: StatisticsSliceKind
|
||||
selectedId?: string
|
||||
onRowClick?: (row: StatisticsBreakdownRow) => void
|
||||
isLoading?: boolean
|
||||
density?: "full" | "mini"
|
||||
}) {
|
||||
const mini = density === "mini"
|
||||
const columns: CompactDataGridColumn<StatisticsBreakdownRow>[] = [
|
||||
{
|
||||
id: "label",
|
||||
@@ -29,7 +32,9 @@ export function StatisticsBreakdownDataGrid({
|
||||
accessorKey: "label",
|
||||
cell: (row) => (
|
||||
<span className={cn("flex items-center gap-2", selectedId === row.id && "font-medium")}>
|
||||
{kind === "countries" && row.id !== "XX" ? <Flag code={row.id} size={16} /> : null}
|
||||
{kind === "countries" && row.id !== "XX" && row.id !== STATISTICS_UNBOUND_USER_ID ? (
|
||||
<Flag code={row.id} size={16} />
|
||||
) : null}
|
||||
<span className="truncate">{row.label || row.id}</span>
|
||||
{selectedId === row.id ? (
|
||||
<Badge variant="outline" size="sm">
|
||||
@@ -45,18 +50,24 @@ export function StatisticsBreakdownDataGrid({
|
||||
accessorKey: "bytes",
|
||||
cell: (row) => <span className="tabular-nums">{formatBytes(row.bytes)}</span>,
|
||||
},
|
||||
{
|
||||
id: "packets",
|
||||
header: "Пакеты",
|
||||
accessorKey: "packets",
|
||||
cell: (row) => <span className="tabular-nums">{row.packets.toLocaleString("ru-RU")}</span>,
|
||||
},
|
||||
{
|
||||
id: "bps",
|
||||
header: "Средний bitrate",
|
||||
accessorKey: "bps",
|
||||
cell: (row) => <span className="tabular-nums">{fmtBps(row.bps)}</span>,
|
||||
},
|
||||
...(!mini
|
||||
? [
|
||||
{
|
||||
id: "packets",
|
||||
header: "Пакеты",
|
||||
accessorKey: "packets" as const,
|
||||
cell: (row: StatisticsBreakdownRow) => (
|
||||
<span className="tabular-nums">{row.packets.toLocaleString("ru-RU")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "bps",
|
||||
header: "Средний bitrate",
|
||||
accessorKey: "bps" as const,
|
||||
cell: (row: StatisticsBreakdownRow) => <span className="tabular-nums">{fmtBps(row.bps)}</span>,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
id: "percent",
|
||||
header: "Доля",
|
||||
|
||||
Reference in New Issue
Block a user