feat(web): Lists/Rules UX parity с Агентами и правило kpi-hybrid
Hybrid row icons, row click, icon actions; DetailPanel header; ToggleGroup режима фильтра (settings-3). Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { createFileRoute, Link, useNavigate } from '@tanstack/react-router'
|
||||
import type { ColumnDef } from '@tanstack/react-table'
|
||||
import { Pencil, Plus, Trash2 } from 'lucide-react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { createFileRoute, useNavigate } from '@tanstack/react-router'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'sonner'
|
||||
import { Trash2 } from 'lucide-react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import type { ColumnDef } from '@tanstack/react-table'
|
||||
import type { Filter, FilterFieldConfig } from '@/components/reui/filters'
|
||||
import { PageHeader, PageShell, ResourcePage } from '@/components/reui-kit'
|
||||
import { DataGridColumnHeader } from '@/components/reui/data-grid/data-grid-column-header'
|
||||
@@ -11,6 +11,7 @@ import { DataGridPrimaryCell } from '@/components/data-grid-cell'
|
||||
import { StatusBadge } from '@/components/status-badge'
|
||||
import { Badge } from '@/components/reui/badge'
|
||||
import { ConfirmDialog } from '@/components/confirm-dialog'
|
||||
import { PolicySetIcon } from '@/components/rules/policy-set-icon'
|
||||
import { policySetsQueryOptions } from '@/queries'
|
||||
import { apiFetch } from '@/lib/api'
|
||||
import { Button } from '@evofw/ui/components/button'
|
||||
@@ -33,7 +34,7 @@ export const Route = createFileRoute('/_auth/rules/')({
|
||||
|
||||
/**
|
||||
* Policy sets list — ResourcePage (Frame + tabs + Filters + DataGrid).
|
||||
* Preview: https://reui.io/preview/base/data-grid-filtering-2
|
||||
* Preview: https://reui.io/preview/base/data-grid-filtering-2 · stats-12
|
||||
* Empty: https://reui.io/preview/base/empty-state-12
|
||||
* Create sheet: https://reui.io/preview/base/sheet-8
|
||||
*/
|
||||
@@ -119,17 +120,14 @@ function PolicySetsPage() {
|
||||
<DataGridColumnHeader column={column} title="Набор" />
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<Link
|
||||
to="/rules/$setId"
|
||||
params={{ setId: row.original.id }}
|
||||
className="min-w-0"
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<PolicySetIcon mode={row.original.policy_mode} />
|
||||
<DataGridPrimaryCell
|
||||
accent="primary"
|
||||
title={row.original.name}
|
||||
subtitle={row.original.description ?? undefined}
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -190,16 +188,18 @@ function PolicySetsPage() {
|
||||
cell: ({ row }) => (
|
||||
<div className="flex justify-end gap-1">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
render={
|
||||
<Link
|
||||
to="/rules/$setId"
|
||||
params={{ setId: row.original.id }}
|
||||
/>
|
||||
}
|
||||
size="icon-sm"
|
||||
variant="ghost"
|
||||
aria-label="Открыть"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
void navigate({
|
||||
to: '/rules/$setId',
|
||||
params: { setId: row.original.id },
|
||||
})
|
||||
}}
|
||||
>
|
||||
Открыть
|
||||
<Pencil className="size-3.5" />
|
||||
</Button>
|
||||
{row.original.id !== 'set-shared-default' ? (
|
||||
<Button
|
||||
@@ -207,7 +207,10 @@ function PolicySetsPage() {
|
||||
variant="ghost"
|
||||
className="text-destructive"
|
||||
aria-label="Удалить"
|
||||
onClick={() => setDeleteId(row.original.id)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setDeleteId(row.original.id)
|
||||
}}
|
||||
>
|
||||
<Trash2 className="size-3.5" />
|
||||
</Button>
|
||||
@@ -216,7 +219,14 @@ function PolicySetsPage() {
|
||||
),
|
||||
},
|
||||
],
|
||||
[],
|
||||
[navigate],
|
||||
)
|
||||
|
||||
const addButton = (
|
||||
<Button size="sm" onClick={() => setSheetOpen(true)}>
|
||||
<Plus data-icon="inline-start" />
|
||||
Новый набор
|
||||
</Button>
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -224,11 +234,7 @@ function PolicySetsPage() {
|
||||
<PageHeader
|
||||
title="Наборы правил"
|
||||
description="Именованные наборы назначаются агентам (можно несколько). Источник правила: список, CIDR или DNS."
|
||||
actions={
|
||||
<Button size="sm" onClick={() => setSheetOpen(true)}>
|
||||
Новый набор
|
||||
</Button>
|
||||
}
|
||||
actions={addButton}
|
||||
/>
|
||||
|
||||
<ResourcePage
|
||||
@@ -254,14 +260,13 @@ function PolicySetsPage() {
|
||||
isError={setsQ.isError}
|
||||
error={setsQ.error}
|
||||
onRetry={() => void setsQ.refetch()}
|
||||
onRowClick={(row) =>
|
||||
void navigate({ to: '/rules/$setId', params: { setId: row.id } })
|
||||
}
|
||||
emptyState={{
|
||||
title: 'Нет наборов',
|
||||
description: 'Создайте первый набор правил политики.',
|
||||
action: (
|
||||
<Button size="sm" onClick={() => setSheetOpen(true)}>
|
||||
Новый набор
|
||||
</Button>
|
||||
),
|
||||
action: addButton,
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user