diff --git a/surfsense_web/app/dashboard/[search_space_id]/chats/chats-client.tsx b/surfsense_web/app/dashboard/[search_space_id]/chats/chats-client.tsx index 272f34509..a0383d886 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/chats/chats-client.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/chats/chats-client.tsx @@ -55,8 +55,8 @@ import { SelectValue, } from "@/components/ui/select"; import { useAtom, useAtomValue } from "jotai"; -import { activeSearchSpaceChatsAtom } from "@/atoms/chats/queries/active-search-space-chats.query.atom"; -import { deleteChatMutationAtom } from "@/atoms/chats/mutations/delete-chat.mutation.atom"; +import { activeSearchSpaceChatsAtom } from "@/atoms/chats/chat-queries.atom"; +import { deleteChatMutationAtom } from "@/atoms/chats/chat-mutations.atom"; export interface Chat { created_at: string; 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 ceeb1e7f4..40f6b2255 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/client-layout.tsx @@ -27,9 +27,9 @@ import { } from "@/components/ui/sidebar"; import { useLLMPreferences } from "@/hooks/use-llm-configs"; import { cn } from "@/lib/utils"; -import { activeChatIdAtom } from "@/atoms/chats/queries/active-chat.query.atom"; -import { chatUIAtom } from "@/atoms/chats/active-chat.atom"; -import { activeSearchSpaceIdAtom } from "@/atoms/seach-spaces/active-seach-space.atom"; +import { activeChatIdAtom } from "@/atoms/chats/chat-queries.atom"; +import { chatUIAtom } from "@/atoms/chats/chat-uis.atom"; +import { activeSearchSpaceIdAtom } from "@/atoms/seach-spaces/seach-space-queries.atom"; export function DashboardClientLayout({ children, diff --git a/surfsense_web/app/dashboard/page.tsx b/surfsense_web/app/dashboard/page.tsx index 4c9e30232..d61e714c6 100644 --- a/surfsense_web/app/dashboard/page.tsx +++ b/surfsense_web/app/dashboard/page.tsx @@ -236,7 +236,7 @@ const DashboardPage = () => { {searchSpaces && searchSpaces.length > 0 && searchSpaces.map((space) => ( - + ((get) => { }, }; }); + +export const activeSearchSpaceChatsAtom = atomWithQuery((get) => { + const searchSpaceId = get(activeSearchSpaceIdAtom); + const authToken = localStorage.getItem("surfsense_bearer_token"); + + return { + queryKey: cacheKeys.activeSearchSpace.chats(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); + }, + }; +}); diff --git a/surfsense_web/atoms/chats/active-chat.atom.ts b/surfsense_web/atoms/chats/chat-uis.atom.ts similarity index 100% rename from surfsense_web/atoms/chats/active-chat.atom.ts rename to surfsense_web/atoms/chats/chat-uis.atom.ts diff --git a/surfsense_web/atoms/chats/queries/active-search-space-chats.query.atom.ts b/surfsense_web/atoms/chats/queries/active-search-space-chats.query.atom.ts deleted file mode 100644 index feafcf434..000000000 --- a/surfsense_web/atoms/chats/queries/active-search-space-chats.query.atom.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { atomWithQuery } from "jotai-tanstack-query"; -import { fetchChatsBySearchSpace } from "@/lib/apis/chat-apis"; -import { activeSearchSpaceIdAtom } from "../../seach-spaces/active-seach-space.atom"; -import { cacheKeys } from "@/lib/query-client/cache-keys"; - -export const activeSearchSpaceChatsAtom = atomWithQuery((get) => { - const searchSpaceId = get(activeSearchSpaceIdAtom); - const authToken = localStorage.getItem("surfsense_bearer_token"); - - return { - queryKey: cacheKeys.activeSearchSpace.chats(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); - }, - }; -}); diff --git a/surfsense_web/atoms/seach-spaces/active-seach-space.atom.ts b/surfsense_web/atoms/seach-spaces/seach-space-queries.atom.ts similarity index 97% rename from surfsense_web/atoms/seach-spaces/active-seach-space.atom.ts rename to surfsense_web/atoms/seach-spaces/seach-space-queries.atom.ts index 4bccf496f..dcdf6d550 100644 --- a/surfsense_web/atoms/seach-spaces/active-seach-space.atom.ts +++ b/surfsense_web/atoms/seach-spaces/seach-space-queries.atom.ts @@ -1,3 +1,3 @@ import { atom } from "jotai"; -export const activeSearchSpaceIdAtom = atom(null); +export const activeSearchSpaceIdAtom = atom(null); \ No newline at end of file diff --git a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx index bc443d143..b2dc67ba8 100644 --- a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx +++ b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx @@ -2,10 +2,10 @@ import { useAtom, useAtomValue } from "jotai"; import { LoaderIcon, PanelRight, TriangleAlert } from "lucide-react"; import { toast } from "sonner"; -import { generatePodcast } from "@/lib/apis/podcast-apis"; +import { generatePodcast } from "@/lib/apis/podcasts.api"; import { cn } from "@/lib/utils"; -import { activeChatAtom, activeChatIdAtom } from "@/atoms/chats/queries/active-chat.query.atom"; -import { chatUIAtom } from "@/atoms/chats/active-chat.atom"; +import { activeChatAtom, activeChatIdAtom } from "@/atoms/chats/chat-queries.atom"; +import { chatUIAtom } from "@/atoms/chats/chat-uis.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 c1672a7ea..5b490b16c 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 "@/atoms/chats/queries/active-chat.query.atom"; -import { chatUIAtom } from "@/atoms/chats/active-chat.atom"; +import { activeChatAtom } from "@/atoms/chats/chat-queries.atom"; +import { chatUIAtom } from "@/atoms/chats/chat-uis.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 25b6446c0..c7ac58e9b 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 "@/atoms/chats/queries/active-chat.query.atom"; +import { activeChatAtom } from "@/atoms/chats/chat-queries.atom"; import type { GeneratePodcastRequest } from "./ChatPanelContainer"; interface ConfigModalProps { diff --git a/surfsense_web/components/dashboard-breadcrumb.tsx b/surfsense_web/components/dashboard-breadcrumb.tsx index 2348ddb42..2b032f8fd 100644 --- a/surfsense_web/components/dashboard-breadcrumb.tsx +++ b/surfsense_web/components/dashboard-breadcrumb.tsx @@ -13,7 +13,7 @@ import { BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; import { useSearchSpace } from "@/hooks/use-search-space"; -import { fetchChatDetails } from "@/lib/apis/chat-apis"; +import { fetchChatDetails } from "@/lib/apis/chats.api"; interface BreadcrumbItemInterface { label: string; diff --git a/surfsense_web/lib/apis/chat-apis.ts b/surfsense_web/lib/apis/chats.api.ts similarity index 100% rename from surfsense_web/lib/apis/chat-apis.ts rename to surfsense_web/lib/apis/chats.api.ts diff --git a/surfsense_web/lib/apis/podcast-apis.ts b/surfsense_web/lib/apis/podcasts.api.ts similarity index 100% rename from surfsense_web/lib/apis/podcast-apis.ts rename to surfsense_web/lib/apis/podcasts.api.ts diff --git a/surfsense_web/lib/apis/search-spaces.api.ts b/surfsense_web/lib/apis/search-spaces.api.ts new file mode 100644 index 000000000..f4b2ad74d --- /dev/null +++ b/surfsense_web/lib/apis/search-spaces.api.ts @@ -0,0 +1,112 @@ +export const fetchSearchSpaces = async () => { + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces`, + { + headers: { + Authorization: `Bearer ${localStorage.getItem( + "surfsense_bearer_token" + )}`, + }, + method: "GET", + } + ); + + if (!response.ok) { + throw new Error("Not authenticated"); + } + + const data = await response.json(); + return data; + } catch (err: any) { + console.error("Error fetching search spaces:", err); + return null; + } +}; + +export const handleDeleteSearchSpace = async (id: number) => { + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${id}`, + { + method: "DELETE", + headers: { + Authorization: `Bearer ${localStorage.getItem( + "surfsense_bearer_token" + )}`, + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to delete search space"); + } + } catch (error) { + console.error("Error deleting search space:", error); + return; + } +}; + +export const handleCreateSearchSpace = async (data: { + name: string; + description: string; +}) => { + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${localStorage.getItem( + "surfsense_bearer_token" + )}`, + }, + body: JSON.stringify(data), + } + ); + + if (!response.ok) { + throw new Error("Failed to create search space"); + } + + const result = await response.json(); + + return result; + } catch (error) { + console.error("Error creating search space:", error); + throw error; + } +}; + +export const fetchSearchSpace = async (searchSpaceId: string) => { + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/searchspaces/${searchSpaceId}`, + { + headers: { + Authorization: `Bearer ${localStorage.getItem( + "surfsense_bearer_token" + )}`, + }, + method: "GET", + } + ); + + if (response.status === 401) { + // Clear token and redirect to home + localStorage.removeItem("surfsense_bearer_token"); + window.location.href = "/"; + throw new Error("Unauthorized: Redirecting to login page"); + } + + if (!response.ok) { + throw new Error(`Failed to fetch search space: ${response.status}`); + } + + const data = await response.json(); + return data; + } catch (err: any) { + console.error("Error fetching search space:", err); + } +};