fix(web): открытие detail-роутов и паритет ReUI DataGrid с EvoBGP/CFDM
Sibling routes index+$id, ColumnHeader/PrimaryCell/StatusBadge/ConfirmDialog, tabs и таблица entries списков. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
import { cn } from '@evofw/ui/lib/utils'
|
||||
|
||||
const ACCENT_CLASS = {
|
||||
primary: 'font-medium text-primary',
|
||||
default: 'font-medium text-foreground',
|
||||
mono: 'font-mono text-sm text-primary',
|
||||
} as const
|
||||
|
||||
export function DataGridPrimaryCell({
|
||||
title,
|
||||
subtitle,
|
||||
accent = 'default',
|
||||
className,
|
||||
}: {
|
||||
title: ReactNode
|
||||
subtitle?: ReactNode
|
||||
accent?: keyof typeof ACCENT_CLASS
|
||||
className?: string
|
||||
}) {
|
||||
return (
|
||||
<div className={cn('flex min-w-0 flex-col gap-0.5', className)}>
|
||||
<span className={cn('truncate', ACCENT_CLASS[accent])}>{title}</span>
|
||||
{subtitle ? (
|
||||
<span className="truncate text-xs text-muted-foreground">{subtitle}</span>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function DataGridMutedCell({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}) {
|
||||
return (
|
||||
<span
|
||||
className={cn('whitespace-nowrap text-xs text-muted-foreground', className)}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -11,13 +11,24 @@ const STATUS_VARIANT: Record<string, BadgeVariant> = {
|
||||
synced: 'success-light',
|
||||
ok: 'success-light',
|
||||
up: 'success-light',
|
||||
enabled: 'success-light',
|
||||
approved: 'success-light',
|
||||
allow: 'success-light',
|
||||
pending_push: 'secondary',
|
||||
pending: 'warning-light',
|
||||
warning: 'warning-light',
|
||||
degraded: 'warning-light',
|
||||
conflict: 'destructive-light',
|
||||
error: 'destructive-light',
|
||||
expired: 'destructive-light',
|
||||
down: 'destructive-light',
|
||||
deny: 'destructive-light',
|
||||
revoked: 'secondary',
|
||||
disabled: 'secondary',
|
||||
static: 'secondary',
|
||||
domains: 'info-light',
|
||||
json_url: 'info-light',
|
||||
evobgp_community: 'info-light',
|
||||
unknown: 'outline',
|
||||
}
|
||||
|
||||
@@ -37,6 +48,13 @@ const STATUS_LABELS: Record<string, string> = {
|
||||
active: 'Активен',
|
||||
synced: 'Синхронизировано',
|
||||
pending_push: 'Ожидает отправки',
|
||||
pending: 'Pending',
|
||||
approved: 'Approved',
|
||||
revoked: 'Revoked',
|
||||
enabled: 'Включён',
|
||||
disabled: 'Выключен',
|
||||
allow: 'allow',
|
||||
deny: 'deny',
|
||||
conflict: 'Конфликт',
|
||||
error: 'Ошибка',
|
||||
ok: 'OK',
|
||||
@@ -45,6 +63,10 @@ const STATUS_LABELS: Record<string, string> = {
|
||||
degraded: 'Slow',
|
||||
down: 'Down',
|
||||
expired: 'Истёк',
|
||||
static: 'static',
|
||||
domains: 'domains',
|
||||
json_url: 'json_url',
|
||||
evobgp_community: 'evobgp_community',
|
||||
unknown: 'Неизвестно',
|
||||
}
|
||||
|
||||
@@ -60,8 +82,16 @@ export function StatusBadge({
|
||||
const variant = STATUS_VARIANT[status] ?? 'outline'
|
||||
const dotColor = DOT_COLOR[variant] ?? 'bg-muted-foreground'
|
||||
return (
|
||||
<Badge variant={variant} size="sm" radius="full" className={cn('gap-1.5', className)}>
|
||||
<span className={cn('size-1.5 shrink-0 rounded-full', dotColor)} aria-hidden />
|
||||
<Badge
|
||||
variant={variant}
|
||||
size="sm"
|
||||
radius="full"
|
||||
className={cn('gap-1.5', className)}
|
||||
>
|
||||
<span
|
||||
className={cn('size-1.5 shrink-0 rounded-full', dotColor)}
|
||||
aria-hidden
|
||||
/>
|
||||
{label ?? STATUS_LABELS[status] ?? status}
|
||||
</Badge>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user