Skip to content

Commit 13195ac

Browse files
author
Eunsoo Lee
committed
Merge branch 'ui-ux-refresh_eunsoo' of https://github.com/microsoft/Multi-Agent-Custom-Automation-Engine-Solution-Accelerator into ui-ux-refresh_eunsoo
2 parents d506511 + 01943ac commit 13195ac

File tree

8 files changed

+138
-107
lines changed

8 files changed

+138
-107
lines changed

src/frontend_react/src/api/config.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export function getApiUrl() {
7575
}
7676

7777
export function getUserId(): string {
78-
USER_ID = window.userInfo ? window.userInfo[0].user_id : null;
78+
// USER_ID = window.userInfo && window.userInfo[0] && window.userInfo[0].user_id ? window.userInfo[0].user_id : null;
7979
const userId = USER_ID ?? "00000000-0000-0000-0000-000000000000";
8080
return userId;
8181
}

src/frontend_react/src/components/content/HomeInput.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const HomeInput: React.FC<HomeInputProps> = ({
4646
const handleSubmit = async () => {
4747
if (input.trim()) {
4848
setSubmitting(true);
49-
showToast("Creating a task...", "progress", { dismissible: false });
49+
showToast("Creating a plan..", "progress", { dismissible: false });
5050
try {
5151
const response = await TaskService.submitInputTask(input.trim());
5252

@@ -55,7 +55,7 @@ const HomeInput: React.FC<HomeInputProps> = ({
5555
textareaRef.current.style.height = "auto";
5656
}
5757

58-
showToast("Task created!", "success");
58+
showToast("Plan created!", "success");
5959
navigate(`/plan/${response.plan_id}`);
6060
console.log('Task response', response);
6161
if (response.plan_id != null) {
@@ -64,10 +64,10 @@ const HomeInput: React.FC<HomeInputProps> = ({
6464
} else {
6565
// plan_id is not valid, handle accordingly
6666
console.log('Invalid plan:', response.status);
67-
showToast("Failed to create task", "error");
67+
showToast("Failed to create plan", "error");
6868
}
6969
} catch (error) {
70-
console.error("Failed to create task:", error);
70+
console.error("Failed to create plan:", error);
7171
showToast("Something went wrong", "error");
7272
} finally {
7373
setSubmitting(false);

src/frontend_react/src/components/content/PlanChat.tsx

Lines changed: 99 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -5,119 +5,126 @@ import remarkGfm from "remark-gfm";
55
import rehypePrism from "rehype-prism";
66
import { PlanChatProps } from "@/models";
77
import {
8-
Body1,
9-
Button,
10-
Tag,
11-
ToolbarDivider
8+
Body1,
9+
Button,
10+
Spinner,
11+
Tag,
12+
ToolbarDivider
1213
} from "@fluentui/react-components";
1314
import {
14-
HeartRegular,
15+
HeartRegular,
1516
} from "@fluentui/react-icons";
1617
import { useRef, useState } from "react";
1718
import ReactMarkdown from "react-markdown";
1819
import "../../styles/PlanChat.css";
1920
import "../../styles/Chat.css";
2021
import "../../styles/prism-material-oceanic.css";
22+
import { TaskService } from "@/services/TaskService";
2123

2224
const PlanChat: React.FC<PlanChatProps> = ({
23-
planData,
24-
OnChatSubmit
25+
planData,
26+
input,
27+
loading,
28+
OnChatSubmit
29+
2530
}) => {
26-
const messages = planData?.messages || [];
27-
const [input, setInput] = useState("");
28-
const [isTyping, setIsTyping] = useState(false);
29-
const [showScrollButton, setShowScrollButton] = useState(false);
30-
const [inputHeight, setInputHeight] = useState(0);
31-
const [currentConversationId, setCurrentConversationId] = useState<string | undefined>(undefined);
31+
const messages = planData?.messages || [];
32+
const [inputValue, setInput] = useState(input);
33+
const [isTyping, setIsTyping] = useState(false);
34+
const [showScrollButton, setShowScrollButton] = useState(false);
35+
const [inputHeight, setInputHeight] = useState(0);
36+
const [currentConversationId, setCurrentConversationId] = useState<string | undefined>(undefined);
3237

33-
const messagesContainerRef = useRef<HTMLDivElement>(null);
34-
const inputContainerRef = useRef<HTMLDivElement>(null);
38+
const messagesContainerRef = useRef<HTMLDivElement>(null);
39+
const inputContainerRef = useRef<HTMLDivElement>(null);
3540

36-
const sendMessage = async () => {};
41+
const sendMessage = async () => { };
3742

38-
const scrollToBottom = () => {};
43+
const scrollToBottom = () => { };
44+
if (!planData) return <Spinner size="large" />;
45+
return (
46+
<div className="chat-container">
47+
<div className="messages" ref={messagesContainerRef}>
48+
<div className="message-wrapper">
49+
{messages.map((msg, index) => {
50+
const isHuman = msg.source.includes("human");
3951

40-
return (
41-
<div className="chat-container">
42-
<div className="messages" ref={messagesContainerRef}>
43-
<div className="message-wrapper">
44-
{messages.map((msg, index) => {
45-
const isHuman = msg.role === "user" || msg.role === "human";
52+
return (
53+
<div key={index} className={`message ${isHuman ? "user" : "assistant"}`}>
54+
{!isHuman && (
55+
<div className="plan-chat-header">
56+
<div className="plan-chat-speaker">
57+
<span className="speaker-name">{TaskService.cleanTextToSpaces(msg.source)}</span>
58+
<Tag size="extra-small" shape="rounded" appearance="filled" className="bot-tag">BOT</Tag>
59+
</div>
60+
</div>
61+
)}
4662

47-
return (
48-
<div key={index} className={`message ${msg.role}`}>
49-
{!isHuman && (
50-
<div className="plan-chat-header">
51-
<div className="plan-chat-speaker">
52-
<span className="speaker-name">HR Agent</span>
53-
<Tag size="extra-small" shape="rounded" appearance="filled" className="bot-tag">BOT</Tag>
54-
</div>
55-
</div>
56-
)}
63+
<Body1>
64+
<div className="plan-chat-message-content">
65+
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypePrism]}>
66+
{msg.content || ""}
67+
</ReactMarkdown>
5768

58-
<Body1>
59-
<div className="plan-chat-message-content">
60-
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypePrism]}>
61-
{msg.content || ""}
62-
</ReactMarkdown>
69+
{!isHuman && (
70+
<div className="assistant-footer">
71+
<div className="assistant-actions">
72+
<Button
73+
onClick={() => msg.content && navigator.clipboard.writeText(msg.content)}
74+
title="Copy Response"
75+
appearance="subtle"
76+
style={{ height: 28, width: 28 }}
77+
icon={<Copy />}
78+
/>
79+
<Tag size="extra-small">Sample data for demonstration purposes only.</Tag>
80+
</div>
81+
</div>
82+
)}
83+
</div>
84+
</Body1>
85+
</div>
86+
);
87+
})}
88+
</div>
6389

64-
{!isHuman && (
65-
<div className="assistant-footer">
66-
<div className="assistant-actions">
67-
<Button
68-
onClick={() => msg.content && navigator.clipboard.writeText(msg.content)}
69-
title="Copy Response"
70-
appearance="subtle"
71-
style={{ height: 28, width: 28 }}
72-
icon={<Copy />}
73-
/>
74-
<Tag size="extra-small">Sample data for demonstration purposes only.</Tag>
75-
</div>
76-
</div>
77-
)}
78-
</div>
79-
</Body1>
80-
</div>
81-
);
82-
})}
83-
</div>
84-
85-
{isTyping && (
86-
<div className="typing-indicator">
87-
<span>Thinking...</span>
88-
</div>
89-
)}
90-
</div>
90+
{isTyping && (
91+
<div className="typing-indicator">
92+
<span>Thinking...</span>
93+
</div>
94+
)}
95+
</div>
9196

92-
{showScrollButton && (
93-
<Tag
94-
onClick={scrollToBottom}
95-
className="scroll-to-bottom plan-chat-scroll-button"
96-
shape="circular"
97-
style={{ bottom: inputHeight }}
98-
>
99-
Back to bottom
100-
</Tag>
101-
)}
97+
{showScrollButton && (
98+
<Tag
99+
onClick={scrollToBottom}
100+
className="scroll-to-bottom plan-chat-scroll-button"
101+
shape="circular"
102+
style={{ bottom: inputHeight }}
103+
>
104+
Back to bottom
105+
</Tag>
106+
)}
102107

103-
<div ref={inputContainerRef} className="plan-chat-input-container">
104-
<div className="plan-chat-input-wrapper">
105-
<ChatInput
106-
value={input}
107-
onChange={setInput}
108-
onEnter={sendMessage}
109-
>
110-
<Button
111-
appearance="transparent"
112-
onClick={sendMessage}
113-
icon={<Send />}
114-
disabled={!planData?.hasHumanClarificationRequest || isTyping || !input.trim()}
115-
/>
116-
</ChatInput>
108+
<div ref={inputContainerRef} className="plan-chat-input-container">
109+
<div className="plan-chat-input-wrapper">
110+
<ChatInput
111+
value={inputValue}
112+
onChange={setInput}
113+
onEnter={() => OnChatSubmit(inputValue)}
114+
disabledChat={!planData.enableChat}
115+
placeholder="Add more info to this task..."
116+
>
117+
<Button
118+
appearance="transparent"
119+
onClick={sendMessage}
120+
icon={<Send />}
121+
disabled={!planData?.enableChat || isTyping || !input.trim()}
122+
/>
123+
</ChatInput>
124+
</div>
125+
</div>
117126
</div>
118-
</div>
119-
</div>
120-
);
127+
);
121128
};
122129

123130
export default PlanChat;

src/frontend_react/src/components/content/PlanPanelLeft.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ const PlanPanelLeft: React.FC<PlanPanelLefProps> = ({ onNewTaskButton }) => {
100100
return (
101101
<div style={{ flexShrink: 0, display: "flex", overflow: "hidden" }}>
102102
<PanelLeft panelWidth={280} panelResize={true}>
103-
<PanelLeftToolbar panelTitle="Contoso" panelIcon={<ContosoLogo style={{ width: 20, height: 20 }} />}>
103+
<PanelLeftToolbar panelTitle="Contoso" panelIcon={<ContosoLogo />}>
104104
<Tooltip content="New task" relationship={"label"} />
105105
</PanelLeftToolbar>
106106

src/frontend_react/src/components/content/TaskDetails.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
9696
const { description, functionOrDetails } = TaskService.splitSubtaskAction(
9797
subtask.action
9898
);
99-
const canInteract = planData.plan.human_clarification_response !== null
99+
const canInteract = planData.enableStepButtons;
100100

101101
return (<div key={subtask.id} className="task-details-subtask-item">
102102
<div className="task-details-status-icon">

src/frontend_react/src/models/plan.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,16 @@ export interface ProcessedPlanData {
109109
plan: PlanWithSteps;
110110
agents: AgentType[];
111111
steps: Step[];
112-
hasHumanClarificationRequest: boolean;
112+
hasClarificationRequest: boolean;
113+
hasClarificationResponse: boolean;
114+
enableChat: boolean;
115+
enableStepButtons: boolean;
113116
messages: PlanMessage[];
114117
}
115118

116119
export interface PlanChatProps {
117120
planData: ProcessedPlanData;
121+
input: string;
118122
loading: boolean;
119123
OnChatSubmit: (message: string) => void;
120124
}

src/frontend_react/src/pages/PlanPage.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const PlanPage: React.FC = () => {
3838
const { planId } = useParams<{ planId: string }>();
3939
const navigate = useNavigate();
4040
const { showToast } = useInlineToaster();
41-
41+
const [input, setInput] = useState("");
4242
// State for plan data
4343
const [planData, setPlanData] = useState<ProcessedPlanData | any>(null);
4444
const [loading, setLoading] = useState<boolean>(true);
@@ -51,9 +51,9 @@ const PlanPage: React.FC = () => {
5151
if (!planId) return;
5252

5353
try {
54+
setPlanData(null);
5455
setLoading(true);
5556
setError(null);
56-
5757
const data = await PlanDataService.fetchPlanData(planId);
5858
console.log('Fetched plan data:', data);
5959
setPlanData(data);
@@ -66,6 +66,7 @@ const PlanPage: React.FC = () => {
6666
}, [planId]);
6767

6868
const loadPlanData2 = useCallback(async () => {
69+
console.log('loadPlanData2 called with planId:', planId);
6970
if (!planId) return;
7071

7172
try {
@@ -94,9 +95,13 @@ const PlanPage: React.FC = () => {
9495
planData.plan.session_id, // session_id
9596
chatInput // human_clarification
9697
);
98+
showToast("Clarification submitted successfully", "success");
9799
await loadPlanData2();
98100
} catch (error) {
101+
showToast("Failed to submit clarification", "error");
99102
console.error('Failed to submit clarification:', error);
103+
} finally {
104+
setInput(""); // Clear input after submission
100105
}
101106
},
102107
[planData, loadPlanData2]
@@ -108,8 +113,11 @@ const PlanPage: React.FC = () => {
108113
showToast("Submitting approval...", "progress", { dismissible: false });
109114
try {
110115
await PlanDataService.approveStep(step);
116+
showToast("Step approved successfully", "success");
111117
await loadPlanData2();
112118
} catch (error) {
119+
showToast("Failed to approve step", "error");
120+
// Log the error for debugging
113121
console.error('Failed to reject step:', error);
114122
} finally {
115123
setProcessingSubtaskId(null);
@@ -121,8 +129,10 @@ const PlanPage: React.FC = () => {
121129
showToast("Submitting rejection...", "progress", { dismissible: false });
122130
try {
123131
await PlanDataService.rejectStep(step);
132+
showToast("Step rejected successfully", "success");
124133
await loadPlanData2();
125134
} catch (error) {
135+
showToast("Failed to reject step", "error");
126136
console.error('Failed to reject step:', error);
127137
} finally {
128138
setProcessingSubtaskId(null);
@@ -161,6 +171,7 @@ const PlanPage: React.FC = () => {
161171
planData={planData}
162172
OnChatSubmit={handleOnchatSubmit}
163173
loading={loading}
174+
input={input}
164175
/>
165176

166177

0 commit comments

Comments
 (0)