diff --git a/src/frontend/src/components/common/PlanCancellationDialog.tsx b/src/frontend/src/components/common/PlanCancellationDialog.tsx index 5b7c8084a..eaa6ec7b2 100644 --- a/src/frontend/src/components/common/PlanCancellationDialog.tsx +++ b/src/frontend/src/components/common/PlanCancellationDialog.tsx @@ -8,6 +8,8 @@ import { DialogBody, DialogActions, Button, + DialogOpenChangeEvent, + DialogOpenChangeData } from '@fluentui/react-components'; import { Warning20Regular } from '@fluentui/react-icons'; import "../../styles/Panel.css"; @@ -29,7 +31,7 @@ const PlanCancellationDialog: React.FC = ({ loading = false }) => { return ( - !data.open && onCancel()}> + !data.open && onCancel()}> diff --git a/src/frontend/src/components/common/TeamSelector.tsx b/src/frontend/src/components/common/TeamSelector.tsx index 885252b8f..ebbd04a25 100644 --- a/src/frontend/src/components/common/TeamSelector.tsx +++ b/src/frontend/src/components/common/TeamSelector.tsx @@ -19,7 +19,13 @@ import { RadioGroup, Tab, TabList, - Tooltip + Tooltip, + DialogOpenChangeEvent, + DialogOpenChangeData, + TabValue, + SelectTabEvent, + SelectTabData, + InputOnChangeData } from '@fluentui/react-components'; import { ChevronUpDown16Regular, @@ -474,7 +480,7 @@ const TeamSelector: React.FC = ({ size="small" disabled={true} className={`${styles.moreButton} ${styles.moreButtonDisabled || ''}`} - onClick={(e) => e.stopPropagation()} + onClick={(e: React.MouseEvent) => e.stopPropagation()} /> ) : ( @@ -482,7 +488,7 @@ const TeamSelector: React.FC = ({ icon={} appearance="subtle" size="small" - onClick={(e) => handleDeleteTeam(team, e)} + onClick={(e: React.MouseEvent) => handleDeleteTeam(team, e)} className={styles.moreButton} /> )} @@ -492,7 +498,7 @@ const TeamSelector: React.FC = ({ return ( <> - handleOpenChange(data.open)}> + handleOpenChange(data.open)}> - setDeleteConfirmOpen(data.open)}> + setDeleteConfirmOpen(data.open)}> diff --git a/src/frontend/src/components/content/PlanPanelLeft.tsx b/src/frontend/src/components/content/PlanPanelLeft.tsx index e7c1424cd..3ed3e483f 100644 --- a/src/frontend/src/components/content/PlanPanelLeft.tsx +++ b/src/frontend/src/components/content/PlanPanelLeft.tsx @@ -60,17 +60,27 @@ const PlanPanelLeft: React.FC = ({ console.log("Loading plans, forceRefresh:", forceRefresh); setPlansLoading(true); setPlansError(null); - const plansData = await apiService.getPlans(undefined, forceRefresh); + const plansData = await apiService.getPlans(undefined, !forceRefresh); // Invert forceRefresh for useCache setPlans(plansData); + + // Reset the reload flag after successful load + if (forceRefresh && restReload) { + restReload(); + } } catch (error) { console.log("Failed to load plans:", error); setPlansError( error instanceof Error ? error : new Error("Failed to load plans") ); + + // Reset the reload flag even on error to prevent infinite loops + if (forceRefresh && restReload) { + restReload(); + } } finally { setPlansLoading(false); } - }, []); + }, [restReload]); // Fetch plans @@ -85,7 +95,7 @@ const PlanPanelLeft: React.FC = ({ useEffect(() => { console.log("Reload tasks changed:", reloadTasks); if (reloadTasks) { - loadPlansData(); + loadPlansData(true); // Force refresh when reloadTasks is true } }, [loadPlansData, setUserInfo, reloadTasks]); useEffect(() => { diff --git a/src/frontend/src/coral/components/PromptCard.tsx b/src/frontend/src/coral/components/PromptCard.tsx index c53ab5002..5b6842571 100644 --- a/src/frontend/src/coral/components/PromptCard.tsx +++ b/src/frontend/src/coral/components/PromptCard.tsx @@ -37,14 +37,14 @@ const PromptCard: React.FC = ({ transition: "background-color 0.2s ease-in-out", }} // 🧠 Only apply hover if not disabled - onMouseOver={(e) => { + onMouseOver={(e: React.MouseEvent) => { if (!disabled) { e.currentTarget.style.backgroundColor = "var(--colorNeutralBackground3Hover)"; e.currentTarget.style.border = "1px solid var(--colorNeutralStroke1)"; // subtle shadow on hover } }} - onMouseOut={(e) => { + onMouseOut={(e: React.MouseEvent) => { if (!disabled) { e.currentTarget.style.backgroundColor = "var(--colorNeutralBackground3)"; diff --git a/src/frontend/src/pages/PlanPage.tsx b/src/frontend/src/pages/PlanPage.tsx index 6f6988cef..58c37fe6f 100644 --- a/src/frontend/src/pages/PlanPage.tsx +++ b/src/frontend/src/pages/PlanPage.tsx @@ -132,19 +132,36 @@ const PlanPage: React.FC = () => { // Persist / forward to backend (fire-and-forget with logging) const agentMessageResponse = PlanDataService.createAgentMessageResponse(agentMessageData, planData, is_final, streaming_message); console.log('📤 Persisting agent message:', agentMessageResponse); - void apiService.sendAgentMessage(agentMessageResponse) + const sendPromise = apiService.sendAgentMessage(agentMessageResponse) .then(saved => { console.log('[agent_message][persisted]', { agent: agentMessageData.agent, type: agentMessageData.agent_type, ts: agentMessageData.timestamp }); + + // If this is a final message, refresh the task list after successful persistence + if (is_final) { + // Single refresh with a delay to ensure backend processing is complete + setTimeout(() => { + setReloadLeftList(true); + }, 1000); + } }) .catch(err => { console.warn('[agent_message][persist-failed]', err); + // Even if persistence fails, still refresh the task list for final messages + // The local plan data has been updated, so the UI should reflect that + if (is_final) { + setTimeout(() => { + setReloadLeftList(true); + }, 1000); + } }); - }, []); + return sendPromise; + + }, [setReloadLeftList]); const resetPlanVariables = useCallback(() => { setInput(""); @@ -335,20 +352,17 @@ const PlanPage: React.FC = () => { setPlanData({ ...planData }); } + // Wait for the agent message to be processed and persisted + // The processAgentMessage function will handle refreshing the task list processAgentMessage(agentMessageData, planData, is_final, streamingMessageBuffer); - setTimeout(() => { - console.log('✅ Plan completed, refreshing left list'); - setReloadLeftList(true); - }, 1000); - } }); return () => unsubscribe(); - }, [scrollToBottom, planData, processAgentMessage, streamingMessageBuffer, setSelectedTeam, setReloadLeftList]); + }, [scrollToBottom, planData, processAgentMessage, streamingMessageBuffer, setSelectedTeam]); //WebsocketMessageType.AGENT_MESSAGE useEffect(() => {