refactor(site): convert archive agent callbacks to React Query mutations (#22542)

This commit is contained in:
Danielle Maywood
2026-03-03 11:03:59 +00:00
committed by GitHub
parent 517cb0ce73
commit c483bfa24f
3 changed files with 68 additions and 63 deletions
+2 -2
View File
@@ -876,10 +876,10 @@ const AgentDetail: FC = () => {
};
const handleArchiveAndDeleteWorkspaceAction = () => {
if (!agentId || isArchived) {
if (!agentId || isArchived || !workspaceId) {
return;
}
requestArchiveAndDeleteWorkspace(agentId);
requestArchiveAndDeleteWorkspace(agentId, workspaceId);
};
if (chatQuery.isLoading) {
+55 -57
View File
@@ -88,7 +88,10 @@ export interface AgentsOutletContext {
setChatErrorReason: (chatId: string, reason: string) => void;
clearChatErrorReason: (chatId: string) => void;
requestArchiveAgent: (chatId: string) => void;
requestArchiveAndDeleteWorkspace: (chatId: string) => void;
requestArchiveAndDeleteWorkspace: (
chatId: string,
workspaceId: string,
) => void;
isSidebarCollapsed: boolean;
onToggleSidebarCollapsed: () => void;
}
@@ -151,11 +154,40 @@ const AgentsPage: FC = () => {
const chatModelsQuery = useQuery(chatModels());
const chatModelConfigsQuery = useQuery(chatModelConfigs());
const createMutation = useMutation(createChat(queryClient));
const archiveMutation = useMutation(archiveChat(queryClient));
const deleteWorkspaceMutation = useMutation({
mutationFn: (workspaceId: string) => API.deleteWorkspace(workspaceId),
const archiveAgentMutation = useMutation({
...archiveChat(queryClient),
onSuccess: async (_data, chatId) => {
clearChatErrorReason(chatId);
await queryClient.invalidateQueries({ queryKey: chatKey(chatId) });
toast.success("Agent archived.");
},
onError: (error) => {
toast.error(getErrorMessage(error, "Failed to archive agent."));
},
});
const archiveAndDeleteMutation = useMutation({
mutationFn: async ({
chatId,
workspaceId,
}: {
chatId: string;
workspaceId: string;
}) => {
await API.archiveChat(chatId);
await API.deleteWorkspace(workspaceId);
return { chatId, workspaceId };
},
onSuccess: async ({ chatId }) => {
clearChatErrorReason(chatId);
await queryClient.invalidateQueries({ queryKey: chatsKey });
await queryClient.invalidateQueries({ queryKey: chatKey(chatId) });
toast.success("Agent archived.");
toast.success("Workspace deletion initiated.");
},
onError: (error) => {
toast.error(getErrorMessage(error, "Failed to archive agent."));
},
});
const [archivingChatId, setArchivingChatId] = useState<string | null>(null);
const [isConfigureAgentsDialogOpen, setConfigureAgentsDialogOpen] =
useState(false);
@@ -219,64 +251,30 @@ const AgentsPage: FC = () => {
});
}, []);
const chatList = chatsQuery.data ?? [];
const isArchiving =
archiveAgentMutation.isPending || archiveAndDeleteMutation.isPending;
const archivingChatId =
(archiveAgentMutation.isPending
? archiveAgentMutation.variables
: undefined) ??
(archiveAndDeleteMutation.isPending
? archiveAndDeleteMutation.variables?.chatId
: undefined);
const requestArchiveAgent = useCallback(
async (chatId: string) => {
if (archiveMutation.isPending) {
return;
}
setArchivingChatId(chatId);
try {
await archiveMutation.mutateAsync(chatId);
clearChatErrorReason(chatId);
await queryClient.invalidateQueries({ queryKey: chatKey(chatId) });
toast.success("Agent archived.");
} catch (error) {
toast.error(getErrorMessage(error, "Failed to archive agent."));
} finally {
setArchivingChatId(null);
(chatId: string) => {
if (!isArchiving) {
archiveAgentMutation.mutate(chatId);
}
},
[archiveMutation, queryClient, clearChatErrorReason],
[isArchiving, archiveAgentMutation],
);
const requestArchiveAndDeleteWorkspace = useCallback(
async (chatId: string) => {
if (archiveMutation.isPending || deleteWorkspaceMutation.isPending) {
return;
}
setArchivingChatId(chatId);
try {
await archiveMutation.mutateAsync(chatId);
clearChatErrorReason(chatId);
await queryClient.invalidateQueries({ queryKey: chatKey(chatId) });
toast.success("Agent archived.");
} catch (error) {
toast.error(getErrorMessage(error, "Failed to archive agent."));
return;
} finally {
setArchivingChatId(null);
}
const chat = chatList.find((c) => c.id === chatId);
if (chat?.workspace_id) {
try {
await deleteWorkspaceMutation.mutateAsync(chat.workspace_id);
toast.success("Workspace deletion initiated.");
} catch (error) {
toast.error(getErrorMessage(error, "Failed to delete workspace."));
}
(chatId: string, workspaceId: string) => {
if (!isArchiving) {
archiveAndDeleteMutation.mutate({ chatId, workspaceId });
}
},
[
archiveMutation,
deleteWorkspaceMutation,
queryClient,
clearChatErrorReason,
chatList,
],
[isArchiving, archiveAndDeleteMutation],
);
const handleToggleSidebarCollapsed = useCallback(
() => setIsSidebarCollapsed((prev) => !prev),
@@ -457,7 +455,7 @@ const AgentsPage: FC = () => {
onArchiveAndDeleteWorkspace={requestArchiveAndDeleteWorkspace}
onNewAgent={handleNewAgent}
isCreating={createMutation.isPending}
isArchiving={archiveMutation.isPending}
isArchiving={isArchiving}
archivingChatId={archivingChatId}
isLoading={chatsQuery.isLoading}
loadError={chatsQuery.isError ? chatsQuery.error : undefined}
+11 -4
View File
@@ -52,7 +52,7 @@ interface AgentsSidebarProps {
modelConfigs: readonly ChatModelConfig[];
logoUrl?: string;
onArchiveAgent: (chatId: string) => void;
onArchiveAndDeleteWorkspace: (chatId: string) => void;
onArchiveAndDeleteWorkspace: (chatId: string, workspaceId: string) => void;
onNewAgent: () => void;
isCreating: boolean;
isArchiving?: boolean;
@@ -266,7 +266,10 @@ interface ChatTreeContextValue {
readonly archivingChatId: string | null;
readonly toggleExpanded: (chatID: string) => void;
readonly onArchiveAgent: (chatId: string) => void;
readonly onArchiveAndDeleteWorkspace: (chatId: string) => void;
readonly onArchiveAndDeleteWorkspace: (
chatId: string,
workspaceId: string,
) => void;
}
const ChatTreeContext = createContext<ChatTreeContextValue | null>(null);
@@ -329,6 +332,7 @@ const ChatTreeNode = memo<ChatTreeNodeProps>(({ chat, isChildNode }) => {
const filesChangedLabel = `${changedFiles} ${
changedFiles === 1 ? "file" : "files"
}`;
const workspaceId = chat.workspace_id;
const isArchivingThisChat = isArchiving && archivingChatId === chat.id;
const isExpanded = normalizedSearch ? true : (expandedById[chatID] ?? false);
const isExecuting =
@@ -473,12 +477,15 @@ const ChatTreeNode = memo<ChatTreeNodeProps>(({ chat, isChildNode }) => {
<ArchiveIcon className="h-3.5 w-3.5" />
Archive agent
</DropdownMenuItem>
{chat.workspace_id && (
{workspaceId && (
<DropdownMenuItem
className="text-content-destructive focus:text-content-destructive"
disabled={isArchiving}
onSelect={() => onArchiveAndDeleteWorkspace(chat.id)}
onSelect={() =>
onArchiveAndDeleteWorkspace(chat.id, workspaceId)
}
>
{" "}
<Trash2Icon className="h-3.5 w-3.5" />
Archive & delete workspace
</DropdownMenuItem>