fix(fleet): navigate to editor instead of dashboard on "Open in Editor" click (#289)

The Fleet View's "Open in Editor" button on container rows was navigating
to the dashboard instead of opening the stack in the editor. Fixed by
threading the stackName through the callback chain and using a pending
ref to survive the node-switch effect reset.
This commit is contained in:
Anso
2026-03-31 10:45:54 -04:00
committed by GitHub
parent 50c29b4248
commit 71ce6b3e1b
4 changed files with 23 additions and 8 deletions
+18 -4
View File
@@ -108,6 +108,7 @@ export default function EditorLayout() {
const rawBytesRef = useRef<Record<string, { lastRx: number; lastTx: number }>>({});
const [activeTab, setActiveTab] = useState<'compose' | 'env'>('compose');
const monacoEditorRef = useRef<import('monaco-editor').editor.IStandaloneCodeEditor | null>(null);
const pendingStackLoadRef = useRef<string | null>(null);
const [createDialogOpen, setCreateDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [newStackName, setNewStackName] = useState('');
@@ -425,6 +426,9 @@ export default function EditorLayout() {
// Also clears any stale editor/container state that belonged to the previous node.
useEffect(() => {
if (!activeNode) return;
const pendingStack = pendingStackLoadRef.current;
pendingStackLoadRef.current = null;
setSelectedFile(null);
setContent('');
setOriginalContent('');
@@ -432,7 +436,13 @@ export default function EditorLayout() {
setOriginalEnvContent('');
setContainers([]);
setIsEditing(false);
setActiveView('dashboard');
if (pendingStack) {
loadFile(pendingStack);
} else {
setActiveView('dashboard');
}
refreshStacks();
fetchImageUpdates();
}, [activeNode?.id]); // eslint-disable-line react-hooks/exhaustive-deps
@@ -1786,11 +1796,15 @@ export default function EditorLayout() {
) : activeView === 'global-observability' ? (
<GlobalObservabilityView />
) : activeView === 'fleet' ? (
<FleetView onNavigateToNode={(nodeId) => {
<FleetView onNavigateToNode={(nodeId, stackName) => {
const node = nodes.find(n => n.id === nodeId);
if (node) {
setActiveNode(node);
setActiveView('dashboard');
if (activeNode?.id === nodeId) {
loadFile(stackName);
} else {
pendingStackLoadRef.current = stackName;
setActiveNode(node);
}
}
}} />
) : activeView === 'audit-log' ? (
+4 -4
View File
@@ -189,7 +189,7 @@ function ContainerRow({ container, nodeId, onNavigate }: {
function StackSection({ stackName, nodeId, onNavigate }: {
stackName: string;
nodeId: number;
onNavigate: (nodeId: number) => void;
onNavigate: (nodeId: number, stackName: string) => void;
}) {
const [expanded, setExpanded] = useState(false);
const [containers, setContainers] = useState<StackContainer[] | null>(null);
@@ -247,7 +247,7 @@ function StackSection({ stackName, nodeId, onNavigate }: {
key={c.Id ?? containerName(c)}
container={c}
nodeId={nodeId}
onNavigate={onNavigate}
onNavigate={(nid) => onNavigate(nid, stackName)}
/>
))
) : (
@@ -259,7 +259,7 @@ function StackSection({ stackName, nodeId, onNavigate }: {
);
}
function NodeCard({ node, onNavigate }: { node: FleetNode; onNavigate: (nodeId: number) => void }) {
function NodeCard({ node, onNavigate }: { node: FleetNode; onNavigate: (nodeId: number, stackName: string) => void }) {
const { isPro } = useLicense();
const [expanded, setExpanded] = useState(false);
const [stacks, setStacks] = useState<string[] | null>(node.stacks);
@@ -431,7 +431,7 @@ function NodeCard({ node, onNavigate }: { node: FleetNode; onNavigate: (nodeId:
// --- Main Component ---
interface FleetViewProps {
onNavigateToNode: (nodeId: number) => void;
onNavigateToNode: (nodeId: number, stackName: string) => void;
}
export function FleetView({ onNavigateToNode }: FleetViewProps) {