delete chat

This commit is contained in:
Nate Kelley 2025-04-02 10:42:54 -06:00
parent c85d51b7d2
commit bb49686be9
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
5 changed files with 153 additions and 53 deletions

View File

@ -16,6 +16,13 @@ import { updateChatToIChat } from '@/lib/chat';
import { useMemo } from 'react';
import last from 'lodash/last';
import { prefetchGetMetricDataClient } from '../metrics/queryRequests';
import { useBusterNotifications } from '@/context/BusterNotifications';
import { useGetUserFavorites } from '../users/queryRequests';
import {
useAddAssetToCollection,
useRemoveAssetFromCollection
} from '../collections/queryRequests';
import { collectionQueryKeys } from '@/api/query_keys/collection';
export const useGetListChats = (
filters?: Omit<Parameters<typeof getListChats>[0], 'page_token' | 'page_size'>
@ -142,8 +149,30 @@ export const useUpdateChat = () => {
export const useDeleteChat = () => {
const queryClient = useQueryClient();
const { openConfirmModal } = useBusterNotifications();
const mutationFn = useMemoizedFn(
async ({
useConfirmModal = true,
data
}: {
data: Parameters<typeof deleteChat>[0];
useConfirmModal?: boolean;
}) => {
const method = () => deleteChat(data);
if (useConfirmModal) {
return await openConfirmModal({
title: 'Delete Chat',
content: 'Are you sure you want to delete this chat?',
onOk: method
});
}
return method();
}
);
return useMutation({
mutationFn: deleteChat,
mutationFn,
onSuccess(data, variables, context) {
queryClient.invalidateQueries({
queryKey: queryKeys.chatsGetList().queryKey
@ -193,3 +222,72 @@ export const useDuplicateChat = () => {
mutationFn: duplicateChat
});
};
export const useSaveChatToCollections = () => {
const queryClient = useQueryClient();
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
const { mutateAsync: addAssetToCollection } = useAddAssetToCollection();
const saveChatToCollection = useMemoizedFn(
async ({ chatIds, collectionIds }: { chatIds: string[]; collectionIds: string[] }) => {
await Promise.all(
collectionIds.map((collectionId) =>
addAssetToCollection({
id: collectionId,
assets: chatIds.map((chatId) => ({ id: chatId, type: 'chat' }))
})
)
);
}
);
return useMutation({
mutationFn: saveChatToCollection,
onSuccess: (_, { collectionIds }) => {
const collectionIsInFavorites = userFavorites.some((f) => {
return collectionIds.includes(f.id);
});
if (collectionIsInFavorites) refreshFavoritesList();
queryClient.invalidateQueries({
queryKey: collectionIds.map(
(id) => collectionQueryKeys.collectionsGetCollection(id).queryKey
)
});
}
});
};
export const useRemoveChatFromCollections = () => {
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
const { mutateAsync: removeAssetFromCollection } = useRemoveAssetFromCollection();
const queryClient = useQueryClient();
const removeChatFromCollection = useMemoizedFn(
async ({ chatIds, collectionIds }: { chatIds: string[]; collectionIds: string[] }) => {
await Promise.all(
collectionIds.map((collectionId) =>
removeAssetFromCollection({
id: collectionId,
assets: chatIds.map((chatId) => ({ id: chatId, type: 'chat' }))
})
)
);
}
);
return useMutation({
mutationFn: removeChatFromCollection,
onSuccess: (_, { collectionIds, chatIds }) => {
const collectionIsInFavorites = userFavorites.some((f) => {
return collectionIds.includes(f.id);
});
if (collectionIsInFavorites) refreshFavoritesList();
queryClient.invalidateQueries({
queryKey: collectionIds.map(
(id) => collectionQueryKeys.collectionsGetCollection(id).queryKey
)
});
}
});
};

View File

@ -61,20 +61,17 @@ export const updateChat = async ({
};
export const deleteChat = async (data: string[]): Promise<void> => {
return mainApi.delete(`${CHATS_BASE}`, { data }).then((res) => res.data);
const stringifiedData = JSON.stringify(data);
return mainApi.delete(`${CHATS_BASE}`, { data: stringifiedData }).then((res) => res.data);
};
export const duplicateChat = async ({
id,
message_id,
share_with_same_people
message_id
}: {
id: string;
/** The message ID to start the duplication from */
message_id: string;
share_with_same_people: boolean;
}): Promise<BusterChat> => {
return mainApi
.post(`${CHATS_BASE}/duplicate`, { id, message_id, share_with_same_people })
.then((res) => res.data);
return mainApi.post(`${CHATS_BASE}/duplicate`, { id, message_id }).then((res) => res.data);
};

View File

@ -104,7 +104,7 @@ export const updateCollectionShare = async ({
export const addAssetToCollection = async (params: {
id: string;
assets: {
type: 'metric' | 'dashboard';
type: 'metric' | 'dashboard' | 'chat';
id: string;
}[];
}) => {

View File

@ -10,10 +10,10 @@ import { SaveToCollectionsDropdown } from '@/components/features/dropdowns/SaveT
import { useBusterNotifications } from '@/context/BusterNotifications';
import { ASSET_ICONS } from '@/components/features/config/assetIcons';
import {
useDeleteMetric,
useRemoveMetricFromCollection,
useSaveMetricToCollections
} from '@/api/buster_rest/metrics';
useDeleteChat,
useSaveChatToCollections,
useRemoveChatFromCollections
} from '@/api/buster_rest/chats';
import {
useAddUserFavorite,
useDeleteUserFavorite,
@ -36,11 +36,6 @@ export const ChatSelectedOptionPopup: React.FC<{
selectedRowKeys={selectedRowKeys}
onSelectChange={onSelectChange}
/>,
<DashboardButton
key="dashboard"
selectedRowKeys={selectedRowKeys}
onSelectChange={onSelectChange}
/>,
<DeleteButton
key="delete"
@ -63,8 +58,8 @@ const CollectionsButton: React.FC<{
onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => {
const { openInfoMessage } = useBusterNotifications();
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollections();
const { mutateAsync: removeMetricFromCollection } = useRemoveMetricFromCollection();
const { mutateAsync: saveChatToCollection } = useSaveChatToCollections();
const { mutateAsync: removeChatFromCollection } = useRemoveChatFromCollections();
const [selectedCollections, setSelectedCollections] = useState<
Parameters<typeof SaveToCollectionsDropdown>[0]['selectedCollections']
@ -72,20 +67,20 @@ const CollectionsButton: React.FC<{
const onSaveToCollection = useMemoizedFn(async (collectionIds: string[]) => {
setSelectedCollections(collectionIds);
await saveMetricToCollection({
metricIds: selectedRowKeys,
await saveChatToCollection({
chatIds: selectedRowKeys,
collectionIds
});
openInfoMessage('Metrics saved to collections');
openInfoMessage('Chats saved to collections');
});
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
await removeMetricFromCollection({
metricIds: selectedRowKeys,
await removeChatFromCollection({
chatIds: selectedRowKeys,
collectionIds: [collectionId]
});
openInfoMessage('Metrics removed from collections');
openInfoMessage('Chats removed from collections');
});
return (
@ -98,25 +93,14 @@ const CollectionsButton: React.FC<{
);
};
const DashboardButton: React.FC<{
selectedRowKeys: string[];
onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => {
return (
<Dropdown items={[{ label: 'Dashboard', value: 'dashboard' }]}>
<Button prefix={<ASSET_ICONS.dashboards />}>Dashboard</Button>
</Dropdown>
);
};
const DeleteButton: React.FC<{
selectedRowKeys: string[];
onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => {
const { mutateAsync: deleteMetric } = useDeleteMetric();
}> = React.memo(({ selectedRowKeys, onSelectChange }) => {
const { mutateAsync: deleteChat } = useDeleteChat();
const onDeleteClick = async () => {
await deleteMetric({ ids: selectedRowKeys });
await deleteChat({ data: selectedRowKeys });
onSelectChange([]);
};
@ -125,12 +109,14 @@ const DeleteButton: React.FC<{
Delete
</Button>
);
};
});
DeleteButton.displayName = 'DeleteButton';
const ThreeDotButton: React.FC<{
selectedRowKeys: string[];
onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => {
}> = React.memo(({ selectedRowKeys, onSelectChange }) => {
const { mutateAsync: removeUserFavorite, isPending: removingFromFavorites } =
useDeleteUserFavorite();
const { mutateAsync: addUserFavorite, isPending: addingToFavorites } = useAddUserFavorite();
@ -148,7 +134,7 @@ const ThreeDotButton: React.FC<{
const name = userFavorites?.find((f) => f.id === id)?.name || '';
return addUserFavorite({
id,
asset_type: ShareAssetType.METRIC,
asset_type: ShareAssetType.CHAT,
name
});
})
@ -171,4 +157,6 @@ const ThreeDotButton: React.FC<{
<Button prefix={<Dots />} />
</Dropdown>
);
};
});
ThreeDotButton.displayName = 'ThreeDotButton';

View File

@ -5,16 +5,18 @@ import { Copy, Trash, Pencil } from '@/components/ui/icons';
import { useDeleteChat, useDuplicateChat } from '@/api/buster_rest/chats';
import { CHAT_HEADER_TITLE_ID } from '../ChatHeaderTitle';
import { timeout } from '@/lib';
import { BusterRoutes, createBusterRoute } from '@/routes';
import { BusterRoutes } from '@/routes';
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
import { useBusterNotifications } from '@/context/BusterNotifications';
export const ChatContainerHeaderDropdown: React.FC<{
children: React.ReactNode;
}> = React.memo(({ children }) => {
const { openSuccessMessage } = useBusterNotifications();
const chatId = useChatIndividualContextSelector((state) => state.chatId);
const onChangePage = useAppLayoutContextSelector((s) => s.onChangePage);
const { mutate: deleteChat, isPending: isDeleting } = useDeleteChat();
const { mutate: duplicateChat } = useDuplicateChat();
const { mutateAsync: duplicateChat, isPending: isDuplicating } = useDuplicateChat();
const currentMessageId = useChatIndividualContextSelector((state) => state.currentMessageId);
const menuItem: DropdownItems = useMemo(() => {
@ -26,19 +28,34 @@ export const ChatContainerHeaderDropdown: React.FC<{
loading: isDeleting,
onClick: () =>
chatId &&
deleteChat([chatId], {
onSuccess: () => {
onChangePage({ route: BusterRoutes.APP_CHAT });
deleteChat(
{ data: [chatId] },
{
onSuccess: () => {
onChangePage({ route: BusterRoutes.APP_CHAT });
openSuccessMessage('Chat deleted');
}
}
})
)
},
{
label: 'Duplicate chat',
value: 'duplicate',
icon: <Copy />,
onClick: () =>
chatId &&
duplicateChat({ id: chatId, message_id: currentMessageId, share_with_same_people: false })
loading: isDuplicating,
onClick: async () => {
if (chatId) {
duplicateChat(
{ id: chatId, message_id: currentMessageId },
{
onSuccess: (chat) => {
onChangePage({ route: BusterRoutes.APP_CHAT_ID, chatId: chat.id });
openSuccessMessage('Chat duplicated');
}
}
);
}
}
},
{
label: 'Edit chat title',