From ef69e3b54dc4ad80d05b3684a8efbc717be1e739 Mon Sep 17 00:00:00 2001 From: Nikki Yong <75350534+yongkfn@users.noreply.github.com> Date: Fri, 1 Mar 2024 21:14:03 +0800 Subject: [PATCH 1/2] added loading spinner Added a spinner component whenever waiting for a query response, so that users know something is still happening --- .../app/components/ui/chat/chat-actions.tsx | 2 +- .../app/components/ui/chat/chat-messages.tsx | 78 ++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/frontend/app/components/ui/chat/chat-actions.tsx b/frontend/app/components/ui/chat/chat-actions.tsx index 6f983c6..b2771bb 100644 --- a/frontend/app/components/ui/chat/chat-actions.tsx +++ b/frontend/app/components/ui/chat/chat-actions.tsx @@ -7,7 +7,7 @@ export default function ChatActions( props: Pick & { showReload?: boolean; showStop?: boolean; - }, + } ) { return (
diff --git a/frontend/app/components/ui/chat/chat-messages.tsx b/frontend/app/components/ui/chat/chat-messages.tsx index a330dae..200c599 100644 --- a/frontend/app/components/ui/chat/chat-messages.tsx +++ b/frontend/app/components/ui/chat/chat-messages.tsx @@ -1,11 +1,12 @@ -import { useEffect, useRef } from "react"; +import { useEffect, useRef, useState, CSSProperties } from "react"; +import PuffLoader from "react-spinners/PuffLoader"; import ChatActions from "./chat-actions"; import ChatMessage from "./chat-message"; import { ChatHandler } from "./chat.interface"; export default function ChatMessages( - props: Pick, + props: Pick ) { const scrollableChatContainerRef = useRef(null); const messageLength = props.messages.length; @@ -28,8 +29,27 @@ export default function ChatMessages( scrollToBottom(); }, [messageLength, lastMessage]); + // State to manage the visibility of the ellipsis + const [showEllipsis, setShowEllipsis] = useState(true); + + useEffect(() => { + // Toggle the visibility of the ellipsis every second + const interval = setInterval(() => { + setShowEllipsis((prev) => !prev); + }, 1000); + + return () => clearInterval(interval); + }, []); // Empty dependency array to run only once on component mount + return ( -
+
+ {props.isLoading && ( +
+

+ +

+
+ )}
); } + +// import { useEffect, useRef } from "react"; + +// import ChatActions from "./chat-actions"; +// import ChatMessage from "./chat-message"; +// import { ChatHandler } from "./chat.interface"; + +// export default function ChatMessages( +// props: Pick, +// ) { +// const scrollableChatContainerRef = useRef(null); +// const messageLength = props.messages.length; +// const lastMessage = props.messages[messageLength - 1]; + +// const scrollToBottom = () => { +// if (scrollableChatContainerRef.current) { +// scrollableChatContainerRef.current.scrollTop = +// scrollableChatContainerRef.current.scrollHeight; +// } +// }; + +// const isLastMessageFromAssistant = +// messageLength > 0 && lastMessage?.role !== "user"; +// const showReload = +// props.reload && !props.isLoading && isLastMessageFromAssistant; +// const showStop = props.stop && props.isLoading; + +// useEffect(() => { +// scrollToBottom(); +// }, [messageLength, lastMessage]); + +// return ( +//
+//
+// {props.messages.map((m) => ( +// +// ))} +//
+//
+// +//
+//
+// ); +// } From 568c7426d071ab127564aa62468ed97a19aa327b Mon Sep 17 00:00:00 2001 From: Yee Kit Date: Tue, 5 Mar 2024 14:45:57 +0800 Subject: [PATCH 2/2] Updated loading spinner to use native svg/tailwinds & moved it in 'send' button --- .../app/components/ui/chat/chat-actions.tsx | 6 +- .../app/components/ui/chat/chat-input.tsx | 22 +++-- .../app/components/ui/chat/chat-message.tsx | 10 +-- .../app/components/ui/chat/chat-messages.tsx | 84 ++----------------- 4 files changed, 31 insertions(+), 91 deletions(-) diff --git a/frontend/app/components/ui/chat/chat-actions.tsx b/frontend/app/components/ui/chat/chat-actions.tsx index b2771bb..da5e3fb 100644 --- a/frontend/app/components/ui/chat/chat-actions.tsx +++ b/frontend/app/components/ui/chat/chat-actions.tsx @@ -1,13 +1,13 @@ import { PauseCircle, RefreshCw } from "lucide-react"; -import { Button } from "../button"; -import { ChatHandler } from "./chat.interface"; +import { Button } from "@/app/components/ui/button"; +import { ChatHandler } from "@/app/components/ui/chat/chat.interface"; export default function ChatActions( props: Pick & { showReload?: boolean; showStop?: boolean; - } + }, ) { return (
diff --git a/frontend/app/components/ui/chat/chat-input.tsx b/frontend/app/components/ui/chat/chat-input.tsx index 8c04f82..1f0d62d 100644 --- a/frontend/app/components/ui/chat/chat-input.tsx +++ b/frontend/app/components/ui/chat/chat-input.tsx @@ -1,6 +1,7 @@ import { Button } from "@/app/components/ui/button"; import { Input } from "@/app/components/ui/input"; import { ChatHandler } from "@/app/components/ui/chat/chat.interface"; +import { IconSpinner } from "@/app/components/ui/icons"; import { Send } from "lucide-react"; export default function ChatInput( @@ -23,12 +24,23 @@ export default function ChatInput( value={props.input} onChange={props.handleInputChange} /> - - ); diff --git a/frontend/app/components/ui/chat/chat-message.tsx b/frontend/app/components/ui/chat/chat-message.tsx index ea54c1e..78a5416 100644 --- a/frontend/app/components/ui/chat/chat-message.tsx +++ b/frontend/app/components/ui/chat/chat-message.tsx @@ -1,10 +1,10 @@ import { Check, Copy } from "lucide-react"; -import { Button } from "../button"; -import ChatAvatar from "./chat-avatar"; -import { Message } from "./chat.interface"; -import Markdown from "./markdown"; -import { useCopyToClipboard } from "./use-copy-to-clipboard"; +import { Button } from "@/app/components/ui/button"; +import ChatAvatar from "@/app/components/ui/chat/chat-avatar"; +import { Message } from "@/app/components/ui/chat/chat.interface"; +import Markdown from "@/app/components/ui/chat/markdown"; +import { useCopyToClipboard } from "@/app/components/ui/chat/use-copy-to-clipboard"; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; diff --git a/frontend/app/components/ui/chat/chat-messages.tsx b/frontend/app/components/ui/chat/chat-messages.tsx index 200c599..aa34037 100644 --- a/frontend/app/components/ui/chat/chat-messages.tsx +++ b/frontend/app/components/ui/chat/chat-messages.tsx @@ -1,12 +1,11 @@ -import { useEffect, useRef, useState, CSSProperties } from "react"; +import { useEffect, useRef } from "react"; -import PuffLoader from "react-spinners/PuffLoader"; -import ChatActions from "./chat-actions"; -import ChatMessage from "./chat-message"; -import { ChatHandler } from "./chat.interface"; +import ChatActions from "@/app/components/ui/chat/chat-actions"; +import ChatMessage from "@/app/components/ui/chat/chat-message"; +import { ChatHandler } from "@/app/components/ui/chat/chat.interface"; export default function ChatMessages( - props: Pick + props: Pick, ) { const scrollableChatContainerRef = useRef(null); const messageLength = props.messages.length; @@ -29,27 +28,8 @@ export default function ChatMessages( scrollToBottom(); }, [messageLength, lastMessage]); - // State to manage the visibility of the ellipsis - const [showEllipsis, setShowEllipsis] = useState(true); - - useEffect(() => { - // Toggle the visibility of the ellipsis every second - const interval = setInterval(() => { - setShowEllipsis((prev) => !prev); - }, 1000); - - return () => clearInterval(interval); - }, []); // Empty dependency array to run only once on component mount - return ( -
- {props.isLoading && ( -
-

- -

-
- )} +
); } - -// import { useEffect, useRef } from "react"; - -// import ChatActions from "./chat-actions"; -// import ChatMessage from "./chat-message"; -// import { ChatHandler } from "./chat.interface"; - -// export default function ChatMessages( -// props: Pick, -// ) { -// const scrollableChatContainerRef = useRef(null); -// const messageLength = props.messages.length; -// const lastMessage = props.messages[messageLength - 1]; - -// const scrollToBottom = () => { -// if (scrollableChatContainerRef.current) { -// scrollableChatContainerRef.current.scrollTop = -// scrollableChatContainerRef.current.scrollHeight; -// } -// }; - -// const isLastMessageFromAssistant = -// messageLength > 0 && lastMessage?.role !== "user"; -// const showReload = -// props.reload && !props.isLoading && isLastMessageFromAssistant; -// const showStop = props.stop && props.isLoading; - -// useEffect(() => { -// scrollToBottom(); -// }, [messageLength, lastMessage]); - -// return ( -//
-//
-// {props.messages.map((m) => ( -// -// ))} -//
-//
-// -//
-//
-// ); -// }