Files
fusion/packages/dashboard/app/components/NodeStatusIndicator.tsx
gsxdsm 1e49494bac feat(i18n): full-sweep string migration — 5,930 keys across 5 locales (#1352)
Migration (multi-agent sweep over 216 files, 60 batches):
- Every user-visible dashboard + TUI string moved to t() with the exact
  English inline default (en rendering byte-identical)
- Catalogs merged from per-batch fragments: en/zh-CN/zh-TW/fr/es now
  carry ~5,930 keys each across common/app/errors/cli namespaces;
  CLI bundles regenerated (6 locales incl. ko)

Integration fixes:
- 18 type errors: reserved {{count}} interpolations renamed, malformed
  plural call, hand-rolled t-param types replaced with TFunction<"app">
- 23 lint errors: superseded label constants/helpers removed
- ExecutorStatusBar hook-order violation (keyboard-open early return
  moved below hooks)
- TUI tests wrapped in I18nextProvider (uninitialized fallback renders
  literal {{placeholders}}); dashboard vitest.setup boots a minimal en
  i18next instance for the same reason

Known WIP (next commits): ~457 residual strings across 50 batches,
Korean drafts for swept keys, and a dashboard test-suite pass that is
still being stabilized (~283 failures under investigation — fake-timer
waitFor interaction, likely stale node_modules vs merged lockfile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 19:06:53 -07:00

70 lines
2.6 KiB
TypeScript

/**
* NodeStatusIndicator - displays the connection status of the currently viewed node.
* Shows a green/red/yellow dot and optional text based on node state.
*/
import { useTranslation } from "react-i18next";
import type { NodeConfig } from "@fusion/core";
export interface NodeStatusIndicatorProps {
/** The node to display, or null for local node */
node: NodeConfig | null;
/** Whether to show additional details (node name, type, status text) */
showDetails?: boolean;
}
/**
* Get display configuration for a node status
*/
function getStatusDisplay(status: NodeConfig["status"], t: (key: string, defaultValue: string) => string): {
label: string;
dotClass: string;
} {
switch (status) {
case "online":
return { label: t("nodeStatus.online", "Online"), dotClass: "node-status-indicator__dot--online" };
case "offline":
return { label: t("nodeStatus.offline", "Offline"), dotClass: "node-status-indicator__dot--offline" };
case "connecting":
return { label: t("nodeStatus.connecting", "Connecting"), dotClass: "node-status-indicator__dot--connecting" };
case "error":
return { label: t("nodeStatus.error", "Error"), dotClass: "node-status-indicator__dot--error" };
default:
return { label: t("nodeStatus.unknown", "Unknown"), dotClass: "node-status-indicator__dot--offline" };
}
}
/**
* Status indicator component for nodes.
* Shows connection status with a colored dot and optional details.
*/
export function NodeStatusIndicator({ node, showDetails = false }: NodeStatusIndicatorProps) {
const { t } = useTranslation("app");
// Local or null node - show "Local" badge
if (!node || node.type === "local") {
return (
<div className="node-status-indicator node-status-indicator--local">
<span className="node-status-indicator__label">{t("nodeStatus.local", "Local")}</span>
</div>
);
}
// Remote node - show status with dot and optional details
const { label: statusLabel, dotClass } = getStatusDisplay(node.status, (key, defaultValue) => t(key, defaultValue));
const isConnecting = node.status === "connecting";
return (
<div className="node-status-indicator node-status-indicator--remote">
<span className={`node-status-indicator__dot ${dotClass}`}>
{isConnecting && <span className="node-status-indicator__spinner" />}
</span>
<span className="node-status-indicator__name">{node.name}</span>
{showDetails && (
<span className="node-status-indicator__details">
{node.type} · {statusLabel}
</span>
)}
</div>
);
}