diff options
Diffstat (limited to 'makima/frontend/src/components/directives/DirectiveDetail.tsx')
| -rw-r--r-- | makima/frontend/src/components/directives/DirectiveDetail.tsx | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveDetail.tsx b/makima/frontend/src/components/directives/DirectiveDetail.tsx index 8f39207..5f3489a 100644 --- a/makima/frontend/src/components/directives/DirectiveDetail.tsx +++ b/makima/frontend/src/components/directives/DirectiveDetail.tsx @@ -3,6 +3,7 @@ import type { DirectiveWithSteps, DirectiveStatus, UpdateDirectiveRequest } from import { DirectiveDAG } from "./DirectiveDAG"; import type { SpecializedStep } from "./DirectiveDAG"; import { DirectiveLogStream } from "./DirectiveLogStream"; +import { TaskSlideOutPanel } from "./TaskSlideOutPanel"; import { useMultiTaskSubscription } from "../../hooks/useMultiTaskSubscription"; import { useSupervisorQuestions } from "../../contexts/SupervisorQuestionsContext"; @@ -53,6 +54,11 @@ export function DirectiveDetail({ const [pickingUpOrders, setPickingUpOrders] = useState(false); const [pickUpResult, setPickUpResult] = useState<string | null>(null); const [creatingPR, setCreatingPR] = useState(false); + const [slideOutTaskId, setSlideOutTaskId] = useState<string | null>(null); + + const handleViewTask = (taskId: string) => { + setSlideOutTaskId(taskId); + }; // Sync goalText and reset editing state when directive changes useEffect(() => { @@ -178,7 +184,15 @@ export function DirectiveDetail({ }; + // Find the task name for the slide-out panel + const slideOutTaskName = slideOutTaskId + ? (directive.steps.find((s) => s.taskId === slideOutTaskId)?.name ?? + taskMap.get(slideOutTaskId) ?? + undefined) + : undefined; + return ( + <> <div className="flex flex-col h-full overflow-y-auto"> {/* Header */} <div className="px-4 py-3 border-b border-dashed border-[rgba(117,170,252,0.2)]"> @@ -228,21 +242,31 @@ export function DirectiveDetail({ {/* Reconcile mode toggle */} <div className="flex items-center gap-2 mb-2"> - <button - type="button" - onClick={() => onUpdate({ reconcileMode: !directive.reconcileMode })} - className={`text-[10px] font-mono border rounded px-2 py-0.5 transition-colors ${ - directive.reconcileMode - ? "text-amber-400 border-amber-800 bg-amber-900/20" - : "text-[#556677] border-[#2a3a5a] hover:text-[#7788aa]" - }`} - > - {directive.reconcileMode ? "Reconcile: ON" : "Reconcile: OFF"} - </button> + <div className="flex items-center border border-[#2a3a5a] rounded overflow-hidden"> + {(["auto", "semi-auto", "manual"] as const).map((mode) => { + const isActive = directive.reconcileMode === mode; + const modeStyles: Record<string, string> = { + auto: isActive ? "text-[#9bc3ff] bg-[#1a2540]" : "text-[#445566] hover:text-[#7788aa]", + "semi-auto": isActive ? "text-amber-400 bg-amber-900/20" : "text-[#445566] hover:text-[#7788aa]", + manual: isActive ? "text-orange-400 bg-orange-900/20" : "text-[#445566] hover:text-[#7788aa]", + }; + const labels: Record<string, string> = { auto: "Auto", "semi-auto": "Semi", manual: "Manual" }; + return ( + <button + key={mode} + type="button" + onClick={() => onUpdate({ reconcileMode: mode })} + className={`text-[10px] font-mono px-2 py-0.5 transition-colors border-r border-[#2a3a5a] last:border-r-0 ${modeStyles[mode]}`} + > + {labels[mode]} + </button> + ); + })} + </div> <span className="text-[9px] font-mono text-[#445566]"> - {directive.reconcileMode - ? "Questions pause execution" - : "Questions timeout after 30s"} + {directive.reconcileMode === "auto" && "Questions timeout after 30s"} + {directive.reconcileMode === "semi-auto" && "Questions pause execution"} + {directive.reconcileMode === "manual" && "Tasks ask clarifying questions"} </span> </div> @@ -424,6 +448,7 @@ export function DirectiveDetail({ onComplete={onCompleteStep} onFail={onFailStep} onSkip={onSkipStep} + onViewTask={handleViewTask} /> </div> @@ -445,6 +470,14 @@ export function DirectiveDetail({ </div> )} </div> + + <TaskSlideOutPanel + taskId={slideOutTaskId || ""} + taskName={slideOutTaskName} + isOpen={!!slideOutTaskId} + onClose={() => setSlideOutTaskId(null)} + /> + </> ); } |
