diff --git a/site/src/api/queries/chats.ts b/site/src/api/queries/chats.ts index 56a65fdd3f..1939002544 100644 --- a/site/src/api/queries/chats.ts +++ b/site/src/api/queries/chats.ts @@ -16,24 +16,112 @@ export const chat = (chatId: string) => ({ queryFn: () => API.getChat(chatId), }); -export const createChat = (queryClient: QueryClient) => ({ - mutationFn: (req: TypesGen.CreateChatRequest) => API.createChat(req), - onSuccess: () => { - void queryClient.invalidateQueries({ queryKey: chatsKey }); - }, -}); - export const archiveChat = (queryClient: QueryClient) => ({ mutationFn: (chatId: string) => API.archiveChat(chatId), - onSuccess: () => { - void queryClient.invalidateQueries({ queryKey: chatsKey }); + onMutate: async (chatId: string) => { + await queryClient.cancelQueries({ queryKey: chatsKey }); + await queryClient.cancelQueries({ queryKey: chatKey(chatId) }); + const previousChats = queryClient.getQueryData(chatsKey); + const previousChat = queryClient.getQueryData( + chatKey(chatId), + ); + queryClient.setQueryData(chatsKey, (old) => + old?.map((chat) => + chat.id === chatId ? { ...chat, archived: true } : chat, + ), + ); + if (previousChat) { + queryClient.setQueryData(chatKey(chatId), { + ...previousChat, + chat: { ...previousChat.chat, archived: true }, + }); + } + return { previousChats, previousChat }; + }, + onError: ( + _error: unknown, + chatId: string, + context: + | { + previousChats?: TypesGen.Chat[]; + previousChat?: TypesGen.ChatWithMessages; + } + | undefined, + ) => { + if (context?.previousChats) { + queryClient.setQueryData( + chatsKey, + context.previousChats, + ); + } + if (context?.previousChat) { + queryClient.setQueryData( + chatKey(chatId), + context.previousChat, + ); + } + }, + onSettled: async (_data: unknown, _error: unknown, chatId: string) => { + await queryClient.invalidateQueries({ queryKey: chatsKey }); + await queryClient.invalidateQueries({ queryKey: chatKey(chatId) }); }, }); export const unarchiveChat = (queryClient: QueryClient) => ({ mutationFn: (chatId: string) => API.unarchiveChat(chatId), - onSuccess: async () => { + onMutate: async (chatId: string) => { + await queryClient.cancelQueries({ queryKey: chatsKey }); + await queryClient.cancelQueries({ queryKey: chatKey(chatId) }); + const previousChats = queryClient.getQueryData(chatsKey); + const previousChat = queryClient.getQueryData( + chatKey(chatId), + ); + queryClient.setQueryData(chatsKey, (old) => + old?.map((chat) => + chat.id === chatId ? { ...chat, archived: false } : chat, + ), + ); + if (previousChat) { + queryClient.setQueryData(chatKey(chatId), { + ...previousChat, + chat: { ...previousChat.chat, archived: false }, + }); + } + return { previousChats, previousChat }; + }, + onError: ( + _error: unknown, + chatId: string, + context: + | { + previousChats?: TypesGen.Chat[]; + previousChat?: TypesGen.ChatWithMessages; + } + | undefined, + ) => { + if (context?.previousChats) { + queryClient.setQueryData( + chatsKey, + context.previousChats, + ); + } + if (context?.previousChat) { + queryClient.setQueryData( + chatKey(chatId), + context.previousChat, + ); + } + }, + onSettled: async (_data: unknown, _error: unknown, chatId: string) => { await queryClient.invalidateQueries({ queryKey: chatsKey }); + await queryClient.invalidateQueries({ queryKey: chatKey(chatId) }); + }, +}); + +export const createChat = (queryClient: QueryClient) => ({ + mutationFn: (req: TypesGen.CreateChatRequest) => API.createChat(req), + onSuccess: () => { + void queryClient.invalidateQueries({ queryKey: chatsKey }); }, }); diff --git a/site/src/pages/AgentsPage/AgentsPage.tsx b/site/src/pages/AgentsPage/AgentsPage.tsx index a699ab3b3c..bb852d4ac7 100644 --- a/site/src/pages/AgentsPage/AgentsPage.tsx +++ b/site/src/pages/AgentsPage/AgentsPage.tsx @@ -158,14 +158,15 @@ const AgentsPage: FC = () => { const chatModelsQuery = useQuery(chatModels()); const chatModelConfigsQuery = useQuery(chatModelConfigs()); const createMutation = useMutation(createChat(queryClient)); + const archiveChatBase = archiveChat(queryClient); const archiveAgentMutation = useMutation({ - ...archiveChat(queryClient), - onSuccess: async (_data, chatId) => { + ...archiveChatBase, + onSuccess: (_data, chatId) => { clearChatErrorReason(chatId); - await queryClient.invalidateQueries({ queryKey: chatKey(chatId) }); toast.success("Agent archived."); }, - onError: (error) => { + onError: (error, chatId, context) => { + archiveChatBase.onError(error, chatId, context); toast.error(getErrorMessage(error, "Failed to archive agent.")); }, }); @@ -192,17 +193,17 @@ const AgentsPage: FC = () => { toast.error(getErrorMessage(error, "Failed to archive agent.")); }, }); + const unarchiveChatBase = unarchiveChat(queryClient); const unarchiveAgentMutation = useMutation({ - ...unarchiveChat(queryClient), - onSuccess: async (_data, chatId) => { - await queryClient.invalidateQueries({ queryKey: chatKey(chatId) }); + ...unarchiveChatBase, + onSuccess: () => { toast.success("Agent unarchived."); }, - onError: (error) => { + onError: (error, chatId, context) => { + unarchiveChatBase.onError(error, chatId, context); toast.error(getErrorMessage(error, "Failed to unarchive agent.")); }, }); - const [isConfigureAgentsDialogOpen, setConfigureAgentsDialogOpen] = useState(false); const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);