fix(ui): раскрывать предупреждения ресурсов порциями

This commit is contained in:
Denozordec committed 2026-10-04 03:00:32 +07:00
1 parent 2762f073a0
commit ab334764cf
6 files changed
+77 -28

No files matched your search

+29 -26
View File
@@ -870,6 +870,34 @@ function SortIcon({ k, sortKey, sortAsc }: { k: ResSortKey; sortKey: ResSortKey;
type ResTypeFilter = "all" | "jump-host" | "exit-node" | "home-router"
function ResourceWarnings({ rows }: { rows: UptimeResourceRow[] }) {
const [expanded, setExpanded] = useState(false)
const [visible, setVisible] = useState(55)
if (!rows.length) return null
function renderRow(row: UptimeResourceRow) {
const issues: string[] = []
if (row.cpu >= 85) issues.push(`CPU ${row.cpu}%`)
if (row.ramPct >= 85) issues.push(`RAM ${row.ramPct}%`)
if (row.hddPct >= 85) issues.push(`HDD ${row.hddPct}%`)
if ((row.temp ?? 0) >= 70) issues.push(`${row.temp}°C`)
return <span key={row.serverId} data-resource-warning={row.serverId} className="inline-flex items-center gap-1 text-[11px] font-mono rounded border border-destructive/30 bg-destructive/10 px-2 py-0.5">
<Flag code={row.server.country} size={10} />{row.server.name} — {issues.join(", ")}
</span>
}
return <Alert variant="destructive">
<ServerCrashIcon />
<AlertTitle className="text-xs mb-1">Серверов с предупреждениями: {rows.length}</AlertTitle>
<AlertDescription>
<div className="flex flex-wrap gap-1.5">{rows.slice(0, 5).map(renderRow)}</div>
{rows.length > 5 && <details onToggle={event => { setExpanded(event.currentTarget.open); if (!event.currentTarget.open) setVisible(55) }}>
<summary className="cursor-pointer rounded-md py-2 text-xs focus-visible:ring-2 focus-visible:ring-ring">Ещё {rows.length - 5}</summary>
{expanded && <div className="flex flex-wrap gap-1.5">{rows.slice(5, visible).map(renderRow)}</div>}
{expanded && rows.length > visible && <Button type="button" variant="ghost" size="sm" onClick={() => setVisible(count => Math.min(count + 50, rows.length))}>Показать ещё {Math.min(50, rows.length - visible)}</Button>}
</details>}
</AlertDescription>
</Alert>
}
function ResourcesTab({ resources, serversList, liveApi }: { resources: ServerResource[]; serversList: Server[]; liveApi?: boolean }) {
const { resource, setResourceSearch: setResSearch, setResourceType: setTypeFilter, resetResources } = useUptimeUrlState()
const { search: resSearch, type: typeFilter, error: resourceError } = resource
@@ -944,32 +972,7 @@ function ResourcesTab({ resources, serversList, liveApi }: { resources: ServerRe
<div className="p-6 flex flex-col gap-4">
{/* ── Alert banner ──────────────────────────────────────────────────── */}
{alerts.length > 0 && (
<Alert variant="destructive">
<ServerCrashIcon />
<AlertTitle className="text-xs mb-1">
{alerts.length} {alerts.length === 1 ? "сервер требует внимания" : "сервера требуют внимания"}
</AlertTitle>
<AlertDescription>
<div className="flex flex-wrap gap-1.5">
{alerts.map(r => {
const s = r.server
const issues: string[] = []
if (r.cpu >= 85) issues.push(`CPU ${r.cpu}%`)
if (r.ramPct >= 85) issues.push(`RAM ${r.ramPct}%`)
if (r.hddPct >= 85) issues.push(`HDD ${r.hddPct}%`)
if ((r.temp ?? 0) >= 70) issues.push(`${r.temp}°C`)
return (
<span key={r.serverId} className="inline-flex items-center gap-1 text-[11px] font-mono rounded border border-destructive/30 bg-destructive/10 px-2 py-0.5">
<Flag code={s.country} size={10} />
{s.name} — {issues.join(", ")}
</span>
)
})}
</div>
</AlertDescription>
</Alert>
)}
<ResourceWarnings rows={alerts} />
<KpiStatGrid
aria-label="Сводка ресурсов"