mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-08 22:58:01 -05:00
fix(frontend): Update isGraphRunning state when manually executing graphs (#11489)
This PR fixes an issue where the `isGraphRunning` state wasn't being updated when users manually executed graphs. This caused the UI to not show proper feedback that a graph was running, such as the running background animation. The fix adds a `setIsGraphRunning` method to the graph store and ensures it's called both when starting execution (for immediate UI feedback) and when errors occur (to reset the state). ### Changes 🏗️ - **Added `setIsGraphRunning` method to graphStore**: Provides a way to manually control the graph running state - **Set running state on manual execution**: Updates `isGraphRunning` to `true` immediately when users click the Run button, providing instant UI feedback - **Reset state on execution errors**: Ensures `isGraphRunning` is set back to `false` if the graph execution fails, preventing the UI from showing incorrect running state - **Improved UI responsiveness**: Users now see immediate visual feedback (like the running background) when they start a graph execution - **Cleaned up unused import**: Removed unnecessary `flowID` from useQueryStates in Flow component - I’ve also changed the colour of the running background to a lighter shade of purple. ### 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: - [x] Click Run button and verify the running background appears immediately - [x] Test with graphs that require input values via the input dialog - [x] Verify running state is cleared when execution completes - [x] Test error scenarios and confirm running state is reset on failure - [x] Confirm all UI elements that depend on `isGraphRunning` update correctly - [x] Test multiple consecutive runs to ensure state management is consistent
This commit is contained in:
@@ -19,6 +19,9 @@ export const useRunGraph = () => {
|
||||
const hasCredentials = useGraphStore(
|
||||
useShallow((state) => state.hasCredentials),
|
||||
);
|
||||
const setIsGraphRunning = useGraphStore(
|
||||
useShallow((state) => state.setIsGraphRunning),
|
||||
);
|
||||
const [openRunInputDialog, setOpenRunInputDialog] = useState(false);
|
||||
|
||||
const [{ flowID, flowVersion, flowExecutionID }, setQueryStates] =
|
||||
@@ -38,6 +41,8 @@ export const useRunGraph = () => {
|
||||
});
|
||||
},
|
||||
onError: (error: any) => {
|
||||
// Reset running state on error
|
||||
setIsGraphRunning(false);
|
||||
toast({
|
||||
title: (error.detail as string) ?? "An unexpected error occurred.",
|
||||
description: "An unexpected error occurred.",
|
||||
@@ -67,6 +72,8 @@ export const useRunGraph = () => {
|
||||
if (hasInputs() || hasCredentials()) {
|
||||
setOpenRunInputDialog(true);
|
||||
} else {
|
||||
// Optimistically set running state immediately for responsive UI
|
||||
setIsGraphRunning(true);
|
||||
await executeGraph({
|
||||
graphId: flowID ?? "",
|
||||
graphVersion: flowVersion || null,
|
||||
|
||||
@@ -18,6 +18,7 @@ export const useRunInputDialog = ({
|
||||
const credentialsSchema = useGraphStore(
|
||||
(state) => state.credentialsInputSchema,
|
||||
);
|
||||
const setIsGraphRunning = useGraphStore((state) => state.setIsGraphRunning);
|
||||
|
||||
const [openCronSchedulerDialog, setOpenCronSchedulerDialog] = useState(false);
|
||||
const [inputValues, setInputValues] = useState<Record<string, any>>({});
|
||||
@@ -41,6 +42,8 @@ export const useRunInputDialog = ({
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
// Reset running state on error
|
||||
setIsGraphRunning(false);
|
||||
toast({
|
||||
title: (error.detail as string) ?? "An unexpected error occurred.",
|
||||
description: "An unexpected error occurred.",
|
||||
@@ -78,6 +81,8 @@ export const useRunInputDialog = ({
|
||||
graphVersion: flowVersion || null,
|
||||
data: { inputs: inputValues, credentials_inputs: credentialValues },
|
||||
});
|
||||
// Optimistically set running state immediately for responsive UI
|
||||
setIsGraphRunning(true);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ export const Flow = () => {
|
||||
)}
|
||||
</ReactFlow>
|
||||
</div>
|
||||
{/* TODO: Need to update it in future - also do not send executionId as prop - rather use useQueryState inside the component */}
|
||||
<FloatingReviewsPanel
|
||||
executionId={flowExecutionID || undefined}
|
||||
graphId={flowID || undefined}
|
||||
|
||||
@@ -21,7 +21,7 @@ export const RunningBackground = () => {
|
||||
borderWidth: "15px",
|
||||
borderStyle: "solid",
|
||||
borderColor: "transparent",
|
||||
borderImage: "linear-gradient(to right, #BC82F3, #BC82F3) 1",
|
||||
borderImage: "linear-gradient(to right, #D4A5F9, #D4A5F9) 1",
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
@@ -30,7 +30,7 @@ export const RunningBackground = () => {
|
||||
borderWidth: "10px",
|
||||
borderStyle: "solid",
|
||||
borderColor: "transparent",
|
||||
borderImage: "linear-gradient(to right, #BC82F3, #BC82F3) 1",
|
||||
borderImage: "linear-gradient(to right, #D4A5F9, #D4A5F9) 1",
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
@@ -39,7 +39,7 @@ export const RunningBackground = () => {
|
||||
borderWidth: "6px",
|
||||
borderStyle: "solid",
|
||||
borderColor: "transparent",
|
||||
borderImage: "linear-gradient(to right, #BC82F3, #BC82F3) 1",
|
||||
borderImage: "linear-gradient(to right, #D4A5F9, #D4A5F9) 1",
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
@@ -48,7 +48,7 @@ export const RunningBackground = () => {
|
||||
borderWidth: "6px",
|
||||
borderStyle: "solid",
|
||||
borderColor: "transparent",
|
||||
borderImage: "linear-gradient(to right, #BC82F3, #BC82F3) 1",
|
||||
borderImage: "linear-gradient(to right, #D4A5F9, #D4A5F9) 1",
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useGraphStore } from "../../../stores/graphStore";
|
||||
import { useReactFlow } from "@xyflow/react";
|
||||
import { useControlPanelStore } from "../../../stores/controlPanelStore";
|
||||
import { useHistoryStore } from "../../../stores/historyStore";
|
||||
import { AgentExecutionStatus } from "@/app/api/__generated__/models/agentExecutionStatus";
|
||||
|
||||
export const useFlow = () => {
|
||||
const [isLocked, setIsLocked] = useState(false);
|
||||
@@ -30,6 +31,9 @@ export const useFlow = () => {
|
||||
const setGraphSchemas = useGraphStore(
|
||||
useShallow((state) => state.setGraphSchemas),
|
||||
);
|
||||
const setGraphExecutionStatus = useGraphStore(
|
||||
useShallow((state) => state.setGraphExecutionStatus),
|
||||
);
|
||||
const updateEdgeBeads = useEdgeStore(
|
||||
useShallow((state) => state.updateEdgeBeads),
|
||||
);
|
||||
@@ -154,6 +158,13 @@ export const useFlow = () => {
|
||||
customNodes,
|
||||
]);
|
||||
|
||||
// update graph execution status
|
||||
useEffect(() => {
|
||||
if (executionDetails) {
|
||||
setGraphExecutionStatus(executionDetails.status as AgentExecutionStatus);
|
||||
}
|
||||
}, [executionDetails]);
|
||||
|
||||
useEffect(() => {
|
||||
if (customNodes.length > 0 && graph?.links) {
|
||||
const timer = setTimeout(() => {
|
||||
|
||||
@@ -5,6 +5,7 @@ interface GraphStore {
|
||||
graphExecutionStatus: AgentExecutionStatus | undefined;
|
||||
isGraphRunning: boolean;
|
||||
setGraphExecutionStatus: (status: AgentExecutionStatus | undefined) => void;
|
||||
setIsGraphRunning: (isRunning: boolean) => void;
|
||||
|
||||
inputSchema: Record<string, any> | null;
|
||||
credentialsInputSchema: Record<string, any> | null;
|
||||
@@ -38,6 +39,10 @@ export const useGraphStore = create<GraphStore>((set, get) => ({
|
||||
});
|
||||
},
|
||||
|
||||
setIsGraphRunning: (isRunning: boolean) => {
|
||||
set({ isGraphRunning: isRunning });
|
||||
},
|
||||
|
||||
setGraphSchemas: (inputSchema, credentialsInputSchema, outputSchema) =>
|
||||
set({ inputSchema, credentialsInputSchema, outputSchema }),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user