diff --git a/attractor-web/src/StartForm.tsx b/attractor-web/src/StartForm.tsx new file mode 100644 index 000000000..e27545c0b --- /dev/null +++ b/attractor-web/src/StartForm.tsx @@ -0,0 +1,76 @@ +import { useState, useCallback, type FormEvent } from "react"; +import { startPipeline, listPipelines, type PipelineStatusResponse } from "./api"; +import { usePolling } from "./hooks"; + +const PLACEHOLDER = `digraph Example { + graph [goal="Run a simple pipeline"] + start [shape=Mdiamond] + exit [shape=Msquare] + start -> exit +}`; + +interface StartFormProps { + onStart: (id: string) => void; +} + +export function StartForm({ onStart }: StartFormProps) { + const [submitting, setSubmitting] = useState(false); + const [error, setError] = useState(null); + + const fetcher = useCallback(() => listPipelines(), []); + const { data: pipelines } = usePolling(fetcher, 3000, true); + + async function handleSubmit(e: FormEvent) { + e.preventDefault(); + const form = e.currentTarget; + const dotSource = new FormData(form).get("dot_source") as string; + if (!dotSource.trim()) return; + + setSubmitting(true); + setError(null); + + try { + const { id } = await startPipeline(dotSource); + onStart(id); + } catch (err) { + setError(String(err)); + } finally { + setSubmitting(false); + } + } + + return ( +
+ +