import React from 'react'; import '@shared/styles/theme.css'; import { Badge, Expandable } from '@shared/components'; import { useToolData } from '@shared/hooks/useToolData'; import type { OperationResultData, OperationType } from '@shared/types'; const TOOL_TO_OP: Record = { n8n_create_workflow: 'create', n8n_update_full_workflow: 'update', n8n_update_partial_workflow: 'partial_update', n8n_delete_workflow: 'delete', n8n_test_workflow: 'test', n8n_autofix_workflow: 'autofix', n8n_deploy_template: 'deploy', }; const OP_CONFIG: Record = { create: { icon: '+', label: 'WORKFLOW CREATED', color: 'var(--n8n-success)' }, update: { icon: '⟳', label: 'WORKFLOW UPDATED', color: 'var(--n8n-info)' }, partial_update: { icon: '⟳', label: 'WORKFLOW UPDATED', color: 'var(--n8n-info)' }, delete: { icon: '−', label: 'WORKFLOW DELETED', color: 'var(--n8n-error)' }, test: { icon: '▶', label: 'WORKFLOW TESTED', color: 'var(--n8n-info)' }, autofix: { icon: '⚡', label: 'WORKFLOW AUTO-FIXED', color: 'var(--n8n-warning)' }, deploy: { icon: '↓', label: 'TEMPLATE DEPLOYED', color: 'var(--n8n-success)' }, }; function detectOperation(toolName: string | null, data: OperationResultData): OperationType { if (toolName && TOOL_TO_OP[toolName]) return TOOL_TO_OP[toolName]; const d = data.data; if (d?.deleted) return 'delete'; if (d?.templateId) return 'deploy'; if (d?.fixesApplied !== undefined || d?.fixes) return 'autofix'; if (d?.executionId) return 'test'; if (d?.operationsApplied !== undefined) return 'partial_update'; return 'create'; } function PartialUpdatePanel({ details }: { details?: Record }) { if (!details) return null; const applied = Array.isArray(details.applied) ? details.applied as string[] : []; const failed = Array.isArray(details.failed) ? details.failed as string[] : []; const warnings = Array.isArray(details.warnings) ? details.warnings as string[] : []; if (applied.length === 0 && failed.length === 0) return null; const items = [ ...applied.map((m) => ({ icon: '✓', color: 'var(--n8n-success)', text: String(m) })), ...failed.map((m) => ({ icon: '✗', color: 'var(--n8n-error)', text: String(m) })), ...warnings.map((m) => ({ icon: '!', color: 'var(--n8n-warning)', text: String(m) })), ]; const summary = (
{applied.length} applied {failed.length > 0 && <>, {failed.length} failed}
); const list = items.map((item, i) => (
{item.icon} {item.text}
)); if (items.length > 5) { return <>{summary}{list}; } return <>{summary}
{list}
; } function AutofixPanel({ data }: { data: OperationResultData }) { const fixes = Array.isArray(data.data?.fixes) ? data.data!.fixes as Record[] : []; const isPreview = data.data?.preview === true; const fixCount = data.data?.fixesApplied ?? fixes.length; return ( <> {isPreview && (
PREVIEW MODE
)} {fixes.length > 0 && ( {fixes.map((fix, i) => { const confidence = String(fix.confidence ?? '').toUpperCase(); return (
{String(fix.description ?? fix.message ?? JSON.stringify(fix))} {confidence && ( {confidence} )}
); })}
)} ); } function DeployPanel({ data }: { data: OperationResultData }) { const d = data.data; const creds = Array.isArray(d?.requiredCredentials) ? d!.requiredCredentials as string[] : []; const triggerType = d?.triggerType; const autoFixStatus = d?.autoFixStatus; return (
0 ? '8px' : 0 }}> {triggerType && {String(triggerType)}} {autoFixStatus && {String(autoFixStatus)}}
{creds.length > 0 && (
Required credentials:
{creds.map((c, i) => (
○ {c}
))}
)}
); } function TestPanel({ data }: { data: OperationResultData }) { const execId = data.data?.executionId; const triggerType = data.data?.triggerType; if (!execId && !triggerType) return null; return (
{execId && (
Execution: {execId}
)} {triggerType && {String(triggerType)}}
); } function ErrorDetails({ details }: { details?: Record }) { if (!details) return null; if (Array.isArray(details.errors)) { const errs = details.errors as string[]; return (
    {errs.map((e, i) =>
  • {String(e)}
  • )}
); } const entries = Object.entries(details).filter(([, v]) => v !== undefined && v !== null); if (entries.length === 0) return null; const hasComplexValues = entries.some(([, v]) => typeof v === 'object'); if (hasComplexValues) { return (
          {JSON.stringify(details, null, 2)}
        
); } return (
{entries.map(([key, val]) => (
{key}: {String(val)}
))}
); } export default function App() { const { data, error, isConnected, toolName } = useToolData(); if (error) { return
Error: {error}
; } if (!isConnected) { return
Connecting...
; } if (!data) { return
Waiting for data...
; } const isSuccess = data.success === true; const op = detectOperation(toolName, data); const config = OP_CONFIG[op]; const workflowName = data.data?.name || data.data?.workflowName; const workflowId = data.data?.id || data.data?.workflowId; const nodeCount = data.data?.nodeCount; const isActive = data.data?.active; const operationsApplied = data.data?.operationsApplied; const executionId = data.data?.executionId; const fixesApplied = data.data?.fixesApplied; const templateId = data.data?.templateId; const label = isSuccess ? config.label : config.label + ' FAILED'; const metaParts: string[] = []; if (workflowId) metaParts.push(`ID: ${workflowId}`); if (nodeCount !== undefined) metaParts.push(`${nodeCount} nodes`); if (isActive !== undefined) metaParts.push(isActive ? 'active' : 'inactive'); if (operationsApplied !== undefined) metaParts.push(`${operationsApplied} ops applied`); if (executionId) metaParts.push(`exec: ${executionId}`); if (fixesApplied !== undefined) metaParts.push(`${fixesApplied} fixes`); if (templateId) metaParts.push(`template: ${templateId}`); const containerStyle = op === 'delete' ? { maxWidth: '480px', borderLeft: '3px solid var(--n8n-error)', paddingLeft: '12px', } : { maxWidth: '480px' }; return (
{/* Header */}
{config.icon}
{label}
{workflowName && (
{workflowName}
)} {metaParts.length > 0 && (
{metaParts.join(' · ')}
)}
{isSuccess ? 'Success' : 'Error'}
{/* Error info */} {!isSuccess && data.error && (
{data.error}
)} {/* Operation-specific panels */} {isSuccess && op === 'partial_update' && } {isSuccess && op === 'autofix' && } {isSuccess && op === 'deploy' && } {isSuccess && op === 'test' && } {/* Error details */} {!isSuccess && } {/* Fallback details for success states without specific panels */} {isSuccess && !['partial_update', 'autofix', 'deploy', 'test'].includes(op) && data.details && ( )}
); }