import React, { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Badge } from "@/components/ui/badge"; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { TaskStatus } from '@/types/workflow'; import { AnalysisModuleConfig } from '@/types/index'; import { BrainCircuit, Terminal } from 'lucide-react'; interface AnalysisModulesViewProps { taskStates: Record; taskOutputs: Record; modulesConfig: Record; } export function AnalysisModulesView({ taskStates, taskOutputs, modulesConfig }: AnalysisModulesViewProps) { // Identify analysis tasks based on the template config // We assume task IDs in the DAG correspond to module IDs or follow a pattern // For now, let's try to match tasks that are NOT fetch tasks // If we have config, use it to drive tabs const moduleIds = Object.keys(modulesConfig); const [activeModuleId, setActiveModuleId] = useState(moduleIds[0] || ''); useEffect(() => { // If no active module and we have modules, select first if (!activeModuleId && moduleIds.length > 0) { setActiveModuleId(moduleIds[0]); } }, [moduleIds, activeModuleId]); if (moduleIds.length === 0) { return (

No analysis modules defined in this template.

); } return (
{moduleIds.map(moduleId => { const config = modulesConfig[moduleId]; // Task ID might match module ID directly or be prefixed // Heuristic: check exact match first const taskId = moduleId; const status = taskStates[taskId] || 'pending'; return (
{config.name}
); })}
{moduleIds.map(moduleId => { const taskId = moduleId; const output = taskOutputs[taskId] || ''; const status = taskStates[taskId] || 'pending'; const config = modulesConfig[moduleId]; return (
{config.name} {config.model_id}
{output ? (
{output}
) : (

{status === 'running' ? 'Generating analysis...' : 'Waiting for input...'}

)}
); })}
); } function StatusDot({ status }: { status: TaskStatus }) { let colorClass = "bg-muted"; if (status === 'completed') colorClass = "bg-green-500"; if (status === 'failed') colorClass = "bg-red-500"; if (status === 'running') colorClass = "bg-blue-500 animate-pulse"; return
; } function StatusBadge({ status }: { status: TaskStatus }) { switch (status) { case 'completed': return Completed; case 'failed': return Failed; case 'running': return Generating...; default: return Pending; } }