Widgets tab links the external demo when config.json names one (demo_url)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-09-19 08:58:36 -07:00
co-authored by Claude Fable 5.1
parent 65a9888784
commit 62605d57eb
7 changed files with 18 additions and 5 deletions
+6 -2
View File
@@ -31,7 +31,7 @@ function Tile({ spec, data, note }: { spec: WidgetSpec; data: WidgetData; note:
)
}
export default function Gallery() {
export default function Gallery({ demoUrl }: { demoUrl?: string }) {
const [cat, setCat] = useState<Sensor[] | null>(null)
const [err, setErr] = useState('')
const rate = useRefreshMs()
@@ -54,7 +54,11 @@ export default function Gallery() {
return (
<div className="dash gallery">
<div className="dash-bar"><span className="hint">{sensors.length} sensors on this machine · live · tap a tile to copy its ID</span></div>
<div className="dash-bar">
<span className="hint">{sensors.length} sensors on this machine · live · tap a tile to copy its ID</span>
<span className="spacer" />
{demoUrl && <a className="btn" href={demoUrl} target="_blank" rel="noreferrer" title="a page outside Ham Lab, built on the same sensor API">External demo ↗</a>}
</div>
<h2 className="section">Widget types</h2>
<div className="kpis">
+1 -1
View File
@@ -179,7 +179,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
{view === 'settings' && <Settings me={hubMe} />}
{view === 'machines' && <Machines hub={hubMe} onChanged={loadMachines} onOpen={(n) => { switchMachine(n); setView('dashboard') }} />}
{view === 'dashboard' && <Dashboard />}
{view === 'widgets' && <Gallery />}
{view === 'widgets' && <Gallery demoUrl={hubMe.demo_url} />}
{view === 'procs' && <Procs />}
{view === 'services' && <Services />}
{view === 'cron' && <Cron />}
+1 -1
View File
@@ -51,7 +51,7 @@ async function req<T>(method: string, path: string, body?: unknown, local = fals
return r.json()
}
export interface Me { host: string; user: string; version: string; load: string; uptime: number; reboot_needed?: boolean; fingerprint?: string; arch?: string }
export interface Me { demo_url?: string; host: string; user: string; version: string; load: string; uptime: number; reboot_needed?: boolean; fingerprint?: string; arch?: string }
export interface PushResult { name: string; ok: boolean; version?: string; error?: string }
export interface MachineStatus { name: string; url: string; fingerprint?: string; added: string; online: boolean; host?: string; version?: string; load?: string; uptime?: number; reboot_needed?: boolean; last_seen?: string; error?: string }
export interface Term { id: string; name: string; running: boolean; exit_code: number; created: string; clients: number }
+1
View File
@@ -427,3 +427,4 @@ h2.section { margin: 0; font-size: 13px; font-weight: 600; color: var(--muted);
.gallery-tile .value { font-size: 18px; overflow-wrap: anywhere; }
.gallery-id { margin-top: auto; padding-top: 8px; font-size: 10.5px; color: var(--muted); overflow-wrap: anywhere; }
@media (max-width: 800px) { .gallery .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
a.btn { text-decoration: none; display: inline-flex; align-items: center; }