diff --git a/app/w/components/console/components/console-entry/console-entry.tsx b/app/w/components/console/components/console-entry/console-entry.tsx new file mode 100644 index 0000000000..610d13588a --- /dev/null +++ b/app/w/components/console/components/console-entry/console-entry.tsx @@ -0,0 +1,75 @@ +import { useState, useMemo } from 'react' +import { formatDistanceToNow, format } from 'date-fns' +import { + Terminal, + Clock, + Calendar, + CheckCircle2, + AlertCircle, +} from 'lucide-react' +import { ConsoleEntry as ConsoleEntryType } from '@/stores/console/types' +import { JSONView } from '../json-view/json-view' + +interface ConsoleEntryProps { + entry: ConsoleEntryType +} + +export function ConsoleEntry({ entry }: ConsoleEntryProps) { + const [isExpanded, setIsExpanded] = useState(false) + + const timeAgo = useMemo( + () => + formatDistanceToNow(new Date(entry.startedAt), { + addSuffix: true, + }), + [entry.startedAt] + ) + + const statusIcon = entry.error ? ( + + ) : ( + + ) + + return ( +
+
+ {entry.blockName && ( +
+ {statusIcon} + {entry.blockName} +
+ )} +
+
+ + {format(new Date(entry.startedAt), 'HH:mm:ss')} +
+
+ + Duration: {entry.durationMs}ms +
+
+ +
+
+ +
+ +
+
+ + {entry.error && ( +
+ +
+
Error
+
{entry.error}
+
+
+ )} +
+
+
+ ) +} diff --git a/app/w/components/console/components/json-view/json-view.tsx b/app/w/components/console/components/json-view/json-view.tsx new file mode 100644 index 0000000000..b9fcfae22d --- /dev/null +++ b/app/w/components/console/components/json-view/json-view.tsx @@ -0,0 +1,65 @@ +import { useState } from 'react' + +interface JSONViewProps { + data: any + level?: number +} + +export const JSONView = ({ data, level = 0 }: JSONViewProps) => { + const [isCollapsed, setIsCollapsed] = useState(true) + + if (data === null) return null + if (typeof data !== 'object') { + return ( + + {JSON.stringify(data)} + + ) + } + + const isArray = Array.isArray(data) + const items = isArray ? data : Object.entries(data) + const isEmpty = items.length === 0 + + if (isEmpty) { + return {isArray ? '[]' : '{}'} + } + + return ( +
+ { + e.stopPropagation() + setIsCollapsed(!isCollapsed) + }} + > + {isCollapsed ? '▶' : '▼'} {isArray ? '[' : '{'} + {isCollapsed ? '...' : ''} + + {!isCollapsed && ( +
+ {isArray + ? items.map((item, index) => ( +
+ + {index < items.length - 1 && ','} +
+ )) + : (items as [string, any][]).map(([key, value], index) => ( +
+ {key}:{' '} + + {index < items.length - 1 && ','} +
+ ))} +
+ )} + {isArray ? ']' : '}'} +
+ ) +} diff --git a/app/w/components/console/console.tsx b/app/w/components/console/console.tsx index e0c07edd57..a92b1992ad 100644 --- a/app/w/components/console/console.tsx +++ b/app/w/components/console/console.tsx @@ -1,16 +1,7 @@ 'use client' import { useState, useMemo, useEffect } from 'react' -import { formatDistanceToNow, format } from 'date-fns' -import { - PanelLeftClose, - Terminal, - XCircle, - Clock, - Calendar, - CheckCircle2, - AlertCircle, -} from 'lucide-react' +import { PanelLeftClose, Terminal } from 'lucide-react' import { Tooltip, TooltipContent, @@ -19,115 +10,8 @@ import { import { useConsoleStore } from '@/stores/console/store' import { ScrollArea } from '@/components/ui/scroll-area' import { Button } from '@/components/ui/button' -import { ConsoleEntry as ConsoleEntryType } from '@/stores/console/types' import { useWorkflowRegistry } from '@/stores/workflow/registry' - -function JSONView({ data, level = 0 }: { data: any; level?: number }) { - const [isCollapsed, setIsCollapsed] = useState(true) - - if (data === null) return null - if (typeof data !== 'object') { - return ( - - {JSON.stringify(data)} - - ) - } - - const isArray = Array.isArray(data) - const items = isArray ? data : Object.entries(data) - const isEmpty = items.length === 0 - - if (isEmpty) { - return {isArray ? '[]' : '{}'} - } - - return ( -
- { - e.stopPropagation() - setIsCollapsed(!isCollapsed) - }} - > - {isCollapsed ? '▶' : '▼'} {isArray ? '[' : '{'} - {isCollapsed ? '...' : ''} - - {!isCollapsed && ( -
- {isArray - ? items.map((item, index) => ( -
- - {index < items.length - 1 && ','} -
- )) - : (items as [string, any][]).map(([key, value], index) => ( -
- {key}:{' '} - - {index < items.length - 1 && ','} -
- ))} -
- )} - {isArray ? ']' : '}'} -
- ) -} - -function ConsoleEntry({ entry }: { entry: ConsoleEntryType }) { - const [isExpanded, setIsExpanded] = useState(false) - - const timeAgo = useMemo( - () => - formatDistanceToNow(new Date(entry.startedAt), { - addSuffix: true, - }), - [entry.startedAt] - ) - - return ( -
-
-
-
- - {format(new Date(entry.startedAt), 'HH:mm:ss')} -
-
- - Duration: {entry.durationMs}ms -
-
- -
-
- -
- -
-
- - {entry.error && ( -
- -
-
Error
-
{entry.error}
-
-
- )} -
-
-
- ) -} +import { ConsoleEntry } from './components/console-entry/console-entry' export function Console() { const [isCollapsed, setIsCollapsed] = useState(false) @@ -137,7 +21,6 @@ export function Console() { const clearConsole = useConsoleStore((state) => state.clearConsole) const { activeWorkflowId } = useWorkflowRegistry() - // Filter entries for active workflow const filteredEntries = useMemo(() => { return entries.filter((entry) => entry.workflowId === activeWorkflowId) }, [entries, activeWorkflowId]) diff --git a/app/w/hooks/use-workflow-execution.ts b/app/w/hooks/use-workflow-execution.ts index 69a08bddd6..76beaa70dc 100644 --- a/app/w/hooks/use-workflow-execution.ts +++ b/app/w/hooks/use-workflow-execution.ts @@ -44,7 +44,8 @@ export function useWorkflowExecution() { startedAt: log.startedAt, endedAt: log.endedAt, workflowId: activeWorkflowId, - timestamp: log.startedAt // Using startedAt as the timestamp + timestamp: log.startedAt, + blockName: log.blockTitle }) }) } @@ -57,7 +58,8 @@ export function useWorkflowExecution() { startedAt: result.metadata?.startTime || new Date().toISOString(), endedAt: result.metadata?.endTime || new Date().toISOString(), workflowId: activeWorkflowId, - timestamp: result.metadata?.startTime || new Date().toISOString() + timestamp: result.metadata?.startTime || new Date().toISOString(), + blockName: 'Workflow Result' }) if (result.logs) { @@ -111,7 +113,8 @@ export function useWorkflowExecution() { startedAt: new Date().toISOString(), endedAt: new Date().toISOString(), workflowId: activeWorkflowId, - timestamp: new Date().toISOString() + timestamp: new Date().toISOString(), + blockName: 'Error' }) addNotification('error', `Workflow execution failed: ${errorMessage}`, activeWorkflowId) diff --git a/stores/console/types.ts b/stores/console/types.ts index d1ed6f7160..2e436d5d21 100644 --- a/stores/console/types.ts +++ b/stores/console/types.ts @@ -6,7 +6,8 @@ export interface ConsoleEntry { startedAt: string endedAt: string workflowId?: string | null - timestamp: string + timestamp: string + blockName?: string } export interface ConsoleStore {