mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-06-11 19:07:01 +00:00
Add new beta 1.2.2.1
This commit is contained in:
Binary file not shown.
@@ -1 +1 @@
|
||||
e0128ac327ea74b645b37bcfab03aa744f067a355f9960a822b411c6ac75cb02 ProxMenux-1.2.2.AppImage
|
||||
8ea86a03ea86d45050d4e24e6432e022f76d805eeaaeeab3ee376ebaa48da52a ProxMenux-1.2.2.1-beta.AppImage
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "./ui/dialog"
|
||||
import { ScrollArea } from "./ui/scroll-area"
|
||||
import { Activity, FileText, HardDrive, Clock } from "lucide-react"
|
||||
import { Activity, FileText, HardDrive, Clock, Info } from "lucide-react"
|
||||
import { fetchApi } from "@/lib/api-config"
|
||||
|
||||
interface ProcessDetail {
|
||||
@@ -78,8 +78,17 @@ export function ProcessInfoModal({ pid, accent, onClose }: ProcessInfoModalProps
|
||||
const [data, setData] = useState<ProcessDetail | null>(null)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [exited, setExited] = useState(false)
|
||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
|
||||
const open = pid != null
|
||||
|
||||
const stopPolling = () => {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current)
|
||||
intervalRef.current = null
|
||||
}
|
||||
}
|
||||
|
||||
const fetchDetail = async (silent = false) => {
|
||||
if (pid == null) return
|
||||
if (!silent) setLoading(true)
|
||||
@@ -88,11 +97,16 @@ export function ProcessInfoModal({ pid, accent, onClose }: ProcessInfoModalProps
|
||||
const res = await fetchApi<ProcessDetail>(`/api/processes/${pid}`)
|
||||
setData(res)
|
||||
} catch (e: any) {
|
||||
// 404 means the process exited while the modal was open — surface a
|
||||
// clear message instead of stale data, but don't auto-close (user may
|
||||
// want to read the last snapshot).
|
||||
setError(e?.message?.includes("404") ? "Process exited" : (e?.message || "Failed to fetch process"))
|
||||
if (e?.message?.includes("404")) setData(null)
|
||||
// 404 = the process exited while the modal was open. Expected for
|
||||
// short-lived helpers (pct exec, backup subprocesses, the `ps` snapshot
|
||||
// itself). Keep the last good snapshot on screen, stop polling, and
|
||||
// surface an info banner — NOT an error — so it doesn't look like a bug.
|
||||
if (e?.message?.includes("404")) {
|
||||
setExited(true)
|
||||
stopPolling()
|
||||
} else {
|
||||
setError(e?.message || "Failed to fetch process")
|
||||
}
|
||||
} finally {
|
||||
if (!silent) setLoading(false)
|
||||
}
|
||||
@@ -102,11 +116,14 @@ export function ProcessInfoModal({ pid, accent, onClose }: ProcessInfoModalProps
|
||||
if (pid == null) {
|
||||
setData(null)
|
||||
setError(null)
|
||||
setExited(false)
|
||||
stopPolling()
|
||||
return
|
||||
}
|
||||
setExited(false)
|
||||
fetchDetail()
|
||||
const id = setInterval(() => fetchDetail(true), REFRESH_MS)
|
||||
return () => clearInterval(id)
|
||||
intervalRef.current = setInterval(() => fetchDetail(true), REFRESH_MS)
|
||||
return () => stopPolling()
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pid])
|
||||
|
||||
@@ -123,10 +140,28 @@ export function ProcessInfoModal({ pid, accent, onClose }: ProcessInfoModalProps
|
||||
<span className="text-xs text-muted-foreground font-mono flex-shrink-0">PID {pid}</span>
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-xs">
|
||||
Live snapshot from <span className="font-mono">/proc/{pid}</span>. Auto-refreshes every {REFRESH_MS / 1000} s while open.
|
||||
{exited ? (
|
||||
<>Last snapshot from <span className="font-mono">/proc/{pid}</span> before the process finished.</>
|
||||
) : (
|
||||
<>Live snapshot from <span className="font-mono">/proc/{pid}</span>. Auto-refreshes every {REFRESH_MS / 1000} s while open.</>
|
||||
)}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{/* Info banner when the process has finished. Amber, not red — this is
|
||||
expected behavior for short-lived processes, not an error. */}
|
||||
{exited && (
|
||||
<div className="flex items-start gap-2 px-3 py-2 rounded-md border border-amber-500/30 bg-amber-500/10 text-xs text-amber-300">
|
||||
<Info className="h-4 w-4 flex-shrink-0 mt-0.5" />
|
||||
<div>
|
||||
<div className="font-medium text-amber-200">This process has finished</div>
|
||||
<div className="text-amber-300/80 mt-0.5">
|
||||
It was likely a short-lived helper (a script, a <span className="font-mono">pct exec</span>, or a one-shot command) that completed while the modal was open. The data below is the last snapshot captured before it exited — not a stale or broken read.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && !data ? (
|
||||
<div className="text-sm text-red-500 py-4">{error}</div>
|
||||
) : !data ? (
|
||||
@@ -134,11 +169,11 @@ export function ProcessInfoModal({ pid, accent, onClose }: ProcessInfoModalProps
|
||||
{loading ? "Loading…" : "—"}
|
||||
</div>
|
||||
) : (
|
||||
<ScrollArea className="max-h-[480px] pr-2">
|
||||
<ScrollArea className={`max-h-[480px] pr-2 ${exited ? "opacity-75" : ""}`}>
|
||||
<div className="space-y-4">
|
||||
{/* Overview */}
|
||||
<Section icon={<Activity className="h-4 w-4 text-blue-400" />} title="Overview">
|
||||
<Row label="State" value={stateLabel(data.state)} />
|
||||
<Row label="State" value={exited ? "Exited" : stateLabel(data.state)} />
|
||||
<Row label="Parent" value={data.parent_name ? `${data.parent_name} (PID ${data.ppid})` : `PID ${data.ppid}`} mono />
|
||||
<Row label="Threads" value={String(data.threads)} mono />
|
||||
<Row label="Open FDs" value={data.fd_count != null ? String(data.fd_count) : "—"} mono />
|
||||
@@ -176,7 +211,7 @@ export function ProcessInfoModal({ pid, accent, onClose }: ProcessInfoModalProps
|
||||
|
||||
{data?.captured_at && (
|
||||
<div className="text-[10px] text-muted-foreground text-right mt-1">
|
||||
Captured {new Date(data.captured_at * 1000).toLocaleTimeString()}
|
||||
{exited ? "Last seen" : "Captured"} {new Date(data.captured_at * 1000).toLocaleTimeString()}
|
||||
{error ? ` · ${error}` : ""}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -216,17 +216,37 @@ export const CHANGELOG: Record<string, ReleaseNote> = {
|
||||
}
|
||||
|
||||
const CURRENT_VERSION_FEATURES = [
|
||||
{
|
||||
icon: <Sliders className="h-5 w-5" />,
|
||||
text: "Dashboard header restyle - The Overview, Storage, Network and VMs & LXCs tabs now lead with a unified card design: circular gauges paired with mini progress bars, and a clearer headline-plus-pill layout for counts. CPU Usage and Memory cards also expose a User / System and Used / Cached breakdown under the gauge",
|
||||
},
|
||||
{
|
||||
icon: <Activity className="h-5 w-5" />,
|
||||
text: "Header Critical badge now respects dismissals (#228) - Permanently silencing every critical alert in a category used to leave the badge stuck on Critical even though the popup correctly reported 0 critical. The rollup that drives /api/system-info now runs a dismiss-aware pass over every category, so the badge, the popup and any API consumer all see the same view",
|
||||
text: "Top processes drill-down - Click the CPU Usage or Memory cards on the Overview tab to open a sortable top-25 list of processes by %CPU or RSS, then click any row for a live per-process detail modal with state, command line, resource usage and lifetime",
|
||||
},
|
||||
{
|
||||
icon: <HardDrive className="h-5 w-5" />,
|
||||
text: "Storage and Network refinements - Storage Used now leads the Storage tab card, Network Status cells stack label-over-value so long hostnames and IPv6 DNS no longer truncate, and the 24 h CPU and Network charts smooth into 5-minute buckets",
|
||||
},
|
||||
{
|
||||
icon: <Cpu className="h-5 w-5" />,
|
||||
text: "Coral on non-Debian LXCs - The Coral LXC installer now detects Alpine / Arch / RHEL / SUSE containers and offers an opt-in passthrough-only mode, so Frigate Docker and other apps bundling their own libedgetpu runtime can wire the device through without aborting",
|
||||
},
|
||||
{
|
||||
icon: <Wrench className="h-5 w-5" />,
|
||||
text: "Coral PCIe driver false-positive update fix - The installer now records the upstream feranick release tag on disk, so the update detector compares like-for-like and stops firing a phantom 'driver update available' notification right after a fresh install",
|
||||
},
|
||||
{
|
||||
icon: <RefreshCw className="h-5 w-5" />,
|
||||
text: "Auto-reconcile of stale alerts - Errors for resources that no longer exist now auto-clear within the regular cleanup cycle. New cases: a PVE storage removed via pvesm, an NFS/CIFS share whose mount target is no longer in /proc/mounts (the lazy-umount case reported in the field), and LXC mount-capacity alerts whose CT has been deleted",
|
||||
text: "Auto-reconcile of stale alerts - Errors for resources that no longer exist auto-clear within the regular cleanup cycle. New cases: a PVE storage removed via pvesm, an NFS/CIFS share whose mount target is gone from /proc/mounts, and LXC mount-capacity alerts for a deleted CT",
|
||||
},
|
||||
{
|
||||
icon: <Shield className="h-5 w-5" />,
|
||||
text: "Header Critical badge respects dismissals (#228) - Permanently silencing every critical alert in a category now also clears the top-right badge, so the header pill and the bottom popup always agree on the count",
|
||||
},
|
||||
{
|
||||
icon: <Bell className="h-5 w-5" />,
|
||||
text: "Notification Send Test buttons unified (#226) - All five channel Send Test buttons (Telegram, Gotify, Discord, Email, Apprise) now sit on the left side and carry their channel's brand colour with white text, instead of Apprise being the right-aligned cyan outlier",
|
||||
text: "Notification Send Test buttons unified (#226) - All five channel Send Test buttons (Telegram, Gotify, Discord, Email, Apprise) now sit on the left and carry their channel's brand colour, instead of Apprise being the right-aligned cyan outlier",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user