'use client'; import { useState, useEffect } from 'react'; import Link from 'next/link'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import { Skeleton } from '@/components/ui/skeleton'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { ArrowLeft, Activity, } from 'lucide-react'; interface PipelineExecution { id: number; pipeline_id: number; trigger_source: string; status: string; started_at: string | null; duration_ms: number | null; error_message: string | null; created_at: string; has_fallback: boolean; } interface Pipeline { id: number; name: string; } const STATUS_COLORS: Record = { completed: 'bg-green-100 text-green-700', failed: 'bg-red-100 text-red-700', running: 'bg-blue-100 text-blue-700', pending: 'bg-gray-100 text-gray-700', skipped: 'bg-slate-100 text-slate-500', waiting: 'bg-yellow-100 text-yellow-700', }; function formatDuration(ms: number | null): string { if (ms == null) return '—'; if (ms < 1000) return `${ms}ms`; return `${(ms / 1000).toFixed(1)}s`; } function formatDate(iso: string | null): string { if (!iso) return '—'; return new Date(iso).toLocaleString(); } export default function PipelineExecutionsPage() { const [executions, setExecutions] = useState([]); const [pipelines, setPipelines] = useState([]); const [isLoading, setIsLoading] = useState(true); const [fallbacksOnly, setFallbacksOnly] = useState(false); const [pipelineFilter, setPipelineFilter] = useState('all'); useEffect(() => { fetchPipelines(); }, []); useEffect(() => { fetchExecutions(); }, [fallbacksOnly, pipelineFilter]); // eslint-disable-line react-hooks/exhaustive-deps const fetchPipelines = async () => { try { const res = await fetch('/api/pipelines'); if (res.ok) { const data = await res.json(); setPipelines(data.data || []); } } catch (err) { console.error('Failed to fetch pipelines:', err); } }; const fetchExecutions = async () => { setIsLoading(true); try { const params = new URLSearchParams({ limit: '100' }); if (fallbacksOnly) params.set('fallbacks_only', '1'); if (pipelineFilter !== 'all') params.set('pipeline_id', pipelineFilter); const res = await fetch(`/api/admin/pipeline-executions?${params.toString()}`); if (res.ok) { const data = await res.json(); setExecutions(data.data || []); } } catch (err) { console.error('Failed to fetch executions:', err); } finally { setIsLoading(false); } }; return (

Pipeline Executions

Pipeline-engine execution history across all pipelines

{/* Filters */}
{isLoading ? (
{[1, 2, 3].map(i => ( ))}
) : executions.length === 0 ? (

No executions match the current filter.

) : (
{executions.map(exec => (
#{exec.id} Pipeline {exec.pipeline_id} {exec.status} {exec.has_fallback && ( fallback )} {exec.trigger_source}
{formatDuration(exec.duration_ms)} {formatDate(exec.started_at ?? exec.created_at)}
{exec.error_message && (

{exec.error_message}

)}
))}
)}
); }