Init 2
This commit is contained in:
+43
-14
@@ -15,6 +15,8 @@ interface BackendServer {
|
||||
useSsl: boolean; verifySsl: boolean; username: string; password: string
|
||||
type: ServerType; site: string; country: string; asn: string
|
||||
comment: string; enabled: boolean
|
||||
lanSubnet: string
|
||||
wanUplinks: WanUplink[]
|
||||
status: "online" | "offline" | null; latency: number | null
|
||||
os: string | null; model: string | null; uptime: string | null
|
||||
cpuLoad: number | null; freeMemory: number | null; totalMemory: number | null
|
||||
@@ -39,10 +41,14 @@ function toFrontend(s: BackendServer): Server {
|
||||
latency: s.latency != null ? Math.round(s.latency) : null,
|
||||
sessions: s.sessions ?? 0,
|
||||
comment: s.comment || undefined,
|
||||
lanSubnet: s.lanSubnet || undefined,
|
||||
wanUplinks: Array.isArray(s.wanUplinks) && s.wanUplinks.length ? s.wanUplinks : undefined,
|
||||
// carry extra fields needed for expanded view
|
||||
uptime: s.uptime ?? undefined,
|
||||
cpuLoad: s.cpuLoad ?? undefined,
|
||||
polledAt: s.polledAt ?? undefined,
|
||||
uptime: s.uptime ?? undefined,
|
||||
cpuLoad: s.cpuLoad ?? undefined,
|
||||
freeMemory: s.freeMemory ?? undefined,
|
||||
totalMemory: s.totalMemory ?? undefined,
|
||||
polledAt: s.polledAt ?? undefined,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,10 +119,10 @@ const ROS_FEATURES: RosFeature[] = [
|
||||
function RosBadge({ os }: { os: string }) {
|
||||
const v = rosVer(os)
|
||||
const cls = v >= 715
|
||||
? "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 border-emerald-500/20"
|
||||
? "bg-[var(--status-online-bg)] text-[var(--status-online-fg)] border-current/20"
|
||||
: v >= 710
|
||||
? "bg-amber-500/10 text-amber-600 dark:text-amber-400 border-amber-500/20"
|
||||
: "bg-red-500/10 text-red-600 dark:text-red-400 border-red-500/20"
|
||||
? "bg-[var(--status-degraded-bg)] text-[var(--status-degraded-fg)] border-current/20"
|
||||
: "bg-[var(--status-offline-bg)] text-[var(--status-offline-fg)] border-current/20"
|
||||
return (
|
||||
<span className={cn("text-xs font-mono border rounded px-2 py-0.5", cls)}>
|
||||
{os}
|
||||
@@ -390,8 +396,10 @@ export default function ServersPage() {
|
||||
|
||||
useEffect(() => {
|
||||
if (mode !== "live") {
|
||||
setServerList(initialServers)
|
||||
setBackendOk(false)
|
||||
queueMicrotask(() => {
|
||||
setServerList(initialServers)
|
||||
setBackendOk(false)
|
||||
})
|
||||
return
|
||||
}
|
||||
apiFetch<BackendServer[]>("/api/servers")
|
||||
@@ -437,6 +445,11 @@ export default function ServersPage() {
|
||||
port: String(full.port ?? 443),
|
||||
proto: full.useSsl ? "https" : "http",
|
||||
verifySsl: full.verifySsl ?? false,
|
||||
lanSubnet: full.lanSubnet ?? prev.lanSubnet,
|
||||
wanUplinks:
|
||||
Array.isArray(full.wanUplinks) && full.wanUplinks.length
|
||||
? JSON.parse(JSON.stringify(full.wanUplinks))
|
||||
: prev.wanUplinks,
|
||||
}))
|
||||
} catch {
|
||||
// ignore — user can fill in manually
|
||||
@@ -459,6 +472,8 @@ export default function ServersPage() {
|
||||
asn: form.asn,
|
||||
comment: form.comment,
|
||||
enabled: form.enabled,
|
||||
lanSubnet: form.lanSubnet.trim(),
|
||||
wanUplinks: form.type === "home-router" ? form.wanUplinks : [],
|
||||
}
|
||||
|
||||
if (isLive) {
|
||||
@@ -484,9 +499,19 @@ export default function ServersPage() {
|
||||
if (sheetMode === "edit" && editingId) {
|
||||
setServerList(list => list.map(s =>
|
||||
s.id === editingId
|
||||
? { ...s, name: form.name, type: form.type, site: form.site, country: form.country,
|
||||
host: form.host, asn: form.asn, comment: form.comment,
|
||||
status: form.enabled ? (s.status === "offline" ? "online" : s.status) : "offline" }
|
||||
? {
|
||||
...s,
|
||||
name: form.name,
|
||||
type: form.type,
|
||||
site: form.site,
|
||||
country: form.country,
|
||||
host: form.host,
|
||||
asn: form.asn,
|
||||
comment: form.comment,
|
||||
lanSubnet: form.lanSubnet || undefined,
|
||||
wanUplinks: form.type === "home-router" ? form.wanUplinks : undefined,
|
||||
status: form.enabled ? (s.status === "offline" ? "online" : s.status) : "offline",
|
||||
}
|
||||
: s
|
||||
))
|
||||
} else {
|
||||
@@ -497,6 +522,8 @@ export default function ServersPage() {
|
||||
status: form.enabled ? "online" : "offline",
|
||||
enabled: form.enabled, latency: null, sessions: 0,
|
||||
comment: form.comment || undefined,
|
||||
lanSubnet: form.lanSubnet || undefined,
|
||||
wanUplinks: form.type === "home-router" ? form.wanUplinks : undefined,
|
||||
}])
|
||||
}
|
||||
}
|
||||
@@ -764,7 +791,7 @@ export default function ServersPage() {
|
||||
</td>
|
||||
<td className={cn("px-4 py-3 font-mono text-right text-sm",
|
||||
s.latency == null ? "text-muted-foreground"
|
||||
: s.latency > 60 ? "text-amber-500" : "")}>
|
||||
: s.latency > 60 ? "text-[var(--status-degraded-fg)]" : "")}>
|
||||
{s.latency == null ? "—" : `${s.latency} мс`}
|
||||
</td>
|
||||
<td className="px-4 py-3"><StatusBadge status={s.status} /></td>
|
||||
@@ -1068,12 +1095,14 @@ export default function ServersPage() {
|
||||
: <><WifiIcon className="size-4" />Проверить подключение</>}
|
||||
</Button>
|
||||
{testState === "ok" && (
|
||||
<div className="flex items-start gap-2 rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-2 text-xs text-emerald-400">
|
||||
<div className="flex items-start gap-2 rounded-md border border-current/25 px-3 py-2 text-xs"
|
||||
style={{ background: "var(--status-online-bg)", color: "var(--status-online-fg)" }}>
|
||||
<CheckCircleIcon className="size-3.5 shrink-0 mt-0.5" /><span>{testMsg}</span>
|
||||
</div>
|
||||
)}
|
||||
{testState === "error" && (
|
||||
<div className="flex items-start gap-2 rounded-md border border-red-500/30 bg-red-500/10 px-3 py-2 text-xs text-red-400">
|
||||
<div className="flex items-start gap-2 rounded-md border border-current/25 px-3 py-2 text-xs"
|
||||
style={{ background: "var(--status-offline-bg)", color: "var(--status-offline-fg)" }}>
|
||||
<XCircleIcon className="size-3.5 shrink-0 mt-0.5" /><span>{testMsg}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user