summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/directives/DirectiveDetail.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'makima/frontend/src/components/directives/DirectiveDetail.tsx')
-rw-r--r--makima/frontend/src/components/directives/DirectiveDetail.tsx61
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)}
+ />
+ </>
);
}