dashboard: show GATEWAY_HEALTH_URL instead of PID for remote gateways

When the dashboard connects to a remote gateway via GATEWAY_HEALTH_URL,
display the URL instead of the remote PID (which is meaningless locally).
Falls back to PID display for local gateways as before.

- Backend: expose gateway_health_url in /api/status response
- Frontend: prefer gateway_health_url over PID in gatewayValue()
- Add truncate + title tooltip for long URLs that overflow the card
- Add min-w-0/overflow-hidden on status cards for proper truncation
- Tests: verify gateway_health_url in remote and no-URL scenarios
This commit is contained in:
Ben 2026-04-17 09:07:58 +10:00 committed by Teknium
parent 5d7d574779
commit 79156ab19c
4 changed files with 7 additions and 2 deletions

View file

@ -467,6 +467,7 @@ async def get_status():
"latest_config_version": latest_ver,
"gateway_running": gateway_running,
"gateway_pid": gateway_pid,
"gateway_health_url": _GATEWAY_HEALTH_URL,
"gateway_state": gateway_state,
"gateway_platforms": gateway_platforms,
"gateway_exit_reason": gateway_exit_reason,

View file

@ -1122,6 +1122,7 @@ class TestStatusRemoteGateway:
assert data["gateway_running"] is True
assert data["gateway_pid"] == 999
assert data["gateway_state"] == "running"
assert data["gateway_health_url"] == "http://gw:8642"
def test_status_remote_probe_not_attempted_when_local_pid_found(self, monkeypatch):
"""When local PID check succeeds, the remote probe is never called."""
@ -1158,6 +1159,7 @@ class TestStatusRemoteGateway:
assert resp.status_code == 200
data = resp.json()
assert data["gateway_running"] is False
assert data["gateway_health_url"] is None
def test_status_remote_running_null_pid(self, monkeypatch):
"""Remote gateway running but PID not in response — pid should be None."""

View file

@ -213,6 +213,7 @@ export interface StatusResponse {
config_version: number;
env_path: string;
gateway_exit_reason: string | null;
gateway_health_url: string | null;
gateway_pid: number | null;
gateway_platforms: Record<string, PlatformStatus>;
gateway_running: boolean;

View file

@ -53,6 +53,7 @@ export default function StatusPage() {
};
function gatewayValue(): string {
if (status!.gateway_running && status!.gateway_health_url) return status!.gateway_health_url;
if (status!.gateway_running && status!.gateway_pid) return `${t.status.pid} ${status!.gateway_pid}`;
if (status!.gateway_running) return t.status.runningRemote;
if (status!.gateway_state === "startup_failed") return t.status.startFailed;
@ -137,14 +138,14 @@ export default function StatusPage() {
<div className="grid gap-4 sm:grid-cols-3">
{items.map(({ icon: Icon, label, value, badgeText, badgeVariant }) => (
<Card key={label}>
<Card key={label} className="min-w-0 overflow-hidden">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium">{label}</CardTitle>
<Icon className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold font-display">{value}</div>
<div className="text-2xl font-bold font-display truncate" title={value}>{value}</div>
{badgeText && (
<Badge variant={badgeVariant} className="mt-2">