mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-10-07 16:19:09 +00:00
138 lines
4.4 KiB
TypeScript
138 lines
4.4 KiB
TypeScript
import { Check, FileCode2, ShieldAlert, X } from "lucide-react"
|
|
|
|
import type { WorkflowApproval } from "@/lib/agents/api"
|
|
|
|
import { Button } from "@/components/ui/button"
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardFooter,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/components/ui/card"
|
|
|
|
type ApprovalStatus = "pending" | "approved" | "rejected" | string
|
|
|
|
interface WorkflowApprovalCardProps {
|
|
approval: WorkflowApproval
|
|
isOwner: boolean
|
|
isPending: boolean
|
|
onApprove: (fingerprint: string) => void
|
|
onReject: (fingerprint: string) => void
|
|
}
|
|
|
|
function statusBadgeClass(status: ApprovalStatus) {
|
|
switch (status) {
|
|
case "approved":
|
|
return "bg-green-500/10 text-green-600 dark:text-green-400"
|
|
case "rejected":
|
|
return "bg-red-500/10 text-red-600 dark:text-red-400"
|
|
default:
|
|
return "bg-amber-500/10 text-amber-600 dark:text-amber-400"
|
|
}
|
|
}
|
|
|
|
function statusLabel(status: ApprovalStatus) {
|
|
switch (status) {
|
|
case "approved":
|
|
return "Approved"
|
|
case "rejected":
|
|
return "Rejected"
|
|
default:
|
|
return "Pending approval"
|
|
}
|
|
}
|
|
|
|
export function WorkflowApprovalCard({
|
|
approval,
|
|
isOwner,
|
|
isPending,
|
|
onApprove,
|
|
onReject,
|
|
}: WorkflowApprovalCardProps) {
|
|
const actionable = isOwner && approval.status === "pending" && !isPending
|
|
const decided = approval.status !== "pending"
|
|
|
|
return (
|
|
<Card className="mx-auto mb-4 w-full max-w-3xl border-amber-500/20 bg-amber-500/5 dark:bg-amber-500/10">
|
|
<CardHeader className="pb-2">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div className="flex items-center gap-2">
|
|
<ShieldAlert className="size-4 text-amber-600 dark:text-amber-400" />
|
|
<CardTitle className="text-sm font-medium">
|
|
Workflow push approval required
|
|
</CardTitle>
|
|
</div>
|
|
<span
|
|
className={`rounded px-1.5 py-0.5 text-[10px] font-medium tracking-wide uppercase ${statusBadgeClass(
|
|
approval.status
|
|
)}`}
|
|
>
|
|
{statusLabel(approval.status)}
|
|
</span>
|
|
</div>
|
|
<CardDescription className="text-xs">
|
|
Open SWE is trying to push GitHub workflow file changes in{" "}
|
|
<strong>{approval.repo}</strong> on <strong>{approval.branch}</strong>
|
|
. Approve only if this exact workflow diff is expected.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="pb-3">
|
|
<div className="space-y-2">
|
|
<div className="flex items-center gap-2 text-[11px] font-medium text-[var(--ui-text-muted)]">
|
|
<FileCode2 className="size-3.5" />
|
|
Changed workflow files
|
|
</div>
|
|
<ul className="space-y-1">
|
|
{approval.files.map((file) => (
|
|
<li
|
|
key={file}
|
|
className="font-mono text-[11px] break-all text-[var(--ui-text)]"
|
|
>
|
|
{file}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="pt-1 text-[11px] text-[var(--ui-text-muted)]">
|
|
Fingerprint:{" "}
|
|
<code className="rounded bg-[var(--ui-panel)] px-1 py-0.5 text-[var(--ui-text)]">
|
|
{approval.fingerprint}
|
|
</code>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
{actionable ? (
|
|
<CardFooter className="gap-2 border-t border-[var(--ui-border)] pt-3">
|
|
<Button
|
|
size="sm"
|
|
onClick={() => onApprove(approval.fingerprint)}
|
|
disabled={isPending}
|
|
>
|
|
<Check className="mr-1 size-3.5" />
|
|
Approve
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="destructive"
|
|
onClick={() => onReject(approval.fingerprint)}
|
|
disabled={isPending}
|
|
>
|
|
<X className="mr-1 size-3.5" />
|
|
Reject
|
|
</Button>
|
|
</CardFooter>
|
|
) : decided ? (
|
|
<CardFooter className="border-t border-[var(--ui-border)] pt-3 text-[11px] text-[var(--ui-text-muted)]">
|
|
This workflow push has been {approval.status}. If the workflow files
|
|
change, a new fingerprint will be required.
|
|
</CardFooter>
|
|
) : null}
|
|
{!isOwner && approval.status === "pending" && (
|
|
<CardFooter className="border-t border-[var(--ui-border)] pt-3 text-[11px] text-[var(--ui-text-muted)]">
|
|
Only the thread owner can approve or reject this workflow push.
|
|
</CardFooter>
|
|
)}
|
|
</Card>
|
|
)
|
|
}
|