diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d3daad7..8c20bcf 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2,6 +2,7 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { Dashboard } from '@/components/dashboard/Dashboard'; import { PromptActivity } from '@/components/prompts/PromptActivity'; +import { TaskFlowDemo } from '@/components/taskflow/TaskFlowDemo'; import { Login } from '@/components/auth/Login'; import { AuthGuard } from '@/components/auth/AuthGuard'; @@ -36,6 +37,14 @@ function App() { } /> + }> + + + } + /> diff --git a/frontend/src/components/dashboard/Dashboard.tsx b/frontend/src/components/dashboard/Dashboard.tsx index 22bc0e3..db9077b 100644 --- a/frontend/src/components/dashboard/Dashboard.tsx +++ b/frontend/src/components/dashboard/Dashboard.tsx @@ -1,14 +1,41 @@ import { Layout } from '@/components/layout/Layout'; import { PromptsList } from '@/components/prompts/PromptsList'; import { ConnectionsList } from '@/components/connections/ConnectionsList'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; import { useAuth } from '@/hooks/useAuth'; +import { useNavigate } from 'react-router-dom'; +import { Workflow } from 'lucide-react'; export function Dashboard() { const { data: user } = useAuth(); + const navigate = useNavigate(); + + const handleTaskFlowDemo = () => { + navigate('/taskflow'); + }; return (
+ {/* Quick Actions */} + + + 🚀 Quick Actions + + +
+ +
+
+
+
diff --git a/frontend/src/components/taskflow/TaskFlow.tsx b/frontend/src/components/taskflow/TaskFlow.tsx new file mode 100644 index 0000000..f9c763f --- /dev/null +++ b/frontend/src/components/taskflow/TaskFlow.tsx @@ -0,0 +1,222 @@ +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import { + CheckCircle, + XCircle, + Loader2, + Clock, + Play, + Pause +} from 'lucide-react'; +import { useState } from 'react'; + +export interface TaskStep { + id: string; + title: string; + description?: string; + status: 'pending' | 'running' | 'completed' | 'error' | 'paused'; + duration?: number; + startTime?: string; + endTime?: string; + output?: string; + dependencies?: string[]; +} + +export interface TaskFlowProps { + title: string; + description?: string; + steps: TaskStep[]; + onStepAction?: (stepId: string, action: 'run' | 'pause' | 'retry') => void; + onFlowAction?: (action: 'start' | 'pause' | 'stop' | 'retry') => void; + isRunning?: boolean; + className?: string; +} + +export function TaskFlow({ + title, + description, + steps, + onStepAction, + onFlowAction, + isRunning = false, + className = "" +}: TaskFlowProps) { + const [expandedStep, setExpandedStep] = useState(null); + + const getStatusIcon = (status: TaskStep['status']) => { + switch (status) { + case 'completed': + return ; + case 'error': + return ; + case 'running': + return ; + case 'paused': + return ; + default: + return ; + } + }; + + const getStatusBadgeVariant = (status: TaskStep['status']) => { + switch (status) { + case 'completed': + return 'default'; + case 'error': + return 'destructive'; + case 'running': + return 'secondary'; + case 'paused': + return 'secondary'; + default: + return 'outline'; + } + }; + + const getOverallStatus = () => { + if (steps.some(step => step.status === 'error')) return 'error'; + if (steps.some(step => step.status === 'running')) return 'running'; + if (steps.some(step => step.status === 'paused')) return 'paused'; + if (steps.every(step => step.status === 'completed')) return 'completed'; + return 'pending'; + }; + + const getCompletedSteps = () => steps.filter(step => step.status === 'completed').length; + const totalSteps = steps.length; + const progressPercentage = totalSteps > 0 ? (getCompletedSteps() / totalSteps) * 100 : 0; + + return ( + + +
+
+ + 🔄 {title} + + {getOverallStatus()} + + + {description && ( +

{description}

+ )} +
+ + Progress: {getCompletedSteps()}/{totalSteps} steps + +
+
+
+
+
+ {onFlowAction && ( +
+ {!isRunning ? ( + + ) : ( + + )} +
+ )} +
+ + +
+ {steps.map((step, index) => ( +
+ {/* Connection line */} + {index < steps.length - 1 && ( +
+ )} + +
+
+ {getStatusIcon(step.status)} +
+ +
+
+
+

{step.title}

+ + {step.status} + +
+ +
+ {step.duration && ( + + {step.duration}ms + + )} + {onStepAction && step.status === 'error' && ( + + )} + {step.output && ( + + )} +
+
+ + {step.description && ( +

+ {step.description} +

+ )} + + {step.startTime && ( +
+ Started: {new Date(step.startTime).toLocaleTimeString()} + {step.endTime && ( + Ended: {new Date(step.endTime).toLocaleTimeString()} + )} +
+ )} + + {expandedStep === step.id && step.output && ( +
+

Output:

+
{step.output}
+
+ )} +
+
+
+ ))} +
+ + + ); +} \ No newline at end of file diff --git a/frontend/src/components/taskflow/TaskFlowDemo.tsx b/frontend/src/components/taskflow/TaskFlowDemo.tsx new file mode 100644 index 0000000..5ad8daf --- /dev/null +++ b/frontend/src/components/taskflow/TaskFlowDemo.tsx @@ -0,0 +1,150 @@ +import { Layout } from '@/components/layout/Layout'; +import { TaskFlow } from '@/components/taskflow'; +import type { TaskStep } from '@/components/taskflow'; +import { useDashboardData } from '@/hooks/api'; +import { useState } from 'react'; + +export function TaskFlowDemo() { + const { data: dashboardData } = useDashboardData(); + const [isRunning, setIsRunning] = useState(false); + const [steps, setSteps] = useState([ + { + id: 'step-1', + title: 'Initialize Repository', + description: 'Clone the repository and set up the workspace', + status: 'completed', + duration: 1200, + startTime: '2024-01-15T10:00:00Z', + endTime: '2024-01-15T10:00:01Z', + output: 'Repository cloned successfully to /workspace/project' + }, + { + id: 'step-2', + title: 'Analyze Code Structure', + description: 'Scan codebase and identify patterns', + status: 'completed', + duration: 3400, + startTime: '2024-01-15T10:00:02Z', + endTime: '2024-01-15T10:00:05Z', + output: 'Found 24 files, 3 main modules, TypeScript project with React frontend' + }, + { + id: 'step-3', + title: 'Generate Implementation Plan', + description: 'Create detailed plan for the requested changes', + status: 'running', + startTime: '2024-01-15T10:00:06Z' + }, + { + id: 'step-4', + title: 'Implement Changes', + description: 'Apply the necessary code modifications', + status: 'pending', + dependencies: ['step-3'] + }, + { + id: 'step-5', + title: 'Run Tests', + description: 'Execute test suite to verify changes', + status: 'pending', + dependencies: ['step-4'] + }, + { + id: 'step-6', + title: 'Create Pull Request', + description: 'Commit changes and create PR', + status: 'pending', + dependencies: ['step-5'] + } + ]); + + const handleStepAction = (stepId: string, action: string) => { + console.log(`Step action: ${action} on step ${stepId}`); + if (action === 'retry') { + setSteps(prevSteps => + prevSteps.map(step => + step.id === stepId + ? { ...step, status: 'pending' as const } + : step + ) + ); + } + }; + + const handleFlowAction = (action: string) => { + console.log(`Flow action: ${action}`); + setIsRunning(action === 'start'); + + if (action === 'start') { + // Simulate workflow progression + setTimeout(() => { + setSteps(prevSteps => + prevSteps.map(step => + step.id === 'step-3' + ? { + ...step, + status: 'completed' as const, + endTime: new Date().toISOString(), + duration: 2100, + output: 'Implementation plan generated:\n1. Create TaskFlow component\n2. Add routing\n3. Update tests' + } + : step.id === 'step-4' + ? { ...step, status: 'running' as const, startTime: new Date().toISOString() } + : step + ) + ); + }, 2000); + } + }; + + return ( + +
+
+

🔄 TaskFlow Demo

+

+ Interactive demonstration of the TaskFlow component for visualizing AI agent workflows +

+
+ + + + +
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/components/taskflow/index.ts b/frontend/src/components/taskflow/index.ts new file mode 100644 index 0000000..243bed8 --- /dev/null +++ b/frontend/src/components/taskflow/index.ts @@ -0,0 +1,2 @@ +export { TaskFlow } from './TaskFlow'; +export type { TaskStep, TaskFlowProps } from './TaskFlow'; \ No newline at end of file