Update 1.2.2.2 beta

This commit is contained in:
MacRimi
2026-06-24 21:58:21 +02:00
parent 61b9fd12bb
commit 87a29f324b
5 changed files with 55 additions and 66 deletions

View File

@@ -1 +1 @@
fd5f754a35e9657ff4868dba0d5e22c0a9538794e5c176137c33e87f9554c587 ProxMenux-1.2.2.2-beta.AppImage
aa78161adc4e3c39ab9c20bdf94ca646745894e3ad09ea188e30997233d92f87 ProxMenux-1.2.2.2-beta.AppImage

View File

@@ -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(min3) / 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"

View File

@@ -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>
)
}

View File

@@ -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)