fix(web): KPI в DetailPanel через KpiStatGrid hybrid (stats-12)
Отдельные карточки с icon tile, крупным value и Badge hint — как на дашборде. Списки, агенты, правила. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -226,24 +226,31 @@ function AgentDetailPage() {
|
||||
{
|
||||
id: 'dropped',
|
||||
icon: <BanIcon aria-hidden />,
|
||||
iconClassName: 'text-warning',
|
||||
label: 'Dropped',
|
||||
description: String(a.last_apply_packets_dropped ?? 0),
|
||||
hint: 'сумма counters',
|
||||
variant: 'warning',
|
||||
},
|
||||
{
|
||||
id: 'accepted',
|
||||
icon: <CheckCircle2Icon aria-hidden />,
|
||||
iconClassName: 'text-success',
|
||||
label: 'Accepted',
|
||||
description: String(a.last_apply_packets_accepted ?? 0),
|
||||
hint: 'сумма counters',
|
||||
},
|
||||
{
|
||||
id: 'kernel',
|
||||
icon: <CpuIcon aria-hidden />,
|
||||
iconClassName: 'text-info',
|
||||
label: 'Kernel',
|
||||
description: a.last_apply_kernel_method ?? '—',
|
||||
},
|
||||
{
|
||||
id: 'apply',
|
||||
icon: <ClockIcon aria-hidden />,
|
||||
iconClassName: 'text-primary',
|
||||
label: 'Last apply',
|
||||
description: a.last_apply_at ?? '—',
|
||||
},
|
||||
|
||||
@@ -82,7 +82,7 @@ type ListItem = {
|
||||
* Lists — master-detail (ReUI PRO composition).
|
||||
* Catalog: https://reui.io/preview/base/list-9
|
||||
* Entries: https://reui.io/preview/base/data-grid-filtering-2
|
||||
* KPI: https://reui.io/preview/base/stats-7
|
||||
* KPI: https://reui.io/preview/base/stats-12 (KpiStatGrid hybrid)
|
||||
* Sheet: https://reui.io/preview/base/sheet-1 · sheet-8
|
||||
* Empty: https://reui.io/preview/base/empty-state-12
|
||||
*/
|
||||
@@ -461,27 +461,38 @@ function ListsPage() {
|
||||
{
|
||||
id: 'count',
|
||||
icon: <HashIcon aria-hidden />,
|
||||
iconClassName: 'text-info',
|
||||
label: 'Записей',
|
||||
description: String(entryItems.length),
|
||||
hint: manual ? 'ручной список' : 'внешний источник',
|
||||
},
|
||||
{
|
||||
id: 'type',
|
||||
icon: <TagIcon aria-hidden />,
|
||||
iconClassName: 'text-primary',
|
||||
label: 'Источник',
|
||||
description:
|
||||
detail.type === 'json_url'
|
||||
? 'JSON'
|
||||
: detail.type === 'evobgp_community'
|
||||
? 'EvoBGP'
|
||||
: 'Ручной',
|
||||
hint:
|
||||
detail.type === 'json_url'
|
||||
? 'JSON по URL'
|
||||
: detail.type === 'evobgp_community'
|
||||
? 'EvoBGP community'
|
||||
: 'Ручной',
|
||||
? 'community prefixes'
|
||||
: 'IP / CIDR / домен / список',
|
||||
},
|
||||
{
|
||||
id: 'cidrs',
|
||||
icon: <RefreshCwIcon aria-hidden />,
|
||||
iconClassName: 'text-success',
|
||||
label: 'CIDR в политике',
|
||||
description: String(
|
||||
detail.entry_count ?? detail.entries.length,
|
||||
),
|
||||
hint: 'materialized',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -410,20 +410,25 @@ function PolicySetDetailPage() {
|
||||
{
|
||||
id: 'rules',
|
||||
icon: <ShieldIcon aria-hidden />,
|
||||
iconClassName: 'text-info',
|
||||
label: 'Правила',
|
||||
description: String(set.rules_count ?? rules.length),
|
||||
},
|
||||
{
|
||||
id: 'agents',
|
||||
icon: <UsersIcon aria-hidden />,
|
||||
iconClassName: 'text-primary',
|
||||
label: 'Агенты',
|
||||
description: String(set.agents_count ?? assignedIds.length),
|
||||
hint: 'назначено',
|
||||
},
|
||||
{
|
||||
id: 'status',
|
||||
icon: <ListIcon aria-hidden />,
|
||||
iconClassName: set.enabled ? 'text-success' : 'text-muted-foreground',
|
||||
label: 'Статус',
|
||||
description: set.enabled ? 'Включён' : 'Выключен',
|
||||
hint: set.enabled ? 'active' : 'disabled',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user