From d8735398562833cabee879b432a92dd601704c61 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Fri, 9 May 2025 20:02:49 +0530 Subject: [PATCH 01/18] (fix:message-input) no badge buttons when shared --- frontend/src/components/MessageInput.tsx | 49 +++++++++---------- .../src/conversation/SharedConversation.tsx | 1 + 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/MessageInput.tsx b/frontend/src/components/MessageInput.tsx index 60cd4b81..7f617673 100644 --- a/frontend/src/components/MessageInput.tsx +++ b/frontend/src/components/MessageInput.tsx @@ -34,8 +34,7 @@ type MessageInputProps = { onChange: (e: React.ChangeEvent) => void; onSubmit: () => void; loading: boolean; - showSourceButton?: boolean; - showToolButton?: boolean; + isShared?: boolean; autoFocus?: boolean; }; @@ -44,8 +43,7 @@ export default function MessageInput({ onChange, onSubmit, loading, - showSourceButton = true, - showToolButton = true, + isShared = false, autoFocus = true, }: MessageInputProps) { const { t } = useTranslation(); @@ -345,8 +343,8 @@ export default function MessageInput({
-
- {showSourceButton && ( + {!isShared && ( +
- )} - {showToolButton && ( - )} - - {/* Additional badges can be added here in the future */} -
+ + + {/* Additional badges can be added here in the future */} +
+ )}
-
+
{logs?.map((log, index) => { if (index === logs.length - 1) { return (
- +
); } else - return ; + return ( + + ); })} {loading && }
@@ -134,9 +140,11 @@ function LogsTable({ logs, setPage, loading, tableHeader }: LogsTableProps) { } function Log({ log, + isOpen, onToggle, }: { log: LogData; + isOpen: boolean; onToggle: (id: string) => void; }) { const { t } = useTranslation(); @@ -148,20 +156,17 @@ function Log({ const { id, action, timestamp, ...filteredLog } = log; return ( -
{ - if ((e.target as HTMLDetailsElement).open) { - onToggle(log.id); - } - }} - > - +
+
onToggle(log.id)} + className={`flex cursor-pointer flex-row items-start gap-2 p-2 px-4 py-3 text-gray-900 ${ + isOpen ? 'rounded-t-xl bg-[#F1F1F1] dark:bg-[#1B1B1B]' : '' + }`} + > Expand log entry

{`${log.timestamp}`}

@@ -174,18 +179,22 @@ function Log({ : log.question}
-
-
-

- {JSON.stringify(filteredLog, null, 2)} -

-
- -
-
+ {isOpen && ( +
+
+
+              {JSON.stringify(filteredLog, null, 2)}
+            
+
+
+ +
+
+ )} +
); } From 8552e81022826f24cb8bdb2ab36d3261708b15d5 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Fri, 9 May 2025 21:39:54 +0530 Subject: [PATCH 03/18] (fix:input) sync with translations --- frontend/src/components/MessageInput.tsx | 6 +++--- frontend/src/locale/en.json | 5 +++++ frontend/src/locale/es.json | 5 +++++ frontend/src/locale/jp.json | 7 ++++++- frontend/src/locale/ru.json | 7 ++++++- frontend/src/locale/zh-TW.json | 5 +++++ frontend/src/locale/zh.json | 7 ++++++- 7 files changed, 36 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/MessageInput.tsx b/frontend/src/components/MessageInput.tsx index 7f617673..e8291519 100644 --- a/frontend/src/components/MessageInput.tsx +++ b/frontend/src/components/MessageInput.tsx @@ -272,11 +272,11 @@ export default function MessageInput({ dispatch(removeAttachment(attachment.id)); } }} - aria-label="Remove attachment" + aria-label={t('conversation.attachments.remove')} > Remove @@ -394,7 +394,7 @@ export default function MessageInput({ className="mr-1 h-3.5 w-3.5 sm:mr-1.5 sm:h-4 sm:w-4" /> - Attach + {t('conversation.attachments.attach')} Date: Mon, 12 May 2025 14:38:15 +0530 Subject: [PATCH 04/18] (fix/logs)log must render once --- frontend/src/settings/Logs.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/frontend/src/settings/Logs.tsx b/frontend/src/settings/Logs.tsx index 74b00a25..d5d4d3e3 100644 --- a/frontend/src/settings/Logs.tsx +++ b/frontend/src/settings/Logs.tsx @@ -17,12 +17,16 @@ type LogsProps = { export default function Logs({ agentId, tableHeader }: LogsProps) { const token = useSelector(selectToken); - const [logs, setLogs] = useState([]); + const [logsByPage, setLogsByPage] = useState>({}); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [loadingLogs, setLoadingLogs] = useLoaderState(true); + const logs = Object.values(logsByPage).flat(); + const fetchLogs = async () => { + if (logsByPage[page] && logsByPage[page].length > 0) return; + setLoadingLogs(true); try { const response = await userService.getLogs( @@ -34,9 +38,13 @@ export default function Logs({ agentId, tableHeader }: LogsProps) { token, ); if (!response.ok) throw new Error('Failed to fetch logs'); - const olderLogs = await response.json(); - setLogs((prevLogs) => [...prevLogs, ...olderLogs.logs]); - setHasMore(olderLogs.has_more); + const data = await response.json(); + + setLogsByPage((prev) => ({ + ...prev, + [page]: data.logs, + })); + setHasMore(data.has_more); } catch (error) { console.error(error); } finally { From 357ced6cba04bf989b6cefcd260a9aac24e97a37 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Mon, 12 May 2025 16:32:17 +0530 Subject: [PATCH 05/18] Revert "(fix:message-input) no badge buttons when shared" This reverts commit d8735398562833cabee879b432a92dd601704c61. --- frontend/src/components/MessageInput.tsx | 50 ++++++++++--------- .../src/conversation/SharedConversation.tsx | 3 +- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/frontend/src/components/MessageInput.tsx b/frontend/src/components/MessageInput.tsx index e8291519..532cc599 100644 --- a/frontend/src/components/MessageInput.tsx +++ b/frontend/src/components/MessageInput.tsx @@ -34,7 +34,8 @@ type MessageInputProps = { onChange: (e: React.ChangeEvent) => void; onSubmit: () => void; loading: boolean; - isShared?: boolean; + showSourceButton?: boolean; + showToolButton?: boolean; autoFocus?: boolean; }; @@ -43,7 +44,8 @@ export default function MessageInput({ onChange, onSubmit, loading, - isShared = false, + showSourceButton = true, + showToolButton = true, autoFocus = true, }: MessageInputProps) { const { t } = useTranslation(); @@ -343,8 +345,8 @@ export default function MessageInput({
- {!isShared && ( -
+
+ {showSourceButton && ( + )} + {showToolButton && ( - - - - {/* Additional badges can be added here in the future */} -
- )} + )} + + {/* Additional badges can be added here in the future */} +
); } return null; })} -
- Source - - {t('none')} - -
- {selectedDocs === null && ( - Selected - )} -
-
) : (
From e1e608b744a263387224dc88ec0a7b2161ac7330 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Tue, 13 May 2025 06:16:16 +0530 Subject: [PATCH 07/18] (fix:bubble) sleeker source cards --- frontend/src/conversation/ConversationBubble.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/conversation/ConversationBubble.tsx b/frontend/src/conversation/ConversationBubble.tsx index 2f9891b5..4d657950 100644 --- a/frontend/src/conversation/ConversationBubble.tsx +++ b/frontend/src/conversation/ConversationBubble.tsx @@ -339,7 +339,7 @@ const ConversationBubble = forwardRef< onMouseOver={() => setActiveTooltip(index)} onMouseOut={() => setActiveTooltip(null)} > -

+

{source.text}

@@ -663,7 +663,7 @@ function AllSources(sources: AllSourcesProps) { {sources.sources.map((source, index) => (

) : null} -

+

{source.text}

From 81104153a6feb7865bc6495edd120b769bdac3ac Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 14 May 2025 03:01:57 +0530 Subject: [PATCH 08/18] (feat:action-buttons) combine the buttons at the top of layout --- frontend/src/App.tsx | 2 + frontend/src/components/ActionButtons.tsx | 86 ++++++++++++++++++++++ frontend/src/conversation/Conversation.tsx | 51 ------------- 3 files changed, 88 insertions(+), 51 deletions(-) create mode 100644 frontend/src/components/ActionButtons.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 41b05ac0..66ba6235 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -13,6 +13,7 @@ import Navigation from './Navigation'; import PageNotFound from './PageNotFound'; import Setting from './settings'; import Agents from './agents'; +import ActionButtons from './components/ActionButtons'; function AuthWrapper({ children }: { children: React.ReactNode }) { const { isAuthLoading } = useTokenAuth(); @@ -34,6 +35,7 @@ function MainLayout() { return (
+
(); + const conversationId = useSelector(selectConversationId); + const [isShareModalOpen, setShareModalState] = useState(false); + + const newChat = () => { + dispatch(setConversation([])); + dispatch( + updateConversationId({ + query: { conversationId: null }, + }), + ); + }; + + return ( +
+
+ {showNewChat && ( + + )} + + {showShare && conversationId && ( + <> + + {isShareModalOpen && ( + setShareModalState(false)} + conversationId={conversationId} + /> + )} + + )} +
{/* */}
+
+
+ ); +} diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 21fc3a1f..bbe96d9c 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -4,11 +4,8 @@ import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import DragFileUpload from '../assets/DragFileUpload.svg'; -import newChatIcon from '../assets/openNewChat.svg'; -import ShareIcon from '../assets/share.svg'; import MessageInput from '../components/MessageInput'; import { useMediaQuery } from '../hooks'; -import { ShareConversationModal } from '../modals/ShareConversationModal'; import { ActiveState } from '../models/misc'; import { selectConversationId, @@ -184,10 +181,6 @@ export default function Conversation() { ); }; - const newChat = () => { - if (queries && queries.length > 0) resetConversation(); - }; - useEffect(() => { if (queries.length) { queries[queries.length - 1].error && setLastQueryReturnedErr(true); @@ -196,50 +189,6 @@ export default function Conversation() { }, [queries[queries.length - 1]]); return (
- {conversationId && queries.length > 0 && ( -
-
- {isMobile && queries.length > 0 && ( - - )} - - -
- {isShareModalOpen && ( - { - setShareModalState(false); - }} - conversationId={conversationId} - /> - )} -
- )} - Date: Wed, 14 May 2025 04:13:53 +0530 Subject: [PATCH 09/18] (fix:input-lag) localised the input state to messageInput --- frontend/src/components/MessageInput.tsx | 19 ++++++++++++------- frontend/src/conversation/Conversation.tsx | 18 ++++++++---------- .../src/conversation/SharedConversation.tsx | 16 +++++++--------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/MessageInput.tsx b/frontend/src/components/MessageInput.tsx index 532cc599..79487188 100644 --- a/frontend/src/components/MessageInput.tsx +++ b/frontend/src/components/MessageInput.tsx @@ -30,9 +30,7 @@ import SourcesPopup from './SourcesPopup'; import ToolsPopup from './ToolsPopup'; type MessageInputProps = { - value: string; - onChange: (e: React.ChangeEvent) => void; - onSubmit: () => void; + onSubmit: (text: string) => void; loading: boolean; showSourceButton?: boolean; showToolButton?: boolean; @@ -40,8 +38,6 @@ type MessageInputProps = { }; export default function MessageInput({ - value, - onChange, onSubmit, loading, showSourceButton = true, @@ -50,6 +46,7 @@ export default function MessageInput({ }: MessageInputProps) { const { t } = useTranslation(); const [isDarkTheme] = useDarkTheme(); + const [value, setValue] = useState(''); const inputRef = useRef(null); const sourceButtonRef = useRef(null); const toolButtonRef = useRef(null); @@ -232,6 +229,11 @@ export default function MessageInput({ handleInput(); }, []); + const handleChange = (e: React.ChangeEvent) => { + setValue(e.target.value); + handleInput(); + }; + const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); @@ -248,7 +250,10 @@ export default function MessageInput({ }; const handleSubmit = () => { - onSubmit(); + if (value.trim() && !loading) { + onSubmit(value); + setValue(''); + } }; return (
@@ -334,7 +339,7 @@ export default function MessageInput({ id="message-input" ref={inputRef} value={value} - onChange={onChange} + onChange={handleChange} tabIndex={1} placeholder={t('inputPlaceholder')} className="inputbox-style no-scrollbar w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-t-[23px] bg-lotion px-4 py-3 text-base leading-tight opacity-100 focus:outline-none dark:bg-transparent dark:text-bright-gray dark:placeholder-bright-gray dark:placeholder-opacity-50 sm:px-6 sm:py-5" diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index bbe96d9c..753a3725 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -39,7 +39,6 @@ export default function Conversation() { const conversationId = useSelector(selectConversationId); const selectedAgent = useSelector(selectSelectedAgent); - const [input, setInput] = useState(''); const [uploadModalState, setUploadModalState] = useState('INACTIVE'); const [files, setFiles] = useState([]); @@ -143,19 +142,19 @@ export default function Conversation() { }; const handleQuestionSubmission = ( - updatedQuestion?: string, + question?: string, updated?: boolean, indx?: number, ) => { if (updated === true) { - handleQuestion({ question: updatedQuestion as string, index: indx }); - } else if (input && status !== 'loading') { + handleQuestion({ question: question as string, index: indx }); + } else if (question && status !== 'loading') { if (lastQueryReturnedErr) { dispatch( updateQuery({ index: queries.length - 1, query: { - prompt: input, + prompt: question, }, }), ); @@ -165,10 +164,9 @@ export default function Conversation() { }); } else { handleQuestion({ - question: input, + question, }); } - setInput(''); } }; @@ -207,9 +205,9 @@ export default function Conversation() { setInput(e.target.value)} - onSubmit={handleQuestionSubmission} + onSubmit={(text) => { + handleQuestionSubmission(text); + }} loading={status === 'loading'} showSourceButton={selectedAgent ? false : true} showToolButton={selectedAgent ? false : true} diff --git a/frontend/src/conversation/SharedConversation.tsx b/frontend/src/conversation/SharedConversation.tsx index e7612ab7..3627c048 100644 --- a/frontend/src/conversation/SharedConversation.tsx +++ b/frontend/src/conversation/SharedConversation.tsx @@ -35,7 +35,6 @@ export const SharedConversation = () => { const apiKey = useSelector(selectClientAPIKey); const status = useSelector(selectStatus); - const [input, setInput] = useState(''); const { t } = useTranslation(); const dispatch = useDispatch(); @@ -76,15 +75,15 @@ export const SharedConversation = () => { }); }; - const handleQuestionSubmission = () => { - if (input && status !== 'loading') { + const handleQuestionSubmission = (question?: string) => { + if (question && status !== 'loading') { if (lastQueryReturnedErr) { // update last failed query with new prompt dispatch( updateQuery({ index: queries.length - 1, query: { - prompt: input, + prompt: question, }, }), ); @@ -93,9 +92,8 @@ export const SharedConversation = () => { isRetry: true, }); } else { - handleQuestion({ question: input }); + handleQuestion({ question }); } - setInput(''); } }; @@ -156,9 +154,9 @@ export const SharedConversation = () => {
{apiKey ? ( setInput(e.target.value)} - onSubmit={() => handleQuestionSubmission()} + onSubmit={(text) => { + handleQuestionSubmission(text); + }} loading={status === 'loading'} showSourceButton={false} showToolButton={false} From 2855283a2c0b96be3a44c7a8b25fa88abe44b359 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Wed, 14 May 2025 04:15:11 +0530 Subject: [PATCH 10/18] (fix/shared) append to right state --- frontend/src/conversation/sharedConversationSlice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/conversation/sharedConversationSlice.ts b/frontend/src/conversation/sharedConversationSlice.ts index 4f784ad2..f0482fa5 100644 --- a/frontend/src/conversation/sharedConversationSlice.ts +++ b/frontend/src/conversation/sharedConversationSlice.ts @@ -72,7 +72,7 @@ export const fetchSharedAnswer = createAsyncThunk( dispatch(sharedConversationSlice.actions.setStatus('failed')); dispatch( sharedConversationSlice.actions.raiseError({ - index: state.conversation.queries.length - 1, + index: state.sharedConversation.queries.length - 1, message: data.error, }), ); From 7f592f2b3516a8d5dd69d993d9c72f73804756cc Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Fri, 16 May 2025 01:56:53 +0530 Subject: [PATCH 11/18] (fix/layout) prevent overlap in tab screen --- frontend/src/App.tsx | 7 +++---- frontend/src/Navigation.tsx | 6 +++--- frontend/src/conversation/ConversationMessages.tsx | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 66ba6235..ec383ca7 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -37,10 +37,10 @@ function MainLayout() {
@@ -48,7 +48,6 @@ function MainLayout() {
); } - export default function App() { const [, , componentMounted] = useDarkTheme(); if (!componentMounted) { diff --git a/frontend/src/Navigation.tsx b/frontend/src/Navigation.tsx index 53487dd6..02e9f19c 100644 --- a/frontend/src/Navigation.tsx +++ b/frontend/src/Navigation.tsx @@ -219,7 +219,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { return ( <> {!navOpen && ( -
+
-
+