import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { Button, Text, Stack, Group, Card, Progress } from "@mantine/core"; import PlayArrowIcon from "@mui/icons-material/PlayArrow"; import CheckIcon from "@mui/icons-material/Check"; import { useFileSelection } from "../../../contexts/FileContext"; import { useFlatToolRegistry } from "../../../data/useTranslatedToolRegistry"; import { AutomationConfig, ExecutionStep } from "../../../types/automation"; import { AUTOMATION_CONSTANTS, EXECUTION_STATUS } from "../../../constants/automation"; import { useResourceCleanup } from "../../../utils/resourceManager"; interface AutomationRunProps { automation: AutomationConfig; onComplete: () => void; automateOperation?: any; // TODO: Type this properly when available } export default function AutomationRun({ automation, onComplete, automateOperation }: AutomationRunProps) { const { t } = useTranslation(); const { selectedFiles } = useFileSelection(); const toolRegistry = useFlatToolRegistry(); const cleanup = useResourceCleanup(); // Progress tracking state const [executionSteps, setExecutionSteps] = useState([]); const [currentStepIndex, setCurrentStepIndex] = useState(-1); // Use the operation hook's loading state const isExecuting = automateOperation?.isLoading || false; const hasResults = automateOperation?.files.length > 0 || automateOperation?.downloadUrl !== null; // Initialize execution steps from automation React.useEffect(() => { if (automation?.operations) { const steps = automation.operations.map((op: any, index: number) => { const tool = toolRegistry[op.operation]; return { id: `${op.operation}-${index}`, operation: op.operation, name: tool?.name || op.operation, status: EXECUTION_STATUS.PENDING }; }); setExecutionSteps(steps); setCurrentStepIndex(-1); } }, [automation, toolRegistry]); // Cleanup when component unmounts React.useEffect(() => { return () => { // Reset progress state when component unmounts setExecutionSteps([]); setCurrentStepIndex(-1); // Clean up any blob URLs cleanup(); }; }, [cleanup]); const executeAutomation = async () => { if (!selectedFiles || selectedFiles.length === 0) { return; } if (!automateOperation) { console.error('No automateOperation provided'); return; } // Reset progress tracking setCurrentStepIndex(0); setExecutionSteps(prev => prev.map(step => ({ ...step, status: EXECUTION_STATUS.PENDING, error: undefined }))); try { // Use the automateOperation.executeOperation to handle file consumption properly await automateOperation.executeOperation( { automationConfig: automation, onStepStart: (stepIndex: number, operationName: string) => { setCurrentStepIndex(stepIndex); setExecutionSteps(prev => prev.map((step, idx) => idx === stepIndex ? { ...step, status: EXECUTION_STATUS.RUNNING } : step )); }, onStepComplete: (stepIndex: number, resultFiles: File[]) => { setExecutionSteps(prev => prev.map((step, idx) => idx === stepIndex ? { ...step, status: EXECUTION_STATUS.COMPLETED } : step )); }, onStepError: (stepIndex: number, error: string) => { setExecutionSteps(prev => prev.map((step, idx) => idx === stepIndex ? { ...step, status: EXECUTION_STATUS.ERROR, error } : step )); } }, selectedFiles ); // Mark all as completed and reset current step setCurrentStepIndex(-1); console.log(`✅ Automation completed successfully`); } catch (error: any) { console.error("Automation execution failed:", error); setCurrentStepIndex(-1); } }; const getProgress = () => { if (executionSteps.length === 0) return 0; const completedSteps = executionSteps.filter(step => step.status === EXECUTION_STATUS.COMPLETED).length; return (completedSteps / executionSteps.length) * 100; }; const getStepIcon = (step: ExecutionStep) => { switch (step.status) { case EXECUTION_STATUS.COMPLETED: return ; case EXECUTION_STATUS.ERROR: return ; case EXECUTION_STATUS.RUNNING: return
; default: return
; } }; return (
{/* Automation Info */} {automation?.name || t("automate.sequence.unnamed", "Unnamed Automation")} {t("automate.sequence.steps", "{{count}} steps", { count: executionSteps.length })} {/* Progress Bar */} {isExecuting && (
Progress: {currentStepIndex + 1}/{executionSteps.length}
)} {/* Execution Steps */} {executionSteps.map((step, index) => ( {index + 1} {getStepIcon(step)}
{step.name} {step.error && ( {step.error} )}
))}
{/* Action Buttons */} {hasResults && ( )}
); }