"use client"; import { Suspense, useEffect, useState } from "react"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; import { ArrowLeft, ArrowRight, RefreshCw } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { api, type ExecutionStatus, type Run } from "@/lib/api"; import { formatDate } from "@/lib/utils"; export default function MultiExecutionPage() { return ( Loading…}> ); } function MultiExecutionView() { const params = useSearchParams(); const idsParam = params.get("ids") ?? ""; const ids = idsParam .split(",") .map((s) => s.trim()) .filter(Boolean); return (

{ids.length} runs dispatched

Each card streams its own status. Click into one for the live canvas.

{ids.length === 0 ? (

No execution IDs provided.

) : (
{ids.map((id) => ( ))}
)}
); } function statusVariant(s?: string) { switch ((s || "").toLowerCase()) { case "success": case "completed": return "success" as const; case "running": case "pending": return "secondary" as const; case "failed": case "error": return "destructive" as const; case "waiting": case "paused": return "warning" as const; default: return "outline" as const; } } function RunCard({ id }: { id: string }) { const [status, setStatus] = useState(null); const [run, setRun] = useState(null); async function refresh() { try { const [s, runs] = await Promise.all([ api.getExecution(id).catch(() => null), api.listRuns({ limit: 100 }).catch(() => [] as Run[]), ]); if (s) setStatus(s); const r = runs.find((x) => x.id === id) ?? null; setRun(r); } catch { // ignore } } useEffect(() => { refresh(); const t = setInterval(refresh, 3000); return () => clearInterval(t); // eslint-disable-next-line react-hooks/exhaustive-deps }, [id]); const s = (status?.status as string) || run?.status || "running"; return (
{run?.pipelineName || "Pipeline"} {id}
{s}
{run?.startedAt ? <>started {formatDate(run.startedAt)} : "—"}
); }