Files
fusion/packages/dashboard/app/components/ProjectNodeSelector.tsx
Fusion 19d787d74d feat(FN-2729): merge fusion/fn-2729
- fix(FN-2729): silence ansi strip lint warning
- test(FN-2729): complete Step 10 — cover node health indicators
- feat(FN-2729): complete Step 9 — colorize CLI node status output
- feat(FN-2729): complete Step 8 — use NodeHealthDot in settings routing status
- test(FN-2729): align ListView node override option expectations
- feat(FN-2729): complete Step 7 — add bulk node status indicators
- fix(engine): prevent auto-merge cooldown loop on unresolvable conflicts
- feat(FN-2911): improve chat attachment compose and preview UX
- feat(FN-2921): merge fusion/fn-2921
- feat(FN-2909): merge fusion/fn-2909
- feat(FN-2914): merge fusion/fn-2914
- feat(FN-2902): merge fusion/fn-2902
- chore(release): v0.8.3
- Update changeset
- fix(tui): swap 3/4 panel hotkeys so they match the help text
- fix(tui): always show auth token and report accurate macOS memory usage

Fusion-Task-Id: FN-2729
2026-04-28 23:23:34 -07:00

54 lines
1.5 KiB
TypeScript

import { useMemo } from "react";
import type { NodeInfo } from "../api";
import "./ProjectNodeSelector.css";
interface ProjectNodeSelectorProps {
projectId: string;
currentNodeId?: string;
onSelect: (nodeId: string | null) => void;
nodes: NodeInfo[];
disabled?: boolean;
}
export function ProjectNodeSelector({
projectId,
currentNodeId,
onSelect,
nodes,
disabled = false,
}: ProjectNodeSelectorProps) {
const sortedNodes = useMemo(() => {
return [...nodes].sort((a, b) => a.name.localeCompare(b.name));
}, [nodes]);
const selectedValue = currentNodeId ?? "";
return (
<label className="project-node-selector" htmlFor={`project-node-selector-${projectId}`}>
<span className="project-node-selector__label">Runtime Node</span>
<select
className="select"
id={`project-node-selector-${projectId}`}
value={selectedValue}
onChange={(event) => {
const value = event.target.value;
onSelect(value ? value : null);
}}
disabled={disabled}
>
<option value="">Auto (no assignment)</option>
{sortedNodes.map((node) => (
<option
key={node.id}
value={node.id}
title={`Status: ${node.status}`}
className={node.status === "offline" || node.status === "error" ? "project-node-selector__option--dim" : ""}
>
{node.name} ({node.type}) {node.status}
</option>
))}
</select>
</label>
);
}