diff --git a/frontend/src/components/MessageInput.tsx b/frontend/src/components/MessageInput.tsx index a60a0f57..1e3576ee 100644 --- a/frontend/src/components/MessageInput.tsx +++ b/frontend/src/components/MessageInput.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useDarkTheme } from '../hooks'; -import { useSelector } from 'react-redux'; +import { useSelector, useDispatch } from 'react-redux'; import userService from '../api/services/userService'; import endpoints from '../api/endpoints'; import PaperPlane from '../assets/paper_plane.svg'; @@ -15,14 +15,13 @@ import { selectSelectedDocs, selectToken } from '../preferences/preferenceSlice' import { ActiveState } from '../models/misc'; import Upload from '../upload/Upload'; import ClipIcon from '../assets/clip.svg'; - +import { setAttachments } from '../conversation/conversationSlice'; interface MessageInputProps { value: string; onChange: (e: React.ChangeEvent) => void; onSubmit: () => void; loading: boolean; - onAttachmentChange?: (attachments: { fileName: string; id: string }[]) => void; } interface UploadState { @@ -39,7 +38,6 @@ export default function MessageInput({ onChange, onSubmit, loading, - onAttachmentChange, }: MessageInputProps) { const { t } = useTranslation(); const [isDarkTheme] = useDarkTheme(); @@ -53,6 +51,8 @@ export default function MessageInput({ const selectedDocs = useSelector(selectSelectedDocs); const token = useSelector(selectToken); + + const dispatch = useDispatch(); const handleFileAttachment = (e: React.ChangeEvent) => { if (!e.target.files || e.target.files.length === 0) return; @@ -213,21 +213,18 @@ export default function MessageInput({ console.log('Selected document:', doc); }; - useEffect(() => { - if (onAttachmentChange) { - const completedAttachments = uploads - .filter(upload => upload.status === 'completed' && upload.attachment_id) - .map(upload => ({ - fileName: upload.fileName, - id: upload.attachment_id as string - })); - onAttachmentChange(completedAttachments); - } - }, [uploads, onAttachmentChange]); const handleSubmit = () => { + const completedAttachments = uploads + .filter(upload => upload.status === 'completed' && upload.attachment_id) + .map(upload => ({ + fileName: upload.fileName, + id: upload.attachment_id as string + })); + + dispatch(setAttachments(completedAttachments)); + onSubmit(); - setUploads(prevUploads => prevUploads.filter(upload => upload.status !== 'completed')); }; return (
diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index f03d89b6..a3c69695 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -29,11 +29,6 @@ import { ActiveState } from '../models/misc'; import ConversationMessages from './ConversationMessages'; import MessageInput from '../components/MessageInput'; -interface AttachmentState { - fileName: string; - id: string; -} - export default function Conversation() { const token = useSelector(selectToken); const queries = useSelector(selectQueries); @@ -50,7 +45,6 @@ export default function Conversation() { useState('INACTIVE'); const [files, setFiles] = useState([]); const [handleDragActive, setHandleDragActive] = useState(false); - const [attachments, setAttachments] = useState([]); const onDrop = useCallback((acceptedFiles: File[]) => { setUploadModalState('ACTIVE'); @@ -101,13 +95,11 @@ export default function Conversation() { isRetry = false, updated = null, indx = undefined, - attachments = [], }: { question: string; isRetry?: boolean; updated?: boolean | null; indx?: number; - attachments?: { fileName: string; id: string }[]; }) => { if (updated === true) { !isRetry && @@ -116,11 +108,8 @@ export default function Conversation() { } else { question = question.trim(); if (question === '') return; - !isRetry && dispatch(addQuery({ prompt: question, attachments })); - fetchStream.current = dispatch(fetchAnswer({ - question, - attachments: attachments.map(a => a.id) - })); + !isRetry && dispatch(addQuery({ prompt: question })); + fetchStream.current = dispatch(fetchAnswer({ question })); } }; @@ -172,10 +161,8 @@ export default function Conversation() { }); } else { handleQuestion({ - question: input, - attachments: attachments + question: input, }); - setAttachments([]); } setInput(''); } @@ -260,7 +247,6 @@ export default function Conversation() { onChange={(e) => setInput(e.target.value)} onSubmit={handleQuestionSubmission} loading={status === 'loading'} - onAttachmentChange={setAttachments} />
diff --git a/frontend/src/conversation/conversationModels.ts b/frontend/src/conversation/conversationModels.ts index 483fcd55..030f2e7a 100644 --- a/frontend/src/conversation/conversationModels.ts +++ b/frontend/src/conversation/conversationModels.ts @@ -13,6 +13,7 @@ export interface ConversationState { queries: Query[]; status: Status; conversationId: string | null; + attachments?: { fileName: string; id: string }[]; } export interface Answer { diff --git a/frontend/src/conversation/conversationSlice.ts b/frontend/src/conversation/conversationSlice.ts index ecd7ef84..e9b3b7ad 100644 --- a/frontend/src/conversation/conversationSlice.ts +++ b/frontend/src/conversation/conversationSlice.ts @@ -13,6 +13,7 @@ const initialState: ConversationState = { queries: [], status: 'idle', conversationId: null, + attachments: [], }; const API_STREAMING = import.meta.env.VITE_API_STREAMING === 'true'; @@ -27,8 +28,8 @@ export function handleAbort() { export const fetchAnswer = createAsyncThunk< Answer, - { question: string; indx?: number; attachments?: string[] } ->('fetchAnswer', async ({ question, indx, attachments }, { dispatch, getState }) => { + { question: string; indx?: number } +>('fetchAnswer', async ({ question, indx }, { dispatch, getState }) => { if (abortController) { abortController.abort(); } @@ -37,6 +38,8 @@ export const fetchAnswer = createAsyncThunk< let isSourceUpdated = false; const state = getState() as RootState; + const attachments = state.conversation.attachments?.map(a => a.id) || []; + if (state.preference) { if (API_STREAMING) { await handleFetchAnswerSteaming( @@ -257,6 +260,9 @@ export const conversationSlice = createSlice({ const { index, message } = action.payload; state.queries[index].error = message; }, + setAttachments: (state, action: PayloadAction<{ fileName: string; id: string }[]>) => { + state.attachments = action.payload; + }, }, extraReducers(builder) { builder @@ -289,5 +295,6 @@ export const { updateStreamingSource, updateToolCalls, setConversation, + setAttachments, } = conversationSlice.actions; export default conversationSlice.reducer;