diff --git a/frontend/src/Navigation.tsx b/frontend/src/Navigation.tsx index b38ade537..ce23e90ef 100644 --- a/frontend/src/Navigation.tsx +++ b/frontend/src/Navigation.tsx @@ -39,6 +39,8 @@ import { setSelectedDocs, setSourceDocs, } from './preferences/preferenceSlice'; +import Spinner from './assets/spinner.svg'; +import SpinnerDark from './assets/spinner-dark.svg'; import { selectQueries } from './conversation/conversationSlice'; import Upload from './upload/Upload'; import Help from './components/Help'; @@ -70,6 +72,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { const conversations = useSelector(selectConversations); const modalStateDeleteConv = useSelector(selectModalStateDeleteConv); const conversationId = useSelector(selectConversationId); + const [isDeletingConversation, setIsDeletingConversation] = useState(false); const { isMobile } = useMediaQuery(); const [isDarkTheme] = useDarkTheme(); @@ -91,25 +94,28 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { const navigate = useNavigate(); useEffect(() => { - if (!conversations) { + if (!conversations?.data) { fetchConversations(); } if (queries.length === 0) { resetConversation(); } - }, [conversations, dispatch]); + }, [conversations?.data, dispatch]); async function fetchConversations() { + dispatch(setConversations({ ...conversations, loading: true })); return await getConversations() .then((fetchedConversations) => { dispatch(setConversations(fetchedConversations)); }) .catch((error) => { console.error('Failed to fetch conversations: ', error); + dispatch(setConversations({ data: null, loading: false })); }); } const handleDeleteAllConversations = () => { + setIsDeletingConversation(true); conversationService .deleteAll() .then(() => { @@ -119,6 +125,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { }; const handleDeleteConversation = (id: string) => { + setIsDeletingConversation(true); conversationService .delete(id, {}) .then(() => { @@ -205,6 +212,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { setNavOpen(!isMobile); }, [isMobile]); useDefaultDocument(); + return ( <> {!navOpen && ( @@ -306,13 +314,22 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { id="conversationsMainDiv" className="mb-auto h-[78vh] overflow-y-auto overflow-x-hidden dark:text-white" > - {conversations && conversations.length > 0 ? ( + {conversations?.loading && !isDeletingConversation && ( +
+ Loading... +
+ )} + {conversations?.data && conversations.data.length > 0 ? (

{t('chats')}

- {conversations?.map((conversation) => ( + {conversations.data?.map((conversation) => ( { } } -export async function getConversations(): Promise< - { name: string; id: string }[] | null -> { +export async function getConversations(): Promise<{ + data: { name: string; id: string }[] | null; + loading: boolean; +}> { try { const response = await conversationService.getConversations(); const data = await response.json(); @@ -34,10 +35,10 @@ export async function getConversations(): Promise< conversations.push(conversation as { name: string; id: string }); }); - return conversations; + return { data: conversations, loading: false }; } catch (error) { console.log(error); - return null; + return { data: null, loading: false }; } } diff --git a/frontend/src/preferences/preferenceSlice.ts b/frontend/src/preferences/preferenceSlice.ts index 6fb2480b2..c566ba70b 100644 --- a/frontend/src/preferences/preferenceSlice.ts +++ b/frontend/src/preferences/preferenceSlice.ts @@ -15,7 +15,10 @@ export interface Preference { token_limit: number; selectedDocs: Doc | null; sourceDocs: Doc[] | null; - conversations: { name: string; id: string }[] | null; + conversations: { + data: { name: string; id: string }[] | null; + loading: boolean; + }; modalState: ActiveState; } @@ -34,7 +37,10 @@ const initialState: Preference = { retriever: 'classic', } as Doc, sourceDocs: null, - conversations: null, + conversations: { + data: null, + loading: false, + }, modalState: 'INACTIVE', }; diff --git a/frontend/src/store.ts b/frontend/src/store.ts index 565ea8cc9..5843d4932 100644 --- a/frontend/src/store.ts +++ b/frontend/src/store.ts @@ -23,7 +23,10 @@ const preloadedState: { preference: Preference } = { chunks: JSON.parse(chunks ?? '2').toString(), token_limit: token_limit ? parseInt(token_limit) : 2000, selectedDocs: doc !== null ? JSON.parse(doc) : null, - conversations: null, + conversations: { + data: null, + loading: false, + }, sourceDocs: [ { name: 'default',