diff --git a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx index d5c08b797..cc35bdb97 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx @@ -17,8 +17,8 @@ import { Separator } from "@/components/ui/separator"; import { SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"; import { useLLMPreferences } from "@/hooks/use-llm-configs"; import { cn } from "@/lib/utils"; -import { activeChatIdAtom } from "@/stores/chat/active-chat.atom"; -import { chatUIAtom } from "@/stores/chat/chat-ui.atom"; +import { activeChatIdAtom } from "@/stores/chats/active-chat.atom"; +import { chatUIAtom } from "@/stores/chats/active-chat-ui.atom"; export function DashboardClientLayout({ children, diff --git a/surfsense_web/components/chat/ChatInterface.tsx b/surfsense_web/components/chat/ChatInterface.tsx index 56632f1a2..9aa280eb7 100644 --- a/surfsense_web/components/chat/ChatInterface.tsx +++ b/surfsense_web/components/chat/ChatInterface.tsx @@ -7,7 +7,7 @@ import { useEffect } from "react"; import { ChatInputUI } from "@/components/chat/ChatInputGroup"; import { ChatMessagesUI } from "@/components/chat/ChatMessages"; import type { Document } from "@/hooks/use-documents"; -import { activeChatIdAtom } from "@/stores/chat/active-chat.atom"; +import { activeChatIdAtom } from "@/stores/chats/active-chat.atom"; import { ChatPanelContainer } from "./ChatPanel/ChatPanelContainer"; interface ChatInterfaceProps { diff --git a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx index 098d6324a..172e85334 100644 --- a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx +++ b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx @@ -4,8 +4,8 @@ import { LoaderIcon, PanelRight, TriangleAlert } from "lucide-react"; import { toast } from "sonner"; import { generatePodcast } from "@/lib/apis/podcast-apis"; import { cn } from "@/lib/utils"; -import { activeChatAtom, activeChatIdAtom } from "@/stores/chat/active-chat.atom"; -import { chatUIAtom } from "@/stores/chat/chat-ui.atom"; +import { activeChatAtom, activeChatIdAtom } from "@/stores/chats/active-chat.atom"; +import { chatUIAtom } from "@/stores/chats/active-chat-ui.atom"; import { ChatPanelView } from "./ChatPanelView"; export interface GeneratePodcastRequest { diff --git a/surfsense_web/components/chat/ChatPanel/ChatPanelView.tsx b/surfsense_web/components/chat/ChatPanel/ChatPanelView.tsx index 40c2650a5..bb88935f2 100644 --- a/surfsense_web/components/chat/ChatPanel/ChatPanelView.tsx +++ b/surfsense_web/components/chat/ChatPanel/ChatPanelView.tsx @@ -5,8 +5,8 @@ import { AlertCircle, Play, RefreshCw, Sparkles } from "lucide-react"; import { motion } from "motion/react"; import { useCallback } from "react"; import { cn } from "@/lib/utils"; -import { activeChatAtom } from "@/stores/chat/active-chat.atom"; -import { chatUIAtom } from "@/stores/chat/chat-ui.atom"; +import { activeChatAtom } from "@/stores/chats/active-chat.atom"; +import { chatUIAtom } from "@/stores/chats/active-chat-ui.atom"; import { getPodcastStalenessMessage, isPodcastStale } from "../PodcastUtils"; import type { GeneratePodcastRequest } from "./ChatPanelContainer"; import { ConfigModal } from "./ConfigModal"; diff --git a/surfsense_web/components/chat/ChatPanel/ConfigModal.tsx b/surfsense_web/components/chat/ChatPanel/ConfigModal.tsx index f1efdd089..b67918a9a 100644 --- a/surfsense_web/components/chat/ChatPanel/ConfigModal.tsx +++ b/surfsense_web/components/chat/ChatPanel/ConfigModal.tsx @@ -4,7 +4,7 @@ import { useAtomValue } from "jotai"; import { Pencil } from "lucide-react"; import { useCallback, useContext, useState } from "react"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; -import { activeChatAtom } from "@/stores/chat/active-chat.atom"; +import { activeChatAtom } from "@/stores/chats/active-chat.atom"; import type { GeneratePodcastRequest } from "./ChatPanelContainer"; interface ConfigModalProps { diff --git a/surfsense_web/lib/apis/chat-apis.ts b/surfsense_web/lib/apis/chat-apis.ts index fb1c98708..4ae8a8feb 100644 --- a/surfsense_web/lib/apis/chat-apis.ts +++ b/surfsense_web/lib/apis/chat-apis.ts @@ -1,28 +1,56 @@ import type { ChatDetails } from "@/app/dashboard/[search_space_id]/chats/chats-client"; export const fetchChatDetails = async ( - chatId: string, - authToken: string + chatId: string, + authToken: string ): Promise => { - try { - const response = await fetch( - `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/chats/${Number(chatId)}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${authToken}`, - }, - } - ); + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/chats/${Number( + chatId + )}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${authToken}`, + }, + } + ); - if (!response.ok) { - throw new Error(`Failed to fetch chat details: ${response.statusText}`); - } + if (!response.ok) { + throw new Error(`Failed to fetch chat details: ${response.statusText}`); + } - return await response.json(); - } catch (err) { - console.error("Error fetching chat details:", err); - return null; - } + return await response.json(); + } catch (err) { + console.error("Error fetching chat details:", err); + return null; + } +}; + +export const fetchChatsBySearchSpace = async ( + searchSpaceId: string, + authToken: string +): Promise => { + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/chats?search_space_id=${searchSpaceId}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${authToken}`, + }, + } + ); + if (!response.ok) { + throw new Error(`Failed to fetch chats: ${response.statusText}`); + } + + return await response.json(); + } catch (err) { + console.error("Error fetching chats:", err); + return null; + } }; diff --git a/surfsense_web/lib/query-client/cache-keys.ts b/surfsense_web/lib/query-client/cache-keys.ts index 48f7e6052..0b66f1450 100644 --- a/surfsense_web/lib/query-client/cache-keys.ts +++ b/surfsense_web/lib/query-client/cache-keys.ts @@ -1,3 +1,4 @@ export const cacheKeys = { activeChat: (chatId: string) => ["activeChat", chatId], + activeSearchSpaceChats: (searchSpaceId: string) => ["activeSearchSpaceChats", searchSpaceId], }; diff --git a/surfsense_web/stores/chat/chat-ui.atom.ts b/surfsense_web/stores/chats/active-chat-ui.atom.ts similarity index 100% rename from surfsense_web/stores/chat/chat-ui.atom.ts rename to surfsense_web/stores/chats/active-chat-ui.atom.ts diff --git a/surfsense_web/stores/chat/active-chat.atom.ts b/surfsense_web/stores/chats/active-chat.atom.ts similarity index 100% rename from surfsense_web/stores/chat/active-chat.atom.ts rename to surfsense_web/stores/chats/active-chat.atom.ts diff --git a/surfsense_web/stores/chats/active-search-space-chats.atom.ts b/surfsense_web/stores/chats/active-search-space-chats.atom.ts new file mode 100644 index 000000000..df5dd2dcd --- /dev/null +++ b/surfsense_web/stores/chats/active-search-space-chats.atom.ts @@ -0,0 +1,23 @@ +import { atomWithQuery } from "jotai-tanstack-query"; +import { fetchChatsBySearchSpace } from "@/lib/apis/chat-apis"; +import { activeSearchSpaceIdAtom } from "../seach-space/active-seach-space.atom"; + +export const activeSearchSpaceChatsAtom = atomWithQuery((get) => { + const searchSpaceId = get(activeSearchSpaceIdAtom); + const authToken = localStorage.getItem("surfsense_bearer_token"); + + return { + queryKey: ["chatsBySearchSpace", searchSpaceId], + enabled: !!searchSpaceId && !!authToken, + queryFn: async () => { + if (!authToken) { + throw new Error("No authentication token found"); + } + if (!searchSpaceId) { + throw new Error("No search space id found"); + } + + return fetchChatsBySearchSpace(searchSpaceId, authToken); + }, + }; +});