Disks: one toggle opens SMART for every drive, remembered per device
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
4b8a2b15ed
commit
b6502ba362
+8
-4
@@ -73,8 +73,10 @@ function SmartPanel({ dev, rotational }: { dev: string; rotational: boolean }) {
|
||||
}
|
||||
|
||||
// ---- device card ----
|
||||
function DeviceCard({ d, live }: { d: StorageDevice; live?: { read_bps: number; write_bps: number; util_pct: number } }) {
|
||||
const [open, setOpen] = useState(false)
|
||||
function DeviceCard({ d, live, forceOpen }: { d: StorageDevice; live?: { read_bps: number; write_bps: number; util_pct: number }; forceOpen: boolean | null }) {
|
||||
const [own, setOwn] = useState(false)
|
||||
const open = forceOpen ?? own
|
||||
const setOpen = (v: boolean) => setOwn(v)
|
||||
return (
|
||||
<section className="card disk">
|
||||
<div className="sub-head">
|
||||
@@ -93,7 +95,7 @@ function DeviceCard({ d, live }: { d: StorageDevice; live?: { read_bps: number;
|
||||
</div>
|
||||
))}
|
||||
{d.parts.length === 0 && <div className="muted">No partitions.</div>}
|
||||
<div className="svc-actions"><button className="btn" onClick={() => setOpen(!open)}>{open ? 'Hide SMART' : 'SMART'}</button></div>
|
||||
{forceOpen === null && <div className="svc-actions"><button className="btn" onClick={() => setOpen(!open)}>{open ? 'Hide SMART' : 'SMART'}</button></div>}
|
||||
{open && <SmartPanel dev={d.name} rotational={d.rotational} />}
|
||||
</section>
|
||||
)
|
||||
@@ -179,6 +181,7 @@ export default function Disks() {
|
||||
const [live, setLive] = useState<Sample | null>(null)
|
||||
const [err, setErr] = useState('')
|
||||
const [task, setTask] = useState<string | null>(null)
|
||||
const [allSmart, setAllSmart] = useState<boolean>(() => localStorage.getItem('hamlab.disks.smart') === '1')
|
||||
const rate = useRefreshMs()
|
||||
|
||||
const load = useCallback(async () => {
|
||||
@@ -205,13 +208,14 @@ export default function Disks() {
|
||||
<div className="dash-bar">
|
||||
<h2 className="section">Devices · {devs.length}</h2>
|
||||
<span className="spacer" />
|
||||
{hasSmart && <button className={'chip' + (allSmart ? ' on' : '')} title="show SMART for every drive" onClick={() => { const v = !allSmart; setAllSmart(v); localStorage.setItem('hamlab.disks.smart', v ? '1' : '0') }}>{allSmart ? 'SMART: all open' : 'SMART: show all'}</button>}
|
||||
{!hasSmart && <Btn className="btn" onClick={async () => { try { const t = await api.installPackages(['smartmontools']); setTask(t.id) } catch (e) { toast(e instanceof Error ? e.message : 'failed', 'err') } }}>Install smartmontools</Btn>}
|
||||
<Btn className="btn" title="reload" onClick={load}>↻</Btn>
|
||||
</div>
|
||||
{!hasSmart && <div className="notice">SMART health needs smartmontools on this host. Install it with the button, then reload.</div>}
|
||||
{task && <TaskOutput id={task} onDone={(t) => { toast(`${t.title}: ${t.exit_code === 0 ? 'finished' : `exited ${t.exit_code}`}`, t.exit_code === 0 ? 'ok' : 'err'); load() }} />}
|
||||
<div className="cards">
|
||||
{devs.map((d) => <DeviceCard key={d.name} d={d} live={liveFor(d.name)} />)}
|
||||
{devs.map((d) => <DeviceCard key={d.name} d={d} live={liveFor(d.name)} forceOpen={allSmart ? true : null} />)}
|
||||
</div>
|
||||
|
||||
<div className="dash-bar"><h2 className="section">ZFS</h2></div>
|
||||
|
||||
Reference in New Issue
Block a user