A machine is titled by its own hostname, and follows a rename
The name a machine was added under stays its identity — the URL, its accent, what the hub's API calls it — and is what the Machines page shows as 'Added as'. The hostname is read live rather than at start-up, so renaming a machine reaches the console without a restart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ec94cb8bff
commit
dbfe163a75
+10
-7
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { api, Me, Term } from './api'
|
||||
import { api, Me, Term, titleOf } from './api'
|
||||
import Rail, { Group } from './Rail'
|
||||
import TerminalPane, { TermHandle } from './TerminalPane'
|
||||
import TermTabs from './TermTabs'
|
||||
@@ -90,7 +90,10 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
|
||||
const [machines, setMachines] = useState<MachineStatus[]>([])
|
||||
const [remoteMe, setRemoteMe] = useState<Me | null>(null)
|
||||
const [remoteErr, setRemoteErr] = useState('')
|
||||
const me: Me = machine ? (remoteMe ?? { ...hubMe, host: machine, load: '', version: '…', uptime: 0, reboot_needed: false }) : hubMe
|
||||
// A machine is titled by its own hostname; the name it was added under stays its identity
|
||||
// (the URL, its accent, what the hub's API calls it). See titleOf.
|
||||
const title = titleOf(machine, machines, hubMe.host)
|
||||
const me: Me = machine ? (remoteMe ?? { ...hubMe, host: title, load: '', version: '…', uptime: 0, reboot_needed: false }) : hubMe
|
||||
const listRate = useRefreshMs(LIST_FLOOR)
|
||||
const [terms, setTerms] = useState<Term[]>([])
|
||||
const [active, setActive] = useState<string | null>(null)
|
||||
@@ -133,7 +136,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
|
||||
// The machine's colour: set on <html>, so the header stripe and the switcher pick it up.
|
||||
useEffect(() => { const paint = () => applyAccent(machine ?? hubMe.host); paint(); window.addEventListener('hamlab:accents', paint); return () => window.removeEventListener('hamlab:accents', paint) }, [machine, hubMe.host])
|
||||
// The tab's title says where you are, so history entries and open tabs can be told apart.
|
||||
useEffect(() => { document.title = `${GROUPS.find((g) => g.id === view)?.label ?? view} · ${machine ?? hubMe.host} — Ham Lab` }, [view, machine, hubMe.host])
|
||||
useEffect(() => { document.title = `${GROUPS.find((g) => g.id === view)?.label ?? view} · ${title} — Ham Lab` }, [view, title])
|
||||
useEffect(() => {
|
||||
const want = `#/${machine ?? 'hub'}/${view}`
|
||||
if (location.hash !== want && !location.hash.startsWith(want + '/')) history.pushState(null, '', want)
|
||||
@@ -236,8 +239,8 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
|
||||
{machine && remoteErr && <span className="badge bad" title={remoteErr}>offline</span>}
|
||||
<span className="spacer" />
|
||||
<span className="stat" title="load average, 1 · 5 · 15 min">load {me.load}</span>
|
||||
<span className={'dot ' + (online && !remoteErr ? 'ok' : 'bad')} title={remoteErr ? `${machine} unreachable` : online ? 'connected' : 'disconnected'} />
|
||||
<Power host={me.host} label={machine ?? me.host} rebootNeeded={me.reboot_needed} />
|
||||
<span className={'dot ' + (online && !remoteErr ? 'ok' : 'bad')} title={remoteErr ? `${title} unreachable` : online ? 'connected' : 'disconnected'} />
|
||||
<Power host={me.host} label={title} rebootNeeded={me.reboot_needed} />
|
||||
<Btn className="link" onClick={logout}>logout</Btn>
|
||||
</header>
|
||||
|
||||
@@ -253,7 +256,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
|
||||
{view === 'dashboard' && <Dashboard />}
|
||||
{view === 'widgets' && <Gallery demoUrl={hubMe.demo_url} />}
|
||||
{view === 'docker' && <Docker />}
|
||||
{view === 'alerts' && <Alerts machines={machines.map((m) => m.name)} />}
|
||||
{view === 'alerts' && <Alerts machines={machines.map((m) => m.name)} titleOf={(n) => titleOf(n === hubMe.host ? null : n, machines, hubMe.host)} />}
|
||||
{view === 'top' && <Top />}
|
||||
{view === 'procs' && <Procs />}
|
||||
{view === 'services' && <Services />}
|
||||
@@ -283,7 +286,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
|
||||
setCtrl={(v) => handles.current[activeTerm.id]?.armCtrl(v)} />}
|
||||
|
||||
<footer className="footer">
|
||||
<span>{machine ? `${machine} · ` : ''}{me.version.startsWith('v') ? me.version : 'v' + me.version}</span>
|
||||
<span>{machine ? `${title} · ` : ''}{me.version.startsWith('v') ? me.version : 'v' + me.version}</span>
|
||||
<span>up {fmtUptime(me.uptime)}</span>
|
||||
<span className="spacer" />
|
||||
<span className="muted">{view === 'top' ? 'Top' : view === 'dashboard' ? 'Dashboard' : view === 'widgets' ? 'Widgets' : view === 'docker' ? 'Docker' : view === 'alerts' ? 'Alerts' : view === 'services' ? 'Services' : view === 'cron' ? 'Cron' : view === 'updates' ? 'Updates' : view === 'disks' ? 'Disks' : view === 'files' ? 'Files' : view === 'procs' ? 'Processes' : view === 'machines' ? 'Machines' : view === 'settings' ? 'Settings' : activeTerm ? activeTerm.name : ''}</span>
|
||||
|
||||
Reference in New Issue
Block a user