import { useEffect, useState } from "react"; import { useParams, useNavigate } from "react-router-dom"; import { Title, Text, Group, Button, Badge, Stack, Paper, Table, Alert, Loader, Code, } from "@mantine/core"; import { IconPlayerPlay, IconArrowLeft } from "@tabler/icons-react"; import { getDag, triggerDag } from "../api"; import { StatusBadge } from "../components/StatusBadge"; import type { DagDetail as DagDetailType } from "../types"; export function DagDetail() { const { name } = useParams<{ name: string }>(); const navigate = useNavigate(); const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [triggering, setTriggering] = useState(false); const load = async () => { if (!name) return; setLoading(true); try { setData(await getDag(name)); setError(null); } catch (e) { setError((e as Error).message); } finally { setLoading(false); } }; useEffect(() => { load(); }, [name]); const handleRun = async () => { if (!name) return; setTriggering(true); try { await triggerDag(name); setTimeout(load, 1000); } catch (e) { setError((e as Error).message); } finally { setTriggering(false); } }; if (loading) return ; if (error) return {error}; if (!data) return Not found; const { dag, validation, runs } = data; return (
{dag.Name} {dag.Description && ( {dag.Description} )}
{dag.Schedule?.map((s: string) => ( {s} ))} {dag.Type || "chain"} {dag.Tags?.map((t: string) => ( {t} ))} {!validation.Valid && ( {validation.Errors.map((e: string, i: number) => ( {e} ))} )} Steps ({dag.Steps?.length || 0}) {validation.Levels?.map((level: string[], i: number) => ( Level {i}: {level.map((name: string) => { const step = dag.Steps?.find( (s) => s.Name === name || s.ID === name ); return ( {name} {step?.Depends?.length ? ` (after ${step.Depends.join(",")})` : ""} ); })} ))} {dag.Env && Object.keys(dag.Env).length > 0 && ( <> Environment {Object.entries(dag.Env) .map(([k, v]) => `${k}=${v}`) .join("\n")} )} Run History {runs?.length ? ( Status Trigger Started Duration {runs.map((r) => ( navigate(`/runs/${r.ID}`)} > {r.Trigger} {new Date(r.StartedAt).toLocaleString()} {r.FinishedAt ? `${Math.round((new Date(r.FinishedAt).getTime() - new Date(r.StartedAt).getTime()) / 1000)}s` : "running..."} ))}
) : ( No runs yet )}
); }