From bd4e5d627d237f0cb8cd597a76a2748b9cd9fc11 Mon Sep 17 00:00:00 2001 From: thierryverse Date: Wed, 12 Nov 2025 13:27:15 +0200 Subject: [PATCH] improve naming --- .../[search_space_id]/chats/chats-client.tsx | 4 +- .../[search_space_id]/client-layout.tsx | 6 +-- .../{stores => atoms}/announcement.atom.ts | 0 .../chats/active-chat-ui.atom.ts | 0 .../atoms/chats/queries/active-chat.atom.ts | 50 +++++++++++++++++++ .../active-search-space-chats.atom.ts | 2 +- .../seach-spaces}/active-seach-space.atom.ts | 0 .../components/announcement-banner.tsx | 2 +- .../chat/ChatPanel/ChatPanelContainer.tsx | 4 +- .../chat/ChatPanel/ChatPanelView.tsx | 4 +- .../components/chat/ChatPanel/ConfigModal.tsx | 2 +- surfsense_web/lib/apis/chat-apis.ts | 24 +++++++++ surfsense_web/lib/query-client/cache-keys.ts | 7 ++- .../stores/chats/active-chat.atom.ts | 39 --------------- 14 files changed, 90 insertions(+), 54 deletions(-) rename surfsense_web/{stores => atoms}/announcement.atom.ts (100%) rename surfsense_web/{stores => atoms}/chats/active-chat-ui.atom.ts (100%) create mode 100644 surfsense_web/atoms/chats/queries/active-chat.atom.ts rename surfsense_web/{stores/chats => atoms/chats/queries}/active-search-space-chats.atom.ts (88%) rename surfsense_web/{stores/seach-space => atoms/seach-spaces}/active-seach-space.atom.ts (100%) delete mode 100644 surfsense_web/stores/chats/active-chat.atom.ts 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 22b3bba77..24be65cce 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 @@ -51,7 +51,7 @@ import { } from "@/components/ui/select"; import { cn } from "@/lib/utils"; import { useAtomValue } from "jotai"; -import { activeSearchSpaceChatsAtom } from "@/stores/chats/active-search-space-chats.atom"; +import { activeSearchSpaceChatsAtom } from "@/atoms/chats/queries/active-search-space-chats.atom"; export interface Chat { created_at: string; @@ -129,8 +129,6 @@ export default function ChatsPageClient({ searchSpaceId }: ChatsPageClientProps) useEffect(() => { let result = [...(chats || [])]; - console.log("chats", chats); - // Filter by search term if (searchQuery) { const query = searchQuery.toLowerCase(); 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 3ad1e94b5..b1526a3ad 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 "@/stores/chats/active-chat.atom"; -import { chatUIAtom } from "@/stores/chats/active-chat-ui.atom"; -import { activeSearchSpaceIdAtom } from "@/stores/seach-space/active-seach-space.atom"; +import { activeChatIdAtom } from "@/atoms/chats/queries/active-chat.atom"; +import { chatUIAtom } from "@/atoms/chats/active-chat-ui.atom"; +import { activeSearchSpaceIdAtom } from "@/atoms/seach-spaces/active-seach-space.atom"; export function DashboardClientLayout({ children, diff --git a/surfsense_web/stores/announcement.atom.ts b/surfsense_web/atoms/announcement.atom.ts similarity index 100% rename from surfsense_web/stores/announcement.atom.ts rename to surfsense_web/atoms/announcement.atom.ts diff --git a/surfsense_web/stores/chats/active-chat-ui.atom.ts b/surfsense_web/atoms/chats/active-chat-ui.atom.ts similarity index 100% rename from surfsense_web/stores/chats/active-chat-ui.atom.ts rename to surfsense_web/atoms/chats/active-chat-ui.atom.ts diff --git a/surfsense_web/atoms/chats/queries/active-chat.atom.ts b/surfsense_web/atoms/chats/queries/active-chat.atom.ts new file mode 100644 index 000000000..48f650768 --- /dev/null +++ b/surfsense_web/atoms/chats/queries/active-chat.atom.ts @@ -0,0 +1,50 @@ +import { atom } from "jotai"; +import { atomWithQuery } from "jotai-tanstack-query"; +import type { ChatDetails } from "@/app/dashboard/[search_space_id]/chats/chats-client"; +import type { PodcastItem } from "@/app/dashboard/[search_space_id]/podcasts/podcasts-client"; +import { fetchChatDetails } from "@/lib/apis/chat-apis"; +import { getPodcastByChatId } from "@/lib/apis/podcast-apis"; +import { cacheKeys } from "@/lib/query-client/cache-keys"; + +type ActiveChatState = { + chatId: string | null; + chatDetails: ChatDetails | null; + podcast: PodcastItem | null; +}; + +export const activeChatIdAtom = atom(null); + +export const activeChatAtom = atomWithQuery((get) => { + const activeChatId = get(activeChatIdAtom); + const authToken = localStorage.getItem("surfsense_bearer_token"); + + if (!activeChatId) { + return { + queryKey: [], + enabled: false, + queryFn: async () => { + return { chatId: null, chatDetails: null, podcast: null }; + }, + }; + } + + return { + queryKey: cacheKeys.activeSearchSpace.activeChat(activeChatId), + enabled: !!activeChatId && !!authToken, + queryFn: async () => { + if (!authToken) { + throw new Error("No authentication token found"); + } + if (!activeChatId) { + throw new Error("No active chat id found"); + } + + const [podcast, chatDetails] = await Promise.all([ + getPodcastByChatId(activeChatId, authToken), + fetchChatDetails(activeChatId, authToken), + ]); + + return { chatId: activeChatId, chatDetails, podcast }; + }, + }; +}); diff --git a/surfsense_web/stores/chats/active-search-space-chats.atom.ts b/surfsense_web/atoms/chats/queries/active-search-space-chats.atom.ts similarity index 88% rename from surfsense_web/stores/chats/active-search-space-chats.atom.ts rename to surfsense_web/atoms/chats/queries/active-search-space-chats.atom.ts index df5dd2dcd..0b8b30eb0 100644 --- a/surfsense_web/stores/chats/active-search-space-chats.atom.ts +++ b/surfsense_web/atoms/chats/queries/active-search-space-chats.atom.ts @@ -1,6 +1,6 @@ import { atomWithQuery } from "jotai-tanstack-query"; import { fetchChatsBySearchSpace } from "@/lib/apis/chat-apis"; -import { activeSearchSpaceIdAtom } from "../seach-space/active-seach-space.atom"; +import { activeSearchSpaceIdAtom } from "../../seach-spaces/active-seach-space.atom"; export const activeSearchSpaceChatsAtom = atomWithQuery((get) => { const searchSpaceId = get(activeSearchSpaceIdAtom); diff --git a/surfsense_web/stores/seach-space/active-seach-space.atom.ts b/surfsense_web/atoms/seach-spaces/active-seach-space.atom.ts similarity index 100% rename from surfsense_web/stores/seach-space/active-seach-space.atom.ts rename to surfsense_web/atoms/seach-spaces/active-seach-space.atom.ts diff --git a/surfsense_web/components/announcement-banner.tsx b/surfsense_web/components/announcement-banner.tsx index c8ac05def..cbc48b444 100644 --- a/surfsense_web/components/announcement-banner.tsx +++ b/surfsense_web/components/announcement-banner.tsx @@ -3,7 +3,7 @@ import { useAtom } from "jotai"; import { ExternalLink, Info, X } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { announcementDismissedAtom } from "@/stores/announcement.atom"; +import { announcementDismissedAtom } from "@/atoms/announcement.atom"; export function AnnouncementBanner() { const [isDismissed, setIsDismissed] = useAtom(announcementDismissedAtom); diff --git a/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx b/surfsense_web/components/chat/ChatPanel/ChatPanelContainer.tsx index 172e85334..a412f99a8 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/chats/active-chat.atom"; -import { chatUIAtom } from "@/stores/chats/active-chat-ui.atom"; +import { activeChatAtom, activeChatIdAtom } from "@/atoms/chats/queries/active-chat.atom"; +import { chatUIAtom } from "@/atoms/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 bb88935f2..ca220856d 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/chats/active-chat.atom"; -import { chatUIAtom } from "@/stores/chats/active-chat-ui.atom"; +import { activeChatAtom } from "@/atoms/chats/queries/active-chat.atom"; +import { chatUIAtom } from "@/atoms/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 b67918a9a..175520d39 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/chats/active-chat.atom"; +import { activeChatAtom } from "@/atoms/chats/queries/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 4ae8a8feb..ff3076744 100644 --- a/surfsense_web/lib/apis/chat-apis.ts +++ b/surfsense_web/lib/apis/chat-apis.ts @@ -54,3 +54,27 @@ export const fetchChatsBySearchSpace = async ( return null; } }; + + +export const deleteChat = async (chatId: number, authToken: string) => { + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL}/api/v1/chats/${chatId}`, + { + method: "DELETE", + headers: { + Authorization: `Bearer ${authToken}`, + }, + } + ); + + if (!response.ok) { + throw new Error(`Failed to delete chat: ${response.statusText}`); + } + + return true; + } catch (err) { + console.error("Error deleting chat:", err); + return false; + } +}; diff --git a/surfsense_web/lib/query-client/cache-keys.ts b/surfsense_web/lib/query-client/cache-keys.ts index 0b66f1450..335125bb8 100644 --- a/surfsense_web/lib/query-client/cache-keys.ts +++ b/surfsense_web/lib/query-client/cache-keys.ts @@ -1,4 +1,7 @@ export const cacheKeys = { - activeChat: (chatId: string) => ["activeChat", chatId], - activeSearchSpaceChats: (searchSpaceId: string) => ["activeSearchSpaceChats", searchSpaceId], + activeSearchSpace: { + chats : (searchSpaceId: string) => ["active-search-space", "chats", searchSpaceId] as const, + activeChat : (chatId: string) => ["active-search-space", "active-chat", chatId] as const, + deleteChat : ( searchSpaceId: string, chatId: string) => ["active-search-space", "chats", searchSpaceId, "delete", chatId] as const, + }, }; diff --git a/surfsense_web/stores/chats/active-chat.atom.ts b/surfsense_web/stores/chats/active-chat.atom.ts deleted file mode 100644 index a0d40a96c..000000000 --- a/surfsense_web/stores/chats/active-chat.atom.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { atom } from "jotai"; -import { atomWithQuery } from "jotai-tanstack-query"; -import type { ChatDetails } from "@/app/dashboard/[search_space_id]/chats/chats-client"; -import type { PodcastItem } from "@/app/dashboard/[search_space_id]/podcasts/podcasts-client"; -import { fetchChatDetails } from "@/lib/apis/chat-apis"; -import { getPodcastByChatId } from "@/lib/apis/podcast-apis"; - -type ActiveChatState = { - chatId: string | null; - chatDetails: ChatDetails | null; - podcast: PodcastItem | null; -}; - -export const activeChatIdAtom = atom(null); - -export const activeChatAtom = atomWithQuery((get) => { - const activeChatId = get(activeChatIdAtom); - const authToken = localStorage.getItem("surfsense_bearer_token"); - - return { - queryKey: ["activeChat", activeChatId], - enabled: !!activeChatId && !!authToken, - queryFn: async () => { - if (!authToken) { - throw new Error("No authentication token found"); - } - if (!activeChatId) { - throw new Error("No active chat id found"); - } - - const [podcast, chatDetails] = await Promise.all([ - getPodcastByChatId(activeChatId, authToken), - fetchChatDetails(activeChatId, authToken), - ]); - - return { chatId: activeChatId, chatDetails, podcast }; - }, - }; -});