78 lines
4.2 KiB
TypeScript
78 lines
4.2 KiB
TypeScript
"use client";
|
|
|
|
import React from "react";
|
|
import { GitFork, PlayCircle, Clock, CheckCircle2, AlertTriangle } from "lucide-react";
|
|
import { Card, CardBody, CardHeader, CardTitle } from "@/components/ui/Card";
|
|
import { Badge, JobStatusBadge } from "@/components/ui/Badge";
|
|
import { EmptyState } from "@/components/ui/EmptyState";
|
|
import { MetricCard } from "@/components/ui/MetricCard";
|
|
import { fmtDate } from "@/lib/utils";
|
|
|
|
const PIPELINES = [
|
|
{ id: "pl-indexing", name: "Repository Indexing", stage: "connectors → asf-worker → MongoDB", last: "2025-11-22T09:10:00Z", status: "running", runs: 184 },
|
|
{ id: "pl-code-analysis", name: "Code Analysis", stage: "PR event → asf-ai → artifact + relationships", last: "2025-11-22T08:40:00Z", status: "queued", runs: 52 },
|
|
{ id: "pl-test-gen", name: "AI Test Generation", stage: "Task → Prompt → LLM → PR", last: "2025-11-21T18:02:00Z", status: "completed", runs: 13 },
|
|
{ id: "pl-deploy", name: "Deployment Rollout", stage: "Build OK → Argo → runtime_events", last: "2025-11-20T14:11:00Z", status: "completed", runs: 27 },
|
|
{ id: "pl-incident", name: "Incident Traceback", stage: "Incident → asf-context → root-cause", last: "2025-11-19T10:55:00Z", status: "failed", runs: 4 },
|
|
];
|
|
|
|
export default function PipelinesPage() {
|
|
return (
|
|
<div className="p-6 lg:p-8 max-w-[1400px] mx-auto">
|
|
<header className="mb-6 flex flex-wrap items-start justify-between gap-3">
|
|
<div>
|
|
<h1 className="text-2xl font-semibold tracking-tight text-slate-900 flex items-center gap-2">
|
|
<GitFork className="w-6 h-6 text-brand-600" />
|
|
Pipelines
|
|
</h1>
|
|
<p className="mt-1 text-sm text-slate-500">
|
|
RabbitMQ-backed flows: domain events → workers → downstream artifacts. This page lists currently registered pipeline topologies.
|
|
</p>
|
|
</div>
|
|
<Badge tone="neutral">Event backbone · RabbitMQ</Badge>
|
|
</header>
|
|
|
|
<section className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
|
<MetricCard label="Running" value={1} tone="blue" icon={<PlayCircle className="w-5 h-5" />} />
|
|
<MetricCard label="Queued" value={1} tone="neutral" icon={<Clock className="w-5 h-5" />} />
|
|
<MetricCard label="Completed (7d)" value={112} tone="green" icon={<CheckCircle2 className="w-5 h-5" />} delta={4.2} />
|
|
<MetricCard label="Failed (24h)" value={1} tone="red" icon={<AlertTriangle className="w-5 h-5" />} />
|
|
</section>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Registered pipelines</CardTitle>
|
|
<Badge tone="brand">{PIPELINES.length} topologies</Badge>
|
|
</CardHeader>
|
|
<CardBody className="p-0">
|
|
<ul className="divide-y divide-slate-100">
|
|
{PIPELINES.length === 0 ? (
|
|
<li className="p-6"><EmptyState title="No pipelines yet" description="Register an async topology in asf-worker to surface it here." /></li>
|
|
) : PIPELINES.map((p) => (
|
|
<li key={p.id} className="p-4 hover:bg-slate-50 transition-colors flex items-start gap-4">
|
|
<div className="w-10 h-10 mt-0.5 rounded-lg bg-brand-50 border border-brand-100 grid place-items-center text-brand-600 shrink-0">
|
|
<GitFork className="w-5 h-5" />
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<div className="flex items-center gap-2 flex-wrap">
|
|
<div className="font-semibold text-slate-800">{p.name}</div>
|
|
<Badge tone="neutral" className="asf-monospace">{p.id}</Badge>
|
|
<JobStatusBadge status={p.status} />
|
|
</div>
|
|
<div className="mt-1 text-xs text-slate-600 font-mono bg-slate-50 inline-block px-2 py-1 rounded-md">
|
|
{p.stage}
|
|
</div>
|
|
<div className="mt-2 flex flex-wrap items-center gap-4 text-xs text-slate-500">
|
|
<span>Last run: <span className="text-slate-700">{fmtDate(p.last)}</span></span>
|
|
<span>Total runs: <span className="tabular-nums text-slate-700 font-semibold">{p.runs}</span></span>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</CardBody>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|