fix: wire conversation panel to DAG nodes with toggle support
- Add MessageSquare icon to GraphNodeCard; prop-thread onConversationOpen and selectedTaskId through WorkflowGraph node data (no useUrlState inside ReactFlow nodes — avoids context/timing issues) - Fix ContextualRightPanel: check taskId before epicId so clicking the conversation icon always opens ThreadDrawer even when an epic filter is active - setEpicId now clears task from URL so selecting an epic resets any open conversation thread - handleGraphSelect toggles: second click on same node calls setTaskId(null) closing the right panel - Add onSelect to WorkflowGraph flowModel deps to prevent stale callbacks - Fix ContextualRightPanel onClose no-ops: wired to setTaskId(null) / setSwarmId(null) so back button works - Right panel always visible (removed panel==='open' gate in UnifiedShell) - SmartDag task grid: horizontal scroll, fixed-width cards, hideClosed=true - Add <Suspense> in page.tsx for useSearchParams compatibility - Enable dolt auto-start in .beads/config.yaml - Add 14 static analysis tests (graph-node-conversation.test.tsx) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cb83fd92a9
commit
861ae89491
11 changed files with 1279 additions and 1174 deletions
|
|
@ -7,6 +7,7 @@ import { SwarmCommandFeed } from './swarm-command-feed';
|
|||
import { ThreadDrawer } from '../shared/thread-drawer';
|
||||
import { MissionInspector } from '../mission/mission-inspector';
|
||||
import { useSwarmList } from '../../hooks/use-swarm-list';
|
||||
import { useUrlState } from '../../hooks/use-url-state';
|
||||
|
||||
export interface ContextualRightPanelProps {
|
||||
epicId?: string | null;
|
||||
|
|
@ -17,23 +18,16 @@ export interface ContextualRightPanelProps {
|
|||
}
|
||||
|
||||
export function ContextualRightPanel({ epicId, taskId, swarmId, issues, projectRoot }: ContextualRightPanelProps) {
|
||||
if (epicId) {
|
||||
return (
|
||||
<SwarmCommandFeed
|
||||
epicId={epicId}
|
||||
issues={issues}
|
||||
projectRoot={projectRoot}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const { setTaskId } = useUrlState();
|
||||
|
||||
// Task conversation takes priority — user explicitly clicked the conversation icon
|
||||
if (taskId) {
|
||||
const selectedIssue = issues.find(i => i.id === taskId) ?? null;
|
||||
return (
|
||||
<ThreadDrawer
|
||||
isOpen={true}
|
||||
embedded={true}
|
||||
onClose={() => {}}
|
||||
onClose={() => setTaskId(null)}
|
||||
title={selectedIssue?.title ?? taskId}
|
||||
id={taskId}
|
||||
issue={selectedIssue}
|
||||
|
|
@ -43,6 +37,16 @@ export function ContextualRightPanel({ epicId, taskId, swarmId, issues, projectR
|
|||
);
|
||||
}
|
||||
|
||||
if (epicId) {
|
||||
return (
|
||||
<SwarmCommandFeed
|
||||
epicId={epicId}
|
||||
issues={issues}
|
||||
projectRoot={projectRoot}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (swarmId) {
|
||||
return (
|
||||
<SwarmIdBranch
|
||||
|
|
@ -63,6 +67,7 @@ export function ContextualRightPanel({ epicId, taskId, swarmId, issues, projectR
|
|||
|
||||
// Inner component so hooks can be called conditionally via component boundary
|
||||
function SwarmIdBranch({ swarmId, projectRoot }: { swarmId: string; projectRoot: string }) {
|
||||
const { setSwarmId } = useUrlState();
|
||||
const { swarms } = useSwarmList(projectRoot);
|
||||
const swarm = swarms.find(s => s.swarmId === swarmId);
|
||||
// Fall back to swarmId as title while swarm list loads
|
||||
|
|
@ -76,7 +81,7 @@ function SwarmIdBranch({ swarmId, projectRoot }: { swarmId: string; projectRoot:
|
|||
missionTitle={missionTitle}
|
||||
projectRoot={projectRoot}
|
||||
assignedAgents={assignedAgents}
|
||||
onClose={() => {}}
|
||||
onClose={() => setSwarmId(null)}
|
||||
onAssign={async () => {}}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue