@@ -30,17 +30,10 @@ const DEFAULT_SEGMENTS = 72
3030const MIN_SEGMENT_PX = 10
3131const MIN_SEGMENT_MS = 60000
3232
33- /**
34- * Predetermined heights for skeleton bars to avoid hydration mismatch.
35- * Using static values instead of Math.random() ensures server/client consistency.
36- */
3733const SKELETON_BAR_HEIGHTS = [
3834 45 , 72 , 38 , 85 , 52 , 68 , 30 , 90 , 55 , 42 , 78 , 35 , 88 , 48 , 65 , 28 , 82 , 58 , 40 , 75 , 32 , 95 , 50 , 70 ,
3935]
4036
41- /**
42- * Skeleton loader for a single graph card
43- */
4437function GraphCardSkeleton ( { title } : { title : string } ) {
4538 return (
4639 < div className = 'flex flex-col overflow-hidden rounded-[6px] bg-[var(--surface-elevated)]' >
@@ -69,9 +62,6 @@ function GraphCardSkeleton({ title }: { title: string }) {
6962 )
7063}
7164
72- /**
73- * Skeleton loader for a workflow row in the workflows list
74- */
7565function WorkflowRowSkeleton ( ) {
7666 return (
7767 < div className = 'flex h-[44px] items-center gap-[16px] px-[24px]' >
@@ -89,9 +79,6 @@ function WorkflowRowSkeleton() {
8979 )
9080}
9181
92- /**
93- * Skeleton loader for the workflows list table
94- */
9582function WorkflowsListSkeleton ( { rowCount = 5 } : { rowCount ?: number } ) {
9683 return (
9784 < div className = 'flex h-full flex-col overflow-hidden rounded-[6px] bg-[var(--surface-1)]' >
@@ -115,9 +102,6 @@ function WorkflowsListSkeleton({ rowCount = 5 }: { rowCount?: number }) {
115102 )
116103}
117104
118- /**
119- * Complete skeleton loader for the entire dashboard
120- */
121105function DashboardSkeleton ( ) {
122106 return (
123107 < div className = 'mt-[24px] flex min-h-0 flex-1 flex-col pb-[24px]' >
@@ -141,11 +125,6 @@ interface DashboardProps {
141125 error ?: Error | null
142126}
143127
144- /**
145- * Dashboard component that visualizes workflow execution metrics.
146- * Derives all metrics from the logs data passed as a prop, ensuring
147- * consistency with the logs list view.
148- */
149128export default function Dashboard ( { logs, isLoading, error } : DashboardProps ) {
150129 const [ segmentCount , setSegmentCount ] = useState < number > ( DEFAULT_SEGMENTS )
151130 const [ selectedSegments , setSelectedSegments ] = useState < Record < string , number [ ] > > ( { } )
@@ -154,19 +133,10 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
154133
155134 const { workflowIds, searchQuery, toggleWorkflowId, timeRange } = useFilterStore ( )
156135
157- // Get all workflows from the registry
158136 const allWorkflows = useWorkflowRegistry ( ( state ) => state . workflows )
159137
160- /**
161- * Derive expanded workflow from filter store.
162- * When exactly one workflow is selected in filters, treat it as "expanded".
163- */
164138 const expandedWorkflowId = workflowIds . length === 1 ? workflowIds [ 0 ] : null
165139
166- /**
167- * Map of workflowId to most recent execution timestamp from logs.
168- * Derived from the logs prop.
169- */
170140 const lastExecutionByWorkflow = useMemo ( ( ) => {
171141 const map = new Map < string , number > ( )
172142 for ( const log of logs ) {
@@ -181,10 +151,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
181151 return map
182152 } , [ logs ] )
183153
184- /**
185- * Compute time bounds from logs for segment calculation.
186- * Uses actual log timestamps to determine the time range.
187- */
188154 const timeBounds = useMemo ( ( ) => {
189155 if ( logs . length === 0 ) {
190156 const now = new Date ( )
@@ -200,27 +166,19 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
200166 if ( ts > maxTime ) maxTime = ts
201167 }
202168
203- // Ensure end is at least now for running executions
204169 const end = new Date ( Math . max ( maxTime , Date . now ( ) ) )
205170 const start = new Date ( minTime )
206171
207172 return { start, end }
208173 } , [ logs ] )
209174
210- /**
211- * Build workflow executions with time segments from logs.
212- * Includes ALL workflows from the registry, not just those with logs.
213- * Workflows without logs will have empty segments.
214- */
215175 const { executions, aggregateSegments, segmentMs } = useMemo ( ( ) => {
216176 const allWorkflowsList = Object . values ( allWorkflows )
217177
218- // If no workflows exist in the workspace, return empty
219178 if ( allWorkflowsList . length === 0 ) {
220179 return { executions : [ ] , aggregateSegments : [ ] , segmentMs : 0 }
221180 }
222181
223- // Determine time bounds - use logs if available, otherwise use a default 24h window
224182 const { start, end } =
225183 logs . length > 0
226184 ? timeBounds
@@ -232,7 +190,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
232190 Math . floor ( totalMs / Math . max ( 1 , segmentCount ) )
233191 )
234192
235- // Group logs by workflow
236193 const logsByWorkflow = new Map < string , WorkflowLog [ ] > ( )
237194 for ( const log of logs ) {
238195 const wfId = log . workflowId
@@ -242,7 +199,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
242199 logsByWorkflow . get ( wfId ) ! . push ( log )
243200 }
244201
245- // Build segments for ALL workflows (from registry), not just those with logs
246202 const workflowExecutions : WorkflowExecution [ ] = [ ]
247203
248204 for ( const workflow of allWorkflowsList ) {
@@ -282,7 +238,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
282238 }
283239 }
284240
285- // Calculate success rates and avg durations
286241 let totalExecs = 0
287242 let totalSuccess = 0
288243
@@ -312,15 +267,13 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
312267 } )
313268 }
314269
315- // Sort by error rate (highest errors first), then by name for consistency
316270 workflowExecutions . sort ( ( a , b ) => {
317271 const errA = a . overallSuccessRate < 100 ? 1 - a . overallSuccessRate / 100 : 0
318272 const errB = b . overallSuccessRate < 100 ? 1 - b . overallSuccessRate / 100 : 0
319273 if ( errA !== errB ) return errB - errA
320274 return a . workflowName . localeCompare ( b . workflowName )
321275 } )
322276
323- // Build aggregate segments (only from logs data)
324277 const aggSegments : {
325278 timestamp : string
326279 totalExecutions : number
@@ -361,20 +314,13 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
361314 }
362315 } , [ logs , timeBounds , segmentCount , allWorkflows ] )
363316
364- /**
365- * Filters and sorts workflow executions.
366- * Only applies workflowIds filter to hide non-selected workflows.
367- * Results are sorted by most recent execution time (newest first).
368- */
369317 const filteredExecutions = useMemo ( ( ) => {
370318 let filtered = executions
371319
372- // Only filter by workflowIds if specific workflows are selected
373320 if ( workflowIds . length > 0 ) {
374321 filtered = filtered . filter ( ( wf ) => workflowIds . includes ( wf . workflowId ) )
375322 }
376323
377- // Apply search filter
378324 if ( searchQuery . trim ( ) ) {
379325 const query = searchQuery . toLowerCase ( ) . trim ( )
380326 filtered = filtered . filter ( ( wf ) => wf . workflowName . toLowerCase ( ) . includes ( query ) )
@@ -384,7 +330,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
384330 const timeA = lastExecutionByWorkflow . get ( a . workflowId ) ?? 0
385331 const timeB = lastExecutionByWorkflow . get ( b . workflowId ) ?? 0
386332
387- // Workflows with executions come first
388333 if ( ! timeA && ! timeB ) return a . workflowName . localeCompare ( b . workflowName )
389334 if ( ! timeA ) return 1
390335 if ( ! timeB ) return - 1
@@ -393,10 +338,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
393338 } )
394339 } , [ executions , lastExecutionByWorkflow , workflowIds , searchQuery ] )
395340
396- /**
397- * Computes aggregated metrics for charts based on selected segments and filters.
398- * Applies workflow filter, segment selection, and recalculates aggregates accordingly.
399- */
400341 const globalDetails = useMemo ( ( ) => {
401342 if ( ! aggregateSegments . length ) return null
402343
@@ -473,14 +414,12 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
473414 value : s . avgDurationMs ?? 0 ,
474415 } ) )
475416
476- // Compute totals from the segments used in charts (respects segment selection)
477417 const totalRuns = segmentsToUse . reduce ( ( sum , s ) => sum + s . totalExecutions , 0 )
478418 const totalErrors = segmentsToUse . reduce (
479419 ( sum , s ) => sum + ( s . totalExecutions - s . successfulExecutions ) ,
480420 0
481421 )
482422
483- // Compute weighted average latency
484423 let weightedLatencySum = 0
485424 let latencyCount = 0
486425 for ( const s of segmentsToUse ) {
@@ -501,7 +440,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
501440 }
502441 } , [ aggregateSegments , selectedSegments , filteredExecutions , expandedWorkflowId ] )
503442
504- /** Toggles workflow filter using the filter store for URL-synced filtering */
505443 const handleToggleWorkflow = useCallback (
506444 ( workflowId : string ) => {
507445 toggleWorkflowId ( workflowId )
@@ -570,13 +508,11 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
570508 [ lastAnchorIndices ]
571509 )
572510
573- // Clear selected segments when logs change (filters changed)
574511 useEffect ( ( ) => {
575512 setSelectedSegments ( { } )
576513 setLastAnchorIndices ( { } )
577514 } , [ logs , timeRange , workflowIds , searchQuery ] )
578515
579- // Handle responsive segment count based on container width
580516 useEffect ( ( ) => {
581517 if ( ! barsAreaRef . current ) return
582518 const el = barsAreaRef . current
@@ -601,7 +537,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
601537 }
602538 } , [ ] )
603539
604- // Show skeleton while loading (only on initial load with no workflows)
605540 if ( isLoading && Object . keys ( allWorkflows ) . length === 0 ) {
606541 return < DashboardSkeleton />
607542 }
@@ -618,7 +553,6 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
618553 )
619554 }
620555
621- // Show empty state only when no workflows exist in the workspace
622556 if ( Object . keys ( allWorkflows ) . length === 0 ) {
623557 return (
624558 < div className = 'mt-[24px] flex flex-1 items-center justify-center' >
0 commit comments