diff --git a/apps/web/src/components/agents/agent-fleet-data-grid.tsx b/apps/web/src/components/agents/agent-fleet-data-grid.tsx index 4db315a..26c6293 100644 --- a/apps/web/src/components/agents/agent-fleet-data-grid.tsx +++ b/apps/web/src/components/agents/agent-fleet-data-grid.tsx @@ -6,6 +6,10 @@ import type { Filter, FilterFieldConfig } from '@/components/reui/filters' import { ResourcePage } from '@/components/reui-kit' import { Badge } from '@/components/reui/badge' import { DataGridColumnHeader } from '@/components/reui/data-grid/data-grid-column-header' +import { + DataGridTableRowSelect, + DataGridTableRowSelectAll, +} from '@/components/reui/data-grid/data-grid-table' import { DataGridMutedCell, DataGridPrimaryCell, @@ -115,6 +119,18 @@ export function AgentFleetDataGrid({ const columns: ColumnDef[] = useMemo( () => [ + ...(enableRowSelection + ? [ + { + id: '__select__', + enableSorting: false, + enableResizing: false, + size: 44, + header: () => , + cell: ({ row }) => , + } as ColumnDef, + ] + : []), { accessorKey: 'name', size: 260, @@ -348,7 +364,7 @@ export function AgentFleetDataGrid({ }, }, ], - [approvePending, handleCopy, onApprove, onDelete, onSelect], + [approvePending, handleCopy, onApprove, onDelete, onSelect, enableRowSelection], ) return ( diff --git a/apps/web/src/components/agents/agents-fleet-kpis.ts b/apps/web/src/components/agents/agents-fleet-kpis.ts index 9d94a54..10af496 100644 --- a/apps/web/src/components/agents/agents-fleet-kpis.ts +++ b/apps/web/src/components/agents/agents-fleet-kpis.ts @@ -52,24 +52,24 @@ export function fleetKpiCards( return [ { id: 'pending', - label: 'Pending', + label: 'Ожидают', value: counts.pending, - hint: 'approve backlog', + hint: 'одобрение', icon: icons.pending, iconClassName: 'text-warning', variant: counts.pending > 0 ? 'warning' : 'default', }, { id: 'invited', - label: 'Invited', + label: 'Приглашённые', value: counts.invited, - hint: 'ожидают install', + hint: 'ждут установки', icon: icons.invited, iconClassName: 'text-info', }, { id: 'approved', - label: 'Approved', + label: 'Одобренные', value: counts.approved, hint: 'в парке', icon: icons.approved, @@ -77,9 +77,9 @@ export function fleetKpiCards( }, { id: 'stale', - label: 'Offline / stale', + label: 'Не на связи', value: counts.stale, - hint: '>24ч без seen', + hint: 'нет seen >24ч', icon: icons.stale, iconClassName: 'text-muted-foreground', variant: counts.stale > 0 ? 'warning' : 'default', diff --git a/apps/web/src/routes/_auth/agents/index.tsx b/apps/web/src/routes/_auth/agents/index.tsx index 94052e2..68e07d1 100644 --- a/apps/web/src/routes/_auth/agents/index.tsx +++ b/apps/web/src/routes/_auth/agents/index.tsx @@ -98,13 +98,14 @@ function parseAgentsSearch(search: Record): AgentsSearch { ? search.agent : undefined const add = searchToFlag(search.add) + const f = searchToFilters(search.f) return { view, agent, add, tab: searchToTab(search.tab, AGENT_TAB_IDS), q: searchToQ(search.q), - f: searchToFilters(search.f), + f: f.length > 0 ? f : undefined, } } diff --git a/apps/web/src/routes/_auth/index.tsx b/apps/web/src/routes/_auth/index.tsx index 6dcfb24..7de93e0 100644 --- a/apps/web/src/routes/_auth/index.tsx +++ b/apps/web/src/routes/_auth/index.tsx @@ -76,7 +76,7 @@ function DashboardPage() { }, { id: 'dropped', - label: 'Dropped', + label: 'Заблокировано', value: d?.packets_dropped ?? '—', hint: 'сумма counters', to: '/stats', @@ -86,7 +86,7 @@ function DashboardPage() { }, { id: 'accepted', - label: 'Accepted', + label: 'Пропущено', value: d?.packets_accepted ?? '—', hint: 'сумма counters', to: '/stats', @@ -110,7 +110,7 @@ function DashboardPage() { { id: 'agents', title: 'Агенты', - description: 'Enroll и approve', + description: 'Подключение и одобрение агентов', to: '/agents', icon: , iconClassName: 'text-info', @@ -118,7 +118,7 @@ function DashboardPage() { { id: 'lists', title: 'Списки', - description: 'Blocklists / sources', + description: 'Блок-листы и источники', to: '/lists', icon: , iconClassName: 'text-primary', @@ -126,7 +126,7 @@ function DashboardPage() { { id: 'rules', title: 'Правила', - description: 'Allow / deny policy', + description: 'Политика блокировки', to: '/rules', icon: , iconClassName: 'text-warning', diff --git a/apps/web/src/routes/_auth/lists/index.tsx b/apps/web/src/routes/_auth/lists/index.tsx index e486b72..82c9299 100644 --- a/apps/web/src/routes/_auth/lists/index.tsx +++ b/apps/web/src/routes/_auth/lists/index.tsx @@ -67,11 +67,12 @@ type ListsSearch = { /** URL-состояние страницы: create/tab/q/f (deep-link и refresh сохраняют вид). */ function parseListsSearch(search: Record): ListsSearch { + const f = searchToFilters(search.f) return { create: searchToFlag(search.create), tab: searchToTab(search.tab, LIST_TAB_IDS), q: searchToQ(search.q), - f: searchToFilters(search.f), + f: f.length > 0 ? f : undefined, } } diff --git a/apps/web/src/routes/_auth/rules/index.tsx b/apps/web/src/routes/_auth/rules/index.tsx index 96d1d7e..22b489a 100644 --- a/apps/web/src/routes/_auth/rules/index.tsx +++ b/apps/web/src/routes/_auth/rules/index.tsx @@ -37,10 +37,11 @@ type RulesSearch = { /** URL-состояние страницы: create/q/f (deep-link и refresh сохраняют вид). */ function parseRulesSearch(search: Record): RulesSearch { + const f = searchToFilters(search.f) return { create: searchToFlag(search.create), q: searchToQ(search.q), - f: searchToFilters(search.f), + f: f.length > 0 ? f : undefined, } } diff --git a/apps/web/src/routes/_auth/stats.tsx b/apps/web/src/routes/_auth/stats.tsx index 96eaecf..2f76a7d 100644 --- a/apps/web/src/routes/_auth/stats.tsx +++ b/apps/web/src/routes/_auth/stats.tsx @@ -48,8 +48,9 @@ type StatsSearch = { /** URL-состояние страницы: f (deep-link и refresh сохраняют вид). */ function parseStatsSearch(search: Record): StatsSearch { + const f = searchToFilters(search.f) return { - f: searchToFilters(search.f), + f: f.length > 0 ? f : undefined, } } diff --git a/packages/ui/src/components/command.tsx b/packages/ui/src/components/command.tsx index 3a7deab..f348bba 100644 --- a/packages/ui/src/components/command.tsx +++ b/packages/ui/src/components/command.tsx @@ -58,7 +58,8 @@ function CommandDialog({ )} showCloseButton={showCloseButton} > - {children} + {/* cmdk-компоненты требуют корень Command — без него useSyncExternalStore падает */} + {children} )