[AutoGen Studio] Allow multiline strings in chat input (#1105)

* [AutoGen Studio] Allow multiline strings in chat input

* make cogicon spin/animate during loading. minor fix to header issue.

---------

Co-authored-by: Victor Dibia <victordibia@microsoft.com>
This commit is contained in:
Dragos Campean 2024-01-03 02:24:24 +02:00 committed by GitHub
parent 8a26d3b3cd
commit 98d148046b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 49 deletions

View File

@ -95,7 +95,7 @@ const Header = ({ meta, link }: any) => {
return ( return (
<div <div
key={index + "linkrow"} key={index + "linkrow"}
className={`text-primary items-center hover:text-accent hover:bg-secondary px-1 pt-1 block text-sm font-medium `} className={`text-primary items-center hover:text-accent px-1 pt-1 block text-sm font-medium `}
> >
<Link <Link
className="hover:text-accent h-full flex flex-col" className="hover:text-accent h-full flex flex-col"

View File

@ -29,7 +29,7 @@ const ChatBox = ({
editable?: boolean; editable?: boolean;
}) => { }) => {
const session: IChatSession | null = useConfigStore((state) => state.session); const session: IChatSession | null = useConfigStore((state) => state.session);
const queryInputRef = React.useRef<HTMLInputElement>(null); const textAreaInputRef = React.useRef<HTMLTextAreaElement>(null);
const messageBoxInputRef = React.useRef<HTMLDivElement>(null); const messageBoxInputRef = React.useRef<HTMLDivElement>(null);
const { user } = React.useContext(appContext); const { user } = React.useContext(appContext);
@ -37,6 +37,7 @@ const ChatBox = ({
const deleteMsgUrl = `${serverUrl}/messages/delete`; const deleteMsgUrl = `${serverUrl}/messages/delete`;
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const [text, setText] = React.useState("");
const [error, setError] = React.useState<IStatus | null>({ const [error, setError] = React.useState<IStatus | null>({
status: true, status: true,
message: "All good", message: "All good",
@ -51,7 +52,7 @@ const ChatBox = ({
let pageHeight, chatMaxHeight; let pageHeight, chatMaxHeight;
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
pageHeight = window.innerHeight; pageHeight = window.innerHeight;
chatMaxHeight = pageHeight - 300 + "px"; chatMaxHeight = pageHeight - 350 + "px";
} }
const parseMessages = (messages: any) => { const parseMessages = (messages: any) => {
@ -265,28 +266,26 @@ const ChatBox = ({
}, 200); }, 200);
}, [messages]); }, [messages]);
const textAreaDefaultHeight = "50px";
// clear text box if loading has just changed to false and there is no error // clear text box if loading has just changed to false and there is no error
React.useEffect(() => { React.useEffect(() => {
if (loading === false && queryInputRef.current) { if (loading === false && textAreaInputRef.current) {
if (queryInputRef.current) { if (textAreaInputRef.current) {
// console.log("loading changed", loading, error);
if (error === null || (error && error.status === false)) { if (error === null || (error && error.status === false)) {
queryInputRef.current.value = ""; textAreaInputRef.current.value = "";
textAreaInputRef.current.style.height = textAreaDefaultHeight;
} }
} }
} }
}, [loading]); }, [loading]);
// scroll to queryInputRef on load
React.useEffect(() => { React.useEffect(() => {
// console.log("scrolling to query input"); if (textAreaInputRef.current) {
// if (queryInputRef.current) { textAreaInputRef.current.style.height = textAreaDefaultHeight; // Reset height to shrink if text is deleted
// queryInputRef.current.scrollIntoView({ const scrollHeight = textAreaInputRef.current.scrollHeight;
// behavior: "smooth", textAreaInputRef.current.style.height = `${scrollHeight}px`;
// block: "center", }
// }); }, [text]);
// }
}, []);
const chatHistory = (messages: IChatMessage[] | null) => { const chatHistory = (messages: IChatMessage[] | null) => {
let history = ""; let history = "";
@ -378,6 +377,23 @@ const ChatBox = ({
}); });
}; };
const handleTextChange = (
event: React.ChangeEvent<HTMLTextAreaElement>
): void => {
setText(event.target.value);
};
const handleKeyDown = (
event: React.KeyboardEvent<HTMLTextAreaElement>
): void => {
if (event.key === "Enter" && !event.shiftKey) {
if (textAreaInputRef.current && !loading) {
event.preventDefault();
getCompletion(textAreaInputRef.current.value);
}
}
};
return ( return (
<div className="text-primary relative h-full rounded "> <div className="text-primary relative h-full rounded ">
<div <div
@ -414,55 +430,53 @@ const ChatBox = ({
{editable && ( {editable && (
<div className="mt-2 p-2 absolute bg-primary bottom-0 w-full"> <div className="mt-2 p-2 absolute bg-primary bottom-0 w-full">
<div <div
className={`mt-2 rounded p-2 shadow-lg flex mb-1 gap-2 ${ className={`rounded p-2 shadow-lg flex mb-1 gap-2 ${
loading ? " opacity-50 pointer-events-none" : "" loading ? " opacity-50 pointer-events-none" : ""
}`} }`}
> >
{/* <input className="flex-1 p-2 ring-2" /> */} {/* <input className="flex-1 p-2 ring-2" /> */}
<form <form
autoComplete="on" autoComplete="on"
className="flex-1 " className="flex-1 relative"
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
// if (queryInputRef.current && !loading) {
// getCompletion(queryInputRef.current?.value);
// }
}} }}
> >
<input <textarea
id="queryInput" id="queryInput"
name="queryInput" name="queryInput"
autoComplete="on" autoComplete="on"
onKeyDown={(e) => { onKeyDown={handleKeyDown}
if (e.key === "Enter" && queryInputRef.current && !loading) { onChange={handleTextChange}
getCompletion(queryInputRef.current?.value); placeholder="Write message here..."
ref={textAreaInputRef}
className="flex items-center w-full resize-none text-gray-600 bg-white p-2 ring-2 rounded-sm pl-5 pr-16"
style={{ maxHeight: "120px", overflowY: "auto" }}
/>
<div
role={"button"}
style={{ width: "45px", height: "35px" }}
title="Send message"
onClick={() => {
if (textAreaInputRef.current && !loading) {
getCompletion(textAreaInputRef.current.value);
} }
}} }}
ref={queryInputRef} className="absolute right-3 bottom-2 bg-accent hover:brightness-75 transition duration-300 rounded cursor-pointer flex justify-center items-center"
className="w-full text-gray-600 bg-white p-2 ring-2 rounded-sm" >
/> {" "}
{!loading && (
<div className="inline-block ">
<PaperAirplaneIcon className="h-6 w-6 text-white " />{" "}
</div>
)}
{loading && (
<div className="inline-block ">
<Cog6ToothIcon className="text-white animate-spin rounded-full h-6 w-6" />
</div>
)}
</div>
</form> </form>
<div
role={"button"}
onClick={() => {
if (queryInputRef.current && !loading) {
getCompletion(queryInputRef.current?.value);
}
}}
className="bg-accent hover:brightness-75 transition duration-300 rounded pt-2 px-5 "
>
{" "}
{!loading && (
<div className="inline-block ">
<PaperAirplaneIcon className="h-6 text-white inline-block" />{" "}
</div>
)}
{loading && (
<div className="inline-block ">
<Cog6ToothIcon className="relative -pb-2 text-white animate-spin inline-flex rounded-full h-6 w-6" />
</div>
)}
</div>
</div>{" "} </div>{" "}
<div> <div>
<div className="mt-2 text-xs text-secondary"> <div className="mt-2 text-xs text-secondary">