mirror of https://github.com/buster-so/buster.git
add to collection dropdown
This commit is contained in:
parent
95805195e0
commit
41616d98b6
|
@ -74,15 +74,8 @@ export const updateChatMessageFeedback = async ({
|
||||||
return mainApi.put(`/messages/${message_id}`, params).then((res) => res.data);
|
return mainApi.put(`/messages/${message_id}`, params).then((res) => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const duplicateChat = async ({
|
export const duplicateChat = async ({ id }: { id: string }): Promise<BusterChat> => {
|
||||||
id,
|
return mainApi.post(`${CHATS_BASE}/duplicate`, { id }).then((res) => res.data);
|
||||||
message_id
|
|
||||||
}: {
|
|
||||||
id: string;
|
|
||||||
/** The message ID to start the duplication from */
|
|
||||||
message_id: string;
|
|
||||||
}): Promise<BusterChat> => {
|
|
||||||
return mainApi.post(`${CHATS_BASE}/duplicate`, { id, message_id }).then((res) => res.data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const startChatFromAsset = async ({
|
export const startChatFromAsset = async ({
|
||||||
|
|
|
@ -257,6 +257,8 @@ export const useAddDashboardToCollection = () => {
|
||||||
const mutationFn = useMemoizedFn(
|
const mutationFn = useMemoizedFn(
|
||||||
async (variables: { dashboardIds: string[]; collectionIds: string[] }) => {
|
async (variables: { dashboardIds: string[]; collectionIds: string[] }) => {
|
||||||
const { dashboardIds, collectionIds } = variables;
|
const { dashboardIds, collectionIds } = variables;
|
||||||
|
console.log('dashboardIds', dashboardIds);
|
||||||
|
console.log('collectionIds', collectionIds);
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
collectionIds.map((collectionId) =>
|
collectionIds.map((collectionId) =>
|
||||||
addAssetToCollection({
|
addAssetToCollection({
|
||||||
|
|
|
@ -7,48 +7,57 @@ import {
|
||||||
useAddDashboardToCollection,
|
useAddDashboardToCollection,
|
||||||
useRemoveDashboardFromCollection
|
useRemoveDashboardFromCollection
|
||||||
} from '@/api/buster_rest/dashboards';
|
} from '@/api/buster_rest/dashboards';
|
||||||
|
import uniq from 'lodash/uniq';
|
||||||
|
|
||||||
export const SaveDashboardToCollectionButton: React.FC<{
|
export const SaveDashboardToCollectionButton: React.FC<{
|
||||||
dashboardIds: string[];
|
dashboardIds: string[];
|
||||||
buttonType?: 'ghost' | 'default';
|
buttonType?: 'ghost' | 'default';
|
||||||
useText?: boolean;
|
useText?: boolean;
|
||||||
}> = React.memo(({ dashboardIds, buttonType = 'ghost', useText = false }) => {
|
selectedCollections: string[];
|
||||||
const { openInfoMessage } = useBusterNotifications();
|
}> = React.memo(
|
||||||
|
({
|
||||||
|
dashboardIds,
|
||||||
|
buttonType = 'ghost',
|
||||||
|
useText = false,
|
||||||
|
selectedCollections: selectedCollectionsProp
|
||||||
|
}) => {
|
||||||
|
const { openInfoMessage } = useBusterNotifications();
|
||||||
|
|
||||||
const [selectedCollections, setSelectedCollections] = useState<
|
const [selectedCollections, setSelectedCollections] =
|
||||||
Parameters<typeof SaveToCollectionsDropdown>[0]['selectedCollections']
|
useState<Parameters<typeof SaveToCollectionsDropdown>[0]['selectedCollections']>(
|
||||||
>([]);
|
selectedCollectionsProp
|
||||||
const { mutateAsync: addDashboardToCollection } = useAddDashboardToCollection();
|
);
|
||||||
const { mutateAsync: removeDashboardFromCollection } = useRemoveDashboardFromCollection();
|
const { mutateAsync: addDashboardToCollection } = useAddDashboardToCollection();
|
||||||
|
const { mutateAsync: removeDashboardFromCollection } = useRemoveDashboardFromCollection();
|
||||||
|
|
||||||
const onSaveToCollection = useMemoizedFn(async (collectionIds: string[]) => {
|
const onSaveToCollection = useMemoizedFn(async (collectionIds: string[]) => {
|
||||||
setSelectedCollections(collectionIds);
|
setSelectedCollections((prev) => uniq([...prev, ...collectionIds]));
|
||||||
await addDashboardToCollection({
|
await addDashboardToCollection({
|
||||||
dashboardIds,
|
dashboardIds,
|
||||||
collectionIds
|
collectionIds
|
||||||
|
});
|
||||||
|
|
||||||
|
openInfoMessage('Dashboards saved to collections');
|
||||||
});
|
});
|
||||||
|
|
||||||
openInfoMessage('Dashboards saved to collections');
|
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
||||||
});
|
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
|
||||||
|
await removeDashboardFromCollection({
|
||||||
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
dashboardIds,
|
||||||
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
|
collectionIds: [collectionId]
|
||||||
|
});
|
||||||
await removeDashboardFromCollection({
|
openInfoMessage('Dashboards removed from collections');
|
||||||
dashboardIds,
|
|
||||||
collectionIds: [collectionId]
|
|
||||||
});
|
});
|
||||||
openInfoMessage('Dashboards removed from collections');
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SaveToCollectionsDropdown
|
<SaveToCollectionsDropdown
|
||||||
onSaveToCollection={onSaveToCollection}
|
onSaveToCollection={onSaveToCollection}
|
||||||
onRemoveFromCollection={onRemoveFromCollection}
|
onRemoveFromCollection={onRemoveFromCollection}
|
||||||
selectedCollections={selectedCollections}>
|
selectedCollections={selectedCollections}>
|
||||||
<CollectionButton buttonType={buttonType} useText={useText} />
|
<CollectionButton buttonType={buttonType} useText={useText} />
|
||||||
</SaveToCollectionsDropdown>
|
</SaveToCollectionsDropdown>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
SaveDashboardToCollectionButton.displayName = 'SaveDashboardToCollectionButton';
|
SaveDashboardToCollectionButton.displayName = 'SaveDashboardToCollectionButton';
|
||||||
|
|
|
@ -125,7 +125,10 @@ export const useSaveToCollectionsDropdownContent = ({
|
||||||
onRemoveFromCollection(collection.id);
|
onRemoveFromCollection(collection.id);
|
||||||
} else {
|
} else {
|
||||||
const allCollectionsAndSelected = selectedCollections.map((id) => id).concat(collection.id);
|
const allCollectionsAndSelected = selectedCollections.map((id) => id).concat(collection.id);
|
||||||
onSaveToCollection(allCollectionsAndSelected);
|
const differenceFromSelectedCollections = allCollectionsAndSelected.filter(
|
||||||
|
(id) => !selectedCollections.some((selectedId) => selectedId === id)
|
||||||
|
);
|
||||||
|
onSaveToCollection(differenceFromSelectedCollections);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,7 @@ export const ChatMessageOptions: React.FC<{
|
||||||
'You are about to duplicate this chat from this message. This will create a new chat with the same messages. Do you want to continue?',
|
'You are about to duplicate this chat from this message. This will create a new chat with the same messages. Do you want to continue?',
|
||||||
onOk: async () => {
|
onOk: async () => {
|
||||||
const res = await duplicateChat({
|
const res = await duplicateChat({
|
||||||
id: chatId,
|
id: chatId
|
||||||
message_id: messageId
|
|
||||||
});
|
});
|
||||||
await timeout(100);
|
await timeout(100);
|
||||||
await onChangePage({
|
await onChangePage({
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { timeout } from '@/lib';
|
||||||
import { BusterRoutes } from '@/routes';
|
import { BusterRoutes } from '@/routes';
|
||||||
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
||||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||||
|
import { assetParamsToRoute } from '@/lib/assets';
|
||||||
|
|
||||||
export const ChatContainerHeaderDropdown: React.FC<{
|
export const ChatContainerHeaderDropdown: React.FC<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
@ -18,6 +19,8 @@ export const ChatContainerHeaderDropdown: React.FC<{
|
||||||
const { mutate: deleteChat, isPending: isDeleting } = useDeleteChat();
|
const { mutate: deleteChat, isPending: isDeleting } = useDeleteChat();
|
||||||
const { mutateAsync: duplicateChat, isPending: isDuplicating } = useDuplicateChat();
|
const { mutateAsync: duplicateChat, isPending: isDuplicating } = useDuplicateChat();
|
||||||
const currentMessageId = useChatIndividualContextSelector((state) => state.currentMessageId);
|
const currentMessageId = useChatIndividualContextSelector((state) => state.currentMessageId);
|
||||||
|
const selectedFileId = useChatIndividualContextSelector((state) => state.selectedFileId);
|
||||||
|
const selectedFileType = useChatIndividualContextSelector((state) => state.selectedFileType);
|
||||||
|
|
||||||
const menuItem: DropdownItems = useMemo(() => {
|
const menuItem: DropdownItems = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
|
@ -45,15 +48,21 @@ export const ChatContainerHeaderDropdown: React.FC<{
|
||||||
loading: isDuplicating,
|
loading: isDuplicating,
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
if (chatId) {
|
if (chatId) {
|
||||||
duplicateChat(
|
const res = await duplicateChat({ id: chatId });
|
||||||
{ id: chatId, message_id: currentMessageId },
|
await timeout(100);
|
||||||
{
|
if (selectedFileType && selectedFileId) {
|
||||||
onSuccess: (chat) => {
|
const route = assetParamsToRoute({
|
||||||
onChangePage({ route: BusterRoutes.APP_CHAT_ID, chatId: chat.id });
|
assetId: selectedFileId,
|
||||||
openSuccessMessage('Chat duplicated');
|
chatId: res.id,
|
||||||
}
|
type: selectedFileType
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
if (route) await onChangePage(route);
|
||||||
|
} else {
|
||||||
|
await onChangePage({ route: BusterRoutes.APP_CHAT_ID, chatId: res.id });
|
||||||
|
}
|
||||||
|
|
||||||
|
openSuccessMessage('Chat duplicated');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const DashboardContainerHeaderButtons: React.FC<FileContainerButtonsProps
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FileButtonContainer>
|
<FileButtonContainer>
|
||||||
<SaveToCollectionButton />
|
<SaveToCollectionButton dashboardId={dashboardId} />
|
||||||
{isEffectiveOwner && <ShareDashboardButton dashboardId={dashboardId} />}
|
{isEffectiveOwner && <ShareDashboardButton dashboardId={dashboardId} />}
|
||||||
{isEditor && !isViewingOldVersion && <AddContentToDashboardButton />}
|
{isEditor && !isViewingOldVersion && <AddContentToDashboardButton />}
|
||||||
<DashboardThreeDotMenu
|
<DashboardThreeDotMenu
|
||||||
|
@ -54,9 +54,18 @@ export const DashboardContainerHeaderButtons: React.FC<FileContainerButtonsProps
|
||||||
|
|
||||||
DashboardContainerHeaderButtons.displayName = 'DashboardContainerHeaderButtons';
|
DashboardContainerHeaderButtons.displayName = 'DashboardContainerHeaderButtons';
|
||||||
|
|
||||||
const SaveToCollectionButton = React.memo(() => {
|
const SaveToCollectionButton = React.memo(({ dashboardId }: { dashboardId: string }) => {
|
||||||
const selectedFileId = useChatIndividualContextSelector((x) => x.selectedFileId)!;
|
const { data: collections } = useGetDashboard(
|
||||||
return <SaveDashboardToCollectionButton dashboardIds={[selectedFileId]} />;
|
{ id: dashboardId },
|
||||||
|
{ select: (x) => x.collections?.map((x) => x.id) }
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SaveDashboardToCollectionButton
|
||||||
|
dashboardIds={[dashboardId]}
|
||||||
|
selectedCollections={collections || []}
|
||||||
|
/>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
SaveToCollectionButton.displayName = 'SaveToCollectionButton';
|
SaveToCollectionButton.displayName = 'SaveToCollectionButton';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue