mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(site): add optimistic updates for chat archive/unarchive (#22622)
This commit is contained in:
@@ -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<TypesGen.Chat[]>(chatsKey);
|
||||
const previousChat = queryClient.getQueryData<TypesGen.ChatWithMessages>(
|
||||
chatKey(chatId),
|
||||
);
|
||||
queryClient.setQueryData<TypesGen.Chat[]>(chatsKey, (old) =>
|
||||
old?.map((chat) =>
|
||||
chat.id === chatId ? { ...chat, archived: true } : chat,
|
||||
),
|
||||
);
|
||||
if (previousChat) {
|
||||
queryClient.setQueryData<TypesGen.ChatWithMessages>(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<TypesGen.Chat[]>(
|
||||
chatsKey,
|
||||
context.previousChats,
|
||||
);
|
||||
}
|
||||
if (context?.previousChat) {
|
||||
queryClient.setQueryData<TypesGen.ChatWithMessages>(
|
||||
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<TypesGen.Chat[]>(chatsKey);
|
||||
const previousChat = queryClient.getQueryData<TypesGen.ChatWithMessages>(
|
||||
chatKey(chatId),
|
||||
);
|
||||
queryClient.setQueryData<TypesGen.Chat[]>(chatsKey, (old) =>
|
||||
old?.map((chat) =>
|
||||
chat.id === chatId ? { ...chat, archived: false } : chat,
|
||||
),
|
||||
);
|
||||
if (previousChat) {
|
||||
queryClient.setQueryData<TypesGen.ChatWithMessages>(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<TypesGen.Chat[]>(
|
||||
chatsKey,
|
||||
context.previousChats,
|
||||
);
|
||||
}
|
||||
if (context?.previousChat) {
|
||||
queryClient.setQueryData<TypesGen.ChatWithMessages>(
|
||||
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 });
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user