mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-10 15:47:59 -05:00
feat(frontend/library): Add "Open in builder" run action (#9755)
- Resolves #9730 ### Changes 🏗️ - feat: Add "Open in builder" run action - refactor: Add `ActionButtonGroup` to replace boilerplate code in `AgentRunDetailsView`, `AgentRunDraftView`, `AgentScheduleDetailsView` - feat: Add link support to `ActionButtonGroup`, `ButtonAction` ### Checklist 📋 #### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - Go to `/library/agents/[id]` - [x] "Run again" button works - [x] "Open in builder" button-link works
This commit is contained in:
committed by
GitHub
parent
ce98925d58
commit
8ceb03ce1a
@@ -226,12 +226,8 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
...(agent?.can_access_graph
|
||||
? [
|
||||
{
|
||||
label: "Open in builder",
|
||||
callback: () =>
|
||||
agent &&
|
||||
router.push(
|
||||
`/build?flowID=${agent.agent_id}&flowVersion=${agent.agent_version}`,
|
||||
),
|
||||
label: "Open graph in builder",
|
||||
href: `/build?flowID=${agent.agent_id}&flowVersion=${agent.agent_version}`,
|
||||
},
|
||||
{ label: "Export agent to file", callback: downloadGraph },
|
||||
]
|
||||
@@ -242,7 +238,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
callback: () => setAgentDeleteDialogOpen(true),
|
||||
},
|
||||
],
|
||||
[agent, router, downloadGraph],
|
||||
[agent, downloadGraph],
|
||||
);
|
||||
|
||||
if (!agent || !graph) {
|
||||
@@ -282,6 +278,7 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
{(selectedView.type == "run" && selectedView.id ? (
|
||||
selectedRun && (
|
||||
<AgentRunDetailsView
|
||||
agent={agent}
|
||||
graph={graphVersions[selectedRun.graph_version] ?? graph}
|
||||
run={selectedRun}
|
||||
agentActions={agentActions}
|
||||
|
||||
@@ -8,13 +8,14 @@ import {
|
||||
GraphExecution,
|
||||
GraphExecutionID,
|
||||
GraphExecutionMeta,
|
||||
LibraryAgent,
|
||||
} from "@/lib/autogpt-server-api";
|
||||
|
||||
import type { ButtonAction } from "@/components/agptui/types";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { IconRefresh, IconSquare } from "@/components/ui/icons";
|
||||
import { useToastOnFail } from "@/components/ui/use-toast";
|
||||
import { Button } from "@/components/agptui/Button";
|
||||
import ActionButtonGroup from "@/components/agptui/action-button-group";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
import {
|
||||
@@ -23,12 +24,14 @@ import {
|
||||
} from "@/components/agents/agent-run-status-chip";
|
||||
|
||||
export default function AgentRunDetailsView({
|
||||
agent,
|
||||
graph,
|
||||
run,
|
||||
agentActions,
|
||||
onRun,
|
||||
deleteRun,
|
||||
}: {
|
||||
agent: LibraryAgent;
|
||||
graph: Graph;
|
||||
run: GraphExecution | GraphExecutionMeta;
|
||||
agentActions: ButtonAction[];
|
||||
@@ -174,9 +177,27 @@ export default function AgentRunDetailsView({
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(agent.can_access_graph
|
||||
? [
|
||||
{
|
||||
label: "Open run in builder",
|
||||
href: `/build?flowID=${run.graph_id}&flowVersion=${run.graph_version}&flowExecutionID=${run.id}`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{ label: "Delete run", variant: "secondary", callback: deleteRun },
|
||||
],
|
||||
[runStatus, runAgain, stopRun, deleteRun],
|
||||
[
|
||||
runStatus,
|
||||
runAgain,
|
||||
stopRun,
|
||||
deleteRun,
|
||||
graph.has_webhook_trigger,
|
||||
agent.can_access_graph,
|
||||
run.graph_id,
|
||||
run.graph_version,
|
||||
run.id,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -254,31 +275,9 @@ export default function AgentRunDetailsView({
|
||||
{/* Run / Agent Actions */}
|
||||
<aside className="w-48 xl:w-56">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-sm font-medium">Run actions</h3>
|
||||
{runActions.map((action, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
variant={action.variant ?? "outline"}
|
||||
onClick={action.callback}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ActionButtonGroup title="Run actions" actions={runActions} />
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-sm font-medium">Agent actions</h3>
|
||||
{agentActions.map((action, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
variant={action.variant ?? "outline"}
|
||||
onClick={action.callback}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ActionButtonGroup title="Agent actions" actions={agentActions} />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -8,9 +8,9 @@ import type { ButtonAction } from "@/components/agptui/types";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { TypeBasedInput } from "@/components/type-based-input";
|
||||
import { useToastOnFail } from "@/components/ui/use-toast";
|
||||
import ActionButtonGroup from "@/components/agptui/action-button-group";
|
||||
import SchemaTooltip from "@/components/SchemaTooltip";
|
||||
import { IconPlay } from "@/components/ui/icons";
|
||||
import { Button } from "@/components/agptui/Button";
|
||||
|
||||
export default function AgentRunDraftView({
|
||||
graph,
|
||||
@@ -87,31 +87,9 @@ export default function AgentRunDraftView({
|
||||
{/* Actions */}
|
||||
<aside className="w-48 xl:w-56">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-sm font-medium">Run actions</h3>
|
||||
{runActions.map((action, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
variant={action.variant ?? "outline"}
|
||||
onClick={action.callback}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ActionButtonGroup title="Run actions" actions={runActions} />
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-sm font-medium">Agent actions</h3>
|
||||
{agentActions.map((action, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
variant={action.variant ?? "outline"}
|
||||
onClick={action.callback}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ActionButtonGroup title="Agent actions" actions={agentActions} />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ import type { ButtonAction } from "@/components/agptui/types";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { AgentRunStatus } from "@/components/agents/agent-run-status-chip";
|
||||
import { useToastOnFail } from "@/components/ui/use-toast";
|
||||
import { Button } from "@/components/agptui/Button";
|
||||
import ActionButtonGroup from "@/components/agptui/action-button-group";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
export default function AgentScheduleDetailsView({
|
||||
@@ -75,7 +75,7 @@ export default function AgentScheduleDetailsView({
|
||||
[api, graph, schedule, onForcedRun, toastOnFail],
|
||||
);
|
||||
|
||||
const runActions: { label: string; callback: () => void }[] = useMemo(
|
||||
const runActions: ButtonAction[] = useMemo(
|
||||
() => [{ label: "Run now", callback: () => runNow() }],
|
||||
[runNow],
|
||||
);
|
||||
@@ -126,27 +126,9 @@ export default function AgentScheduleDetailsView({
|
||||
{/* Run / Agent Actions */}
|
||||
<aside className="w-48 xl:w-56">
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-sm font-medium">Run actions</h3>
|
||||
{runActions.map((action, i) => (
|
||||
<Button key={i} variant="outline" onClick={action.callback}>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ActionButtonGroup title="Run actions" actions={runActions} />
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-sm font-medium">Agent actions</h3>
|
||||
{agentActions.map((action, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
variant={action.variant ?? "outline"}
|
||||
onClick={action.callback}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<ActionButtonGroup title="Agent actions" actions={agentActions} />
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import type { ButtonAction } from "@/components/agptui/types";
|
||||
import { Button, buttonVariants } from "@/components/agptui/Button";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function ActionButtonGroup({
|
||||
title,
|
||||
actions,
|
||||
className,
|
||||
}: {
|
||||
title: React.ReactNode;
|
||||
actions: ButtonAction[];
|
||||
className?: string;
|
||||
}): React.ReactElement {
|
||||
return (
|
||||
<div className={cn("flex flex-col gap-3", className)}>
|
||||
<h3 className="text-sm font-medium">{title}</h3>
|
||||
{actions.map((action, i) =>
|
||||
"callback" in action ? (
|
||||
<Button
|
||||
key={i}
|
||||
variant={action.variant ?? "outline"}
|
||||
onClick={action.callback}
|
||||
>
|
||||
{action.label}
|
||||
</Button>
|
||||
) : (
|
||||
<Link
|
||||
key={i}
|
||||
className={buttonVariants({ variant: action.variant })}
|
||||
href={action.href}
|
||||
>
|
||||
{action.label}
|
||||
</Link>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,5 +4,4 @@ import React from "react";
|
||||
export type ButtonAction = {
|
||||
label: React.ReactNode;
|
||||
variant?: ButtonProps["variant"];
|
||||
callback: () => void;
|
||||
};
|
||||
} & ({ callback: () => void } | { href: string });
|
||||
|
||||
Reference in New Issue
Block a user