fix(ui): улучшить функциональность панели данных и заменить устаревшие компоненты
Docker images / prepare-release (push) Successful in 7s
Docker images / backend-image (push) Successful in 2m1s
Docker images / frontend-image (push) Successful in 2m7s
Docker images / updater-image (push) Successful in 41s
Docker images / notify-webhook (push) Has been skipped
Docker images / publish-release (push) Successful in 8s

This commit is contained in:
Denozordec
2026-06-30 22:36:00 +07:00
parent d3a2d38b37
commit d2de8d3188
16 changed files with 162 additions and 214 deletions
+21 -21
View File
@@ -3,6 +3,7 @@
import { useCallback, useEffect, useMemo, useState } from "react"
import { PageHeader } from "@/components/page-header"
import { DataPageCard } from "@/components/data-page-card"
import { DataPageToolbar, DataPageToolbarFrame } from "@/components/data-page-toolbar"
import { GreTunnelsDataGrid } from "@/components/data-grids/gre-tunnels-data-grid"
import { GrePoolsDataGrid } from "@/components/data-grids/gre-pools-data-grid"
import { FormField, FormToggle, SectionTitle, SegmentedControl } from "@/components/form-kit"
@@ -25,7 +26,7 @@ import {
} from "@/components/ui/dropdown-menu"
import { Flag } from "@/components/flag"
import {
PlusIcon, SearchIcon, RefreshCwIcon, MoreHorizontalIcon,
PlusIcon, RefreshCwIcon, MoreHorizontalIcon,
LockIcon, LockOpenIcon, ShieldCheckIcon, NetworkIcon,
EyeIcon, EyeOffIcon, ChevronDownIcon, ChevronRightIcon,
CodeXmlIcon, PencilIcon, PowerIcon, Trash2Icon, CopyIcon, CheckIcon,
@@ -454,23 +455,21 @@ export default function GrePage() {
{/* ── Tunnels ── */}
{pageTab === "tunnels" && (
<DataPageCard>
<div className="flex items-center gap-3 px-5 py-3 border-b flex-wrap">
<div className="flex items-center gap-1 rounded-md border border-border bg-muted/40 p-0.5">
{tunnelTabs.map((t) => (
<button key={t.value} onClick={() => setTabFilter(t.value)}
className={`flex items-center gap-1.5 rounded px-3 py-1 text-sm transition-colors ${tabFilter === t.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`}>
{t.label}
<span className="text-xs tabular-nums opacity-60">{t.count}</span>
</button>
))}
</div>
<div className="flex items-center gap-2 h-8 px-3 border border-input rounded-md bg-background min-w-[220px]">
<SearchIcon className="size-3.5 text-muted-foreground shrink-0" />
<input className="flex-1 bg-transparent outline-none placeholder:text-muted-foreground text-sm"
placeholder="Поиск по имени, IP…" value={search} onChange={(e) => setSearch(e.target.value)} />
</div>
<span className="text-sm text-muted-foreground ml-auto">{filtered.length} туннелей</span>
</div>
<DataPageToolbar
segmented={{
value: tabFilter,
onChange: setTabFilter,
options: tunnelTabs.map((t) => ({
value: t.value,
label: t.label,
count: t.count,
})),
}}
search={search}
onSearchChange={setSearch}
searchPlaceholder="Поиск по имени, IP…"
countLabel={`${filtered.length} туннелей`}
/>
<GreTunnelsDataGrid
tunnels={filtered}
@@ -484,12 +483,13 @@ export default function GrePage() {
{/* ── IP Pools ── */}
{pageTab === "pools" && (
<DataPageCard>
<div className="flex items-center justify-between px-5 py-3 border-b">
<DataPageToolbarFrame className="justify-between">
<span className="text-sm text-muted-foreground">{displayPools.length} пула</span>
<Button size="sm" variant="outline" onClick={() => { setPForm(defaultPoolForm); setPoolOpen(true) }}>
<PlusIcon className="size-4" />Добавить пул
<PlusIcon className="size-4" />
Добавить пул
</Button>
</div>
</DataPageToolbarFrame>
<GrePoolsDataGrid pools={displayPools} />
<div className="border-t px-5 py-4">