mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-07-26 18:38:30 +00:00
Update 1.2.2.2 beta
This commit is contained in:
Binary file not shown.
@@ -1 +1 @@
|
||||
fd5f754a35e9657ff4868dba0d5e22c0a9538794e5c176137c33e87f9554c587 ProxMenux-1.2.2.2-beta.AppImage
|
||||
aa78161adc4e3c39ab9c20bdf94ca646745894e3ad09ea188e30997233d92f87 ProxMenux-1.2.2.2-beta.AppImage
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { Thermometer } from "lucide-react"
|
||||
import { Badge } from "./ui/badge"
|
||||
import { AreaChart, Area, ResponsiveContainer, Tooltip } from "recharts"
|
||||
import { AreaChart, Area, ResponsiveContainer, Tooltip, YAxis } from "recharts"
|
||||
import { fetchApi } from "@/lib/api-config"
|
||||
import { useDiskTempThresholds } from "@/lib/health-thresholds"
|
||||
|
||||
@@ -145,6 +145,18 @@ export function DiskTemperatureCard({
|
||||
<stop offset="100%" stopColor={lineColor} stopOpacity={0.02} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
{/* Y domain is computed the same way the detail modal
|
||||
does — floor(min−3) / ceil(max+3), floor at 0 — so
|
||||
the line shape here matches the bigger chart instead
|
||||
of recharts' auto-domain collapsing 24 → 29 °C into
|
||||
a near-flat line that doesn't look like the modal. */}
|
||||
<YAxis
|
||||
hide
|
||||
domain={[
|
||||
(dataMin: number) => Math.max(0, Math.floor(dataMin - 3)),
|
||||
(dataMax: number) => Math.ceil(dataMax + 3),
|
||||
]}
|
||||
/>
|
||||
<Tooltip content={<MiniTooltip />} cursor={{ stroke: lineColor, strokeOpacity: 0.3, strokeWidth: 1 }} />
|
||||
<Area
|
||||
type="monotone"
|
||||
|
||||
@@ -7180,14 +7180,15 @@ function FilesTree({ files, truncated }: { files: Array<{ path: string; size: nu
|
||||
// operator confirmation in the Complete restore flow.
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
function RollbackPlanView({ plan }: { plan: RollbackPlan }) {
|
||||
const hasDestructive = (plan.vms_to_remove?.length || 0) > 0
|
||||
|| (plan.lxcs_to_remove?.length || 0) > 0
|
||||
|| (plan.components_to_uninstall?.length || 0) > 0
|
||||
// The destructive "Not in backup — will be deleted on rollback"
|
||||
// block was removed: operators read it as an action ProxMenux
|
||||
// would take silently. We only show the "Configurations included
|
||||
// in backup" section now, which is purely informative.
|
||||
const hasRollback = (plan.vms_to_restore?.length || 0) > 0
|
||||
|| (plan.lxcs_to_restore?.length || 0) > 0
|
||||
|| (plan.components_to_reinstall?.length || 0) > 0
|
||||
|
||||
if (!hasDestructive && !hasRollback) {
|
||||
if (!hasRollback) {
|
||||
return (
|
||||
<div className="text-xs text-muted-foreground italic">
|
||||
No host-state differences detected — the backup state matches the current host (or the backup didn't include /etc/pve).
|
||||
@@ -7195,70 +7196,43 @@ function RollbackPlanView({ plan }: { plan: RollbackPlan }) {
|
||||
)
|
||||
}
|
||||
|
||||
const Pill = ({ children, tone }: { children: any; tone: "red" | "green" }) => (
|
||||
<code className={`font-mono ml-1 px-1.5 py-0.5 rounded border ${
|
||||
tone === "red"
|
||||
? "bg-red-500/10 border-red-500/30 text-red-300"
|
||||
: "bg-emerald-500/10 border-emerald-500/30 text-emerald-300"
|
||||
}`}>{children}</code>
|
||||
// Pill renders inline with proper flex wrapping so dozens of VM
|
||||
// IDs don't overflow the modal on mobile (previous version used
|
||||
// raw spaces between pills and any value past the viewport got
|
||||
// clipped).
|
||||
const Pill = ({ children }: { children: any }) => (
|
||||
<code className="font-mono px-1.5 py-0.5 rounded border bg-emerald-500/10 border-emerald-500/30 text-emerald-300 text-[11px]">
|
||||
{children}
|
||||
</code>
|
||||
)
|
||||
// Row uses flex-wrap + min-w-0 + gap so labels and pills flow to
|
||||
// a new line on narrow screens instead of pushing the card wider.
|
||||
const Row = ({ label, items }: { label: string; items: (string | number)[] }) => (
|
||||
<div className="flex flex-wrap items-center gap-x-2 gap-y-1.5 min-w-0">
|
||||
<span className="text-muted-foreground shrink-0">{label}</span>
|
||||
<div className="flex flex-wrap gap-1.5 min-w-0">
|
||||
{items.map((id) => <Pill key={id}>{id}</Pill>)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="space-y-3 text-xs">
|
||||
{hasDestructive && (
|
||||
<div className="rounded-md border border-red-500/40 bg-red-500/5 p-3 space-y-2">
|
||||
<div className="text-[11px] font-semibold uppercase tracking-wider text-red-400">
|
||||
Not in backup — will be deleted on rollback
|
||||
</div>
|
||||
{plan.vms_to_remove.length > 0 && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">VMs:</span>
|
||||
{plan.vms_to_remove.map((id) => <Pill key={id} tone="red">{id}</Pill>)}
|
||||
</div>
|
||||
)}
|
||||
{plan.lxcs_to_remove.length > 0 && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">LXCs:</span>
|
||||
{plan.lxcs_to_remove.map((id) => <Pill key={id} tone="red">{id}</Pill>)}
|
||||
</div>
|
||||
)}
|
||||
{plan.components_to_uninstall.length > 0 && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">Components:</span>
|
||||
{plan.components_to_uninstall.map((c) => <Pill key={c} tone="red">{c}</Pill>)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="rounded-md border border-emerald-500/40 bg-emerald-500/5 p-3 space-y-2 text-xs">
|
||||
<div className="text-[11px] font-semibold uppercase tracking-wider text-emerald-400">
|
||||
Configurations included in backup
|
||||
</div>
|
||||
{plan.vms_to_restore.length > 0 && (
|
||||
<Row label="VM configs:" items={plan.vms_to_restore} />
|
||||
)}
|
||||
|
||||
{hasRollback && (
|
||||
<div className="rounded-md border border-emerald-500/40 bg-emerald-500/5 p-3 space-y-2">
|
||||
<div className="text-[11px] font-semibold uppercase tracking-wider text-emerald-400">
|
||||
Configurations included in backup
|
||||
</div>
|
||||
{plan.vms_to_restore.length > 0 && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">VM configs:</span>
|
||||
{plan.vms_to_restore.map((id) => <Pill key={id} tone="green">{id}</Pill>)}
|
||||
</div>
|
||||
)}
|
||||
{plan.lxcs_to_restore.length > 0 && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">LXC configs:</span>
|
||||
{plan.lxcs_to_restore.map((id) => <Pill key={id} tone="green">{id}</Pill>)}
|
||||
</div>
|
||||
)}
|
||||
{plan.components_to_reinstall.length > 0 && (
|
||||
<div>
|
||||
<span className="text-muted-foreground">Components:</span>
|
||||
{plan.components_to_reinstall.map((c) => <Pill key={c} tone="green">{c}</Pill>)}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-[10px] text-muted-foreground pt-1">
|
||||
Only the /etc/pve config is restored — disk images stay where they live.
|
||||
</div>
|
||||
</div>
|
||||
{plan.lxcs_to_restore.length > 0 && (
|
||||
<Row label="LXC configs:" items={plan.lxcs_to_restore} />
|
||||
)}
|
||||
{plan.components_to_reinstall.length > 0 && (
|
||||
<Row label="Components:" items={plan.components_to_reinstall} />
|
||||
)}
|
||||
<div className="text-[10px] text-muted-foreground pt-1">
|
||||
Only the /etc/pve config is restored — disk images stay where they live.
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,7 +70,10 @@ const getStatusInfo = (temp: number) => {
|
||||
}
|
||||
|
||||
export function TemperatureDetailModal({ open, onOpenChange, liveTemperature }: TemperatureDetailModalProps) {
|
||||
const [timeframe, setTimeframe] = useState("hour")
|
||||
// Default to 24 h — matches the disk temperature modal and is the
|
||||
// useful timeframe for spotting trends; the 1-h view rarely tells
|
||||
// you anything that the live reading doesn't already show.
|
||||
const [timeframe, setTimeframe] = useState("day")
|
||||
const [data, setData] = useState<TempHistoryPoint[]>([])
|
||||
const [stats, setStats] = useState<TempStats>({ min: 0, max: 0, avg: 0, current: 0 })
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
Reference in New Issue
Block a user