mirror of https://github.com/buster-so/buster.git
favorites update
This commit is contained in:
parent
6ebb364101
commit
152bd1242f
|
@ -101,7 +101,9 @@ export const useAddUserFavorite = () => {
|
|||
mutationFn: createUserFavorite,
|
||||
onMutate: (params) => {
|
||||
queryClient.setQueryData(queryKeys.favoritesGetList.queryKey, (prev) => {
|
||||
return [params, ...(prev || [])];
|
||||
const prevIds = prev?.map((p) => p.id) || [];
|
||||
const dedupedAdd = params.filter((p) => !prevIds.includes(p.id));
|
||||
return [...dedupedAdd, ...(prev || [])];
|
||||
});
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
|
@ -116,7 +118,7 @@ export const useDeleteUserFavorite = () => {
|
|||
mutationFn: deleteUserFavorite,
|
||||
onMutate: (id) => {
|
||||
queryClient.setQueryData(queryKeys.favoritesGetList.queryKey, (prev) => {
|
||||
return prev?.filter((fav) => fav.id !== id);
|
||||
return prev?.filter((fav) => !id.includes(fav.id));
|
||||
});
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
|
|
|
@ -93,51 +93,31 @@ export const getUserFavorites_server = async () => {
|
|||
return serverFetch<BusterUserFavorite[]>(`/users/favorites`);
|
||||
};
|
||||
|
||||
export const createUserFavorite = async (payload: {
|
||||
id: string;
|
||||
asset_type: ShareAssetType;
|
||||
index?: number;
|
||||
name: string; //just used for the UI for optimistic update
|
||||
}) => {
|
||||
export const createUserFavorite = async (
|
||||
payload: {
|
||||
id: string;
|
||||
asset_type: ShareAssetType;
|
||||
index?: number;
|
||||
name: string; //just used for the UI for optimistic update
|
||||
}[]
|
||||
) => {
|
||||
return mainApi
|
||||
.post<BusterUserFavorite[]>(`/users/favorites`, payload)
|
||||
.then((response) => response.data);
|
||||
};
|
||||
|
||||
export const createUserFavorite_server = async (
|
||||
payload: Parameters<typeof createUserFavorite>[0]
|
||||
) => {
|
||||
return serverFetch<BusterUserFavorite[]>(`/users/favorites`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteUserFavorite = async (id: string) => {
|
||||
export const deleteUserFavorite = async (data: string[]) => {
|
||||
return mainApi
|
||||
.delete<BusterUserFavorite[]>(`/users/favorites/${id}`)
|
||||
.delete<BusterUserFavorite[]>(`/users/favorites`, { data })
|
||||
.then((response) => response.data);
|
||||
};
|
||||
|
||||
export const deleteUserFavorite_server = async (id: string) => {
|
||||
return serverFetch<BusterUserFavorite[]>(`/users/favorites/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
|
||||
export const updateUserFavorites = async (payload: string[]) => {
|
||||
return mainApi
|
||||
.put<BusterUserFavorite[]>(`/users/favorites`, payload)
|
||||
.then((response) => response.data);
|
||||
};
|
||||
|
||||
export const updateUserFavorites_server = async (payload: string[]) => {
|
||||
return serverFetch<BusterUserFavorite[]>(`/users/favorites`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
};
|
||||
|
||||
//USER LIST
|
||||
|
||||
export const getUserList = async (payload: {
|
||||
|
|
|
@ -19,8 +19,10 @@ export const assetTypeToIcon = (assetType: ShareAssetType) => {
|
|||
return ASSET_ICONS.dashboards;
|
||||
case ShareAssetType.COLLECTION:
|
||||
return ASSET_ICONS.collections;
|
||||
case ShareAssetType.CHAT:
|
||||
return ASSET_ICONS.chats;
|
||||
default:
|
||||
const _result: unknown = assetType;
|
||||
const _result: never = assetType;
|
||||
return ASSET_ICONS.metrics;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import { ShareAssetType } from '@/api/asset_interfaces/share';
|
||||
import {
|
||||
useAddUserFavorite,
|
||||
useDeleteUserFavorite,
|
||||
useGetUserFavorites
|
||||
} from '@/api/buster_rest/users';
|
||||
import { DropdownItems } from '@/components/ui/dropdown';
|
||||
import { Star, Xmark } from '@/components/ui/icons';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useThreeDotFavoritesOptions = ({
|
||||
itemIds,
|
||||
assetType,
|
||||
onFinish
|
||||
}: {
|
||||
itemIds: string[];
|
||||
assetType: ShareAssetType;
|
||||
onFinish: (ids: string[]) => void;
|
||||
}) => {
|
||||
const { mutateAsync: addUserFavorite } = useAddUserFavorite();
|
||||
const { mutateAsync: removeUserFavorite } = useDeleteUserFavorite();
|
||||
const { data: userFavorites } = useGetUserFavorites();
|
||||
|
||||
const dropdownOptions: DropdownItems = useMemo(
|
||||
() => [
|
||||
{
|
||||
label: 'Add to favorites',
|
||||
icon: <Star />,
|
||||
value: 'add-to-favorites',
|
||||
onClick: async () => {
|
||||
await addUserFavorite([
|
||||
...itemIds.map((id) => ({
|
||||
id,
|
||||
asset_type: assetType,
|
||||
name: userFavorites?.find((f) => f.id === id)?.name || ''
|
||||
}))
|
||||
]);
|
||||
onFinish(itemIds);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Remove from favorites',
|
||||
icon: <Xmark />,
|
||||
value: 'remove-from-favorites',
|
||||
onClick: async () => {
|
||||
await removeUserFavorite(itemIds);
|
||||
onFinish(itemIds);
|
||||
}
|
||||
}
|
||||
],
|
||||
[addUserFavorite, removeUserFavorite, itemIds, assetType, userFavorites]
|
||||
);
|
||||
|
||||
return dropdownOptions;
|
||||
};
|
|
@ -84,13 +84,17 @@ export const useFavoriteStar = ({
|
|||
const onFavoriteClick = useMemoizedFn(async (e?: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e?.stopPropagation();
|
||||
e?.preventDefault();
|
||||
if (!isFavorited)
|
||||
return await addItemToFavorite({
|
||||
asset_type: type,
|
||||
id,
|
||||
name
|
||||
});
|
||||
await removeItemFromFavorite(id);
|
||||
if (!isFavorited) {
|
||||
return await addItemToFavorite([
|
||||
{
|
||||
asset_type: type,
|
||||
id,
|
||||
name
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
return await removeItemFromFavorite([id]);
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
|
|
|
@ -241,7 +241,7 @@ const favoritesDropdown = (
|
|||
deleteUserFavorite
|
||||
}: {
|
||||
onFavoritesReorder: (itemIds: string[]) => void;
|
||||
deleteUserFavorite: (itemId: string) => void;
|
||||
deleteUserFavorite: (itemIds: string[]) => void;
|
||||
}
|
||||
): ISidebarGroup => {
|
||||
return {
|
||||
|
@ -257,7 +257,7 @@ const favoritesDropdown = (
|
|||
icon: <Icon />,
|
||||
route,
|
||||
id: favorite.id,
|
||||
onRemove: () => deleteUserFavorite(favorite.id)
|
||||
onRemove: () => deleteUserFavorite([favorite.id])
|
||||
};
|
||||
})
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Dots, Star, Trash, Xmark } from '@/components/ui/icons';
|
||||
import { Dots, Trash } from '@/components/ui/icons';
|
||||
import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||
import { Dropdown, DropdownItems } from '@/components/ui/dropdown';
|
||||
import { Dropdown } from '@/components/ui/dropdown';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { SaveToCollectionsDropdown } from '@/components/features/dropdowns/SaveToCollectionsDropdown';
|
||||
|
@ -14,12 +14,8 @@ import {
|
|||
useSaveChatToCollections,
|
||||
useRemoveChatFromCollections
|
||||
} from '@/api/buster_rest/chats';
|
||||
import {
|
||||
useAddUserFavorite,
|
||||
useDeleteUserFavorite,
|
||||
useGetUserFavorites
|
||||
} from '@/api/buster_rest/users';
|
||||
import { ShareAssetType } from '@/api/asset_interfaces/share';
|
||||
import { useThreeDotFavoritesOptions } from '@/components/features/dropdowns/useThreeDotFavoritesOptions';
|
||||
|
||||
export const ChatSelectedOptionPopup: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
|
@ -117,40 +113,11 @@ const ThreeDotButton: React.FC<{
|
|||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange }) => {
|
||||
const { mutateAsync: removeUserFavorite, isPending: removingFromFavorites } =
|
||||
useDeleteUserFavorite();
|
||||
const { mutateAsync: addUserFavorite, isPending: addingToFavorites } = useAddUserFavorite();
|
||||
const { data: userFavorites } = useGetUserFavorites();
|
||||
|
||||
const dropdownOptions: DropdownItems = [
|
||||
{
|
||||
label: 'Add to favorites',
|
||||
icon: <Star />,
|
||||
value: 'add-to-favorites',
|
||||
loading: addingToFavorites,
|
||||
onClick: async () => {
|
||||
await Promise.all(
|
||||
selectedRowKeys.map((id) => {
|
||||
const name = userFavorites?.find((f) => f.id === id)?.name || '';
|
||||
return addUserFavorite({
|
||||
id,
|
||||
asset_type: ShareAssetType.CHAT,
|
||||
name
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Remove from favorites',
|
||||
icon: <Xmark />,
|
||||
loading: removingFromFavorites,
|
||||
value: 'remove-from-favorites',
|
||||
onClick: async () => {
|
||||
await Promise.all(selectedRowKeys.map((id) => removeUserFavorite(id)));
|
||||
}
|
||||
}
|
||||
];
|
||||
const dropdownOptions = useThreeDotFavoritesOptions({
|
||||
itemIds: selectedRowKeys,
|
||||
assetType: ShareAssetType.CHAT,
|
||||
onFinish: () => onSelectChange([])
|
||||
});
|
||||
|
||||
return (
|
||||
<Dropdown items={dropdownOptions}>
|
||||
|
|
|
@ -9,7 +9,7 @@ export const CollectionIndividualSelectedPopup: React.FC<{
|
|||
selectedRowKeys: string[];
|
||||
collectionId: string;
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange, collectionId }) => {
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange, collectionId }) => {
|
||||
const show = selectedRowKeys.length > 0;
|
||||
|
||||
return (
|
||||
|
@ -27,7 +27,9 @@ export const CollectionIndividualSelectedPopup: React.FC<{
|
|||
show={show}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
CollectionIndividualSelectedPopup.displayName = 'CollectionIndividualSelectedPopup';
|
||||
|
||||
const CollectionDeleteButton: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import { Trash } from '@/components/ui/icons';
|
||||
import { Dots, Trash } from '@/components/ui/icons';
|
||||
import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import React from 'react';
|
||||
import { useDeleteCollection } from '@/api/buster_rest/collections';
|
||||
import { ShareAssetType } from '@/api/asset_interfaces/share';
|
||||
import { Dropdown } from '@/components/ui/dropdown';
|
||||
import { useThreeDotFavoritesOptions } from '@/components/features/dropdowns/useThreeDotFavoritesOptions';
|
||||
|
||||
export const CollectionListSelectedPopup: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange }) => {
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange }) => {
|
||||
const show = selectedRowKeys.length > 0;
|
||||
|
||||
return (
|
||||
|
@ -21,12 +23,19 @@ export const CollectionListSelectedPopup: React.FC<{
|
|||
key="delete"
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={onSelectChange}
|
||||
/>,
|
||||
<ThreeDotButton
|
||||
key="three-dot"
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
onSelectChange={onSelectChange}
|
||||
/>
|
||||
]}
|
||||
show={show}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
CollectionListSelectedPopup.displayName = 'CollectionListSelectedPopup';
|
||||
|
||||
const CollectionDeleteButton: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
|
@ -49,3 +58,20 @@ const CollectionDeleteButton: React.FC<{
|
|||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
const ThreeDotButton: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange }) => {
|
||||
const dropdownOptions = useThreeDotFavoritesOptions({
|
||||
itemIds: selectedRowKeys,
|
||||
assetType: ShareAssetType.COLLECTION,
|
||||
onFinish: () => onSelectChange([])
|
||||
});
|
||||
|
||||
return (
|
||||
<Dropdown items={dropdownOptions}>
|
||||
<Button prefix={<Dots />} />
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
import React, { useState } from 'react';
|
||||
import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||
import { Dropdown, DropdownItems } from '@/components/ui/dropdown';
|
||||
import { Dropdown } from '@/components/ui/dropdown';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
import { SaveToCollectionsDropdown } from '@/components/features/dropdowns/SaveToCollectionsDropdown';
|
||||
import { ASSET_ICONS } from '@/components/features/config/assetIcons';
|
||||
import { Dots, Star, Trash, Xmark } from '@/components/ui/icons';
|
||||
import {
|
||||
useAddUserFavorite,
|
||||
useDeleteUserFavorite,
|
||||
useGetUserFavorites
|
||||
} from '@/api/buster_rest/users';
|
||||
import { Dots, Trash } from '@/components/ui/icons';
|
||||
import { ShareAssetType } from '@/api/asset_interfaces/share';
|
||||
import {
|
||||
useAddDashboardToCollection,
|
||||
useDeleteDashboards,
|
||||
useRemoveDashboardFromCollection
|
||||
} from '@/api/buster_rest/dashboards';
|
||||
import { useThreeDotFavoritesOptions } from '@/components/features/dropdowns/useThreeDotFavoritesOptions';
|
||||
|
||||
export const DashboardSelectedOptionPopup: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
hasSelected: boolean;
|
||||
}> = ({ selectedRowKeys, onSelectChange, hasSelected }) => {
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange, hasSelected }) => {
|
||||
return (
|
||||
<BusterListSelectedOptionPopupContainer
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
|
@ -48,7 +44,9 @@ export const DashboardSelectedOptionPopup: React.FC<{
|
|||
show={hasSelected}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
DashboardSelectedOptionPopup.displayName = 'DashboardSelectedOptionPopup';
|
||||
|
||||
const CollectionsButton: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
|
@ -115,37 +113,11 @@ const ThreeDotButton: React.FC<{
|
|||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange }) => {
|
||||
const { mutateAsync: addUserFavorite } = useAddUserFavorite();
|
||||
const { mutateAsync: removeUserFavorite } = useDeleteUserFavorite();
|
||||
const { data: userFavorites } = useGetUserFavorites();
|
||||
|
||||
const dropdownOptions: DropdownItems = [
|
||||
{
|
||||
label: 'Add to favorites',
|
||||
icon: <Star />,
|
||||
value: 'add-to-favorites',
|
||||
onClick: async () => {
|
||||
await Promise.all(
|
||||
selectedRowKeys.map((id) => {
|
||||
const name = userFavorites?.find((f) => f.id === id)?.name || '';
|
||||
return addUserFavorite({
|
||||
id,
|
||||
asset_type: ShareAssetType.DASHBOARD,
|
||||
name
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Remove from favorites',
|
||||
icon: <Xmark />,
|
||||
value: 'remove-from-favorites',
|
||||
onClick: async () => {
|
||||
await Promise.all(selectedRowKeys.map((id) => removeUserFavorite(id)));
|
||||
}
|
||||
}
|
||||
];
|
||||
const dropdownOptions = useThreeDotFavoritesOptions({
|
||||
itemIds: selectedRowKeys,
|
||||
assetType: ShareAssetType.DASHBOARD,
|
||||
onFinish: () => onSelectChange([])
|
||||
});
|
||||
|
||||
return (
|
||||
<Dropdown items={dropdownOptions}>
|
||||
|
|
|
@ -7,26 +7,22 @@ import { SaveToCollectionsDropdown } from '@/components/features/dropdowns/SaveT
|
|||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { ASSET_ICONS } from '@/components/features/config/assetIcons';
|
||||
import { Dropdown, DropdownItems } from '@/components/ui/dropdown';
|
||||
import { Dropdown } from '@/components/ui/dropdown';
|
||||
import { StatusBadgeButton } from '@/components/features/metrics/StatusBadgeIndicator';
|
||||
import { Dots, Star, Trash, Xmark } from '@/components/ui/icons';
|
||||
import { Dots, Trash } from '@/components/ui/icons';
|
||||
import {
|
||||
useDeleteMetric,
|
||||
useRemoveMetricFromCollection,
|
||||
useSaveMetricToCollections,
|
||||
useUpdateMetric
|
||||
} from '@/api/buster_rest/metrics';
|
||||
import {
|
||||
useAddUserFavorite,
|
||||
useDeleteUserFavorite,
|
||||
useGetUserFavorites
|
||||
} from '@/api/buster_rest/users';
|
||||
import { useThreeDotFavoritesOptions } from '@/components/features/dropdowns/useThreeDotFavoritesOptions';
|
||||
|
||||
export const MetricSelectedOptionPopup: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
hasSelected: boolean;
|
||||
}> = ({ selectedRowKeys, onSelectChange, hasSelected }) => {
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange, hasSelected }) => {
|
||||
return (
|
||||
<BusterListSelectedOptionPopupContainer
|
||||
selectedRowKeys={selectedRowKeys}
|
||||
|
@ -61,7 +57,9 @@ export const MetricSelectedOptionPopup: React.FC<{
|
|||
show={hasSelected}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
MetricSelectedOptionPopup.displayName = 'MetricSelectedOptionPopup';
|
||||
|
||||
const CollectionsButton: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
|
@ -177,42 +175,18 @@ const DeleteButton: React.FC<{
|
|||
const ThreeDotButton: React.FC<{
|
||||
selectedRowKeys: string[];
|
||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange }) => {
|
||||
const { mutateAsync: addUserFavorite } = useAddUserFavorite();
|
||||
const { mutateAsync: removeUserFavorite } = useDeleteUserFavorite();
|
||||
const { data: userFavorites } = useGetUserFavorites();
|
||||
|
||||
const dropdownOptions: DropdownItems = [
|
||||
{
|
||||
label: 'Add to favorites',
|
||||
icon: <Star />,
|
||||
value: 'add-to-favorites',
|
||||
onClick: async () => {
|
||||
await Promise.all(
|
||||
selectedRowKeys.map((id) => {
|
||||
const name = userFavorites?.find((f) => f.id === id)?.name || '';
|
||||
return addUserFavorite({
|
||||
id,
|
||||
asset_type: ShareAssetType.METRIC,
|
||||
name
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Remove from favorites',
|
||||
icon: <Xmark />,
|
||||
value: 'remove-from-favorites',
|
||||
onClick: async () => {
|
||||
await Promise.all(selectedRowKeys.map((id) => removeUserFavorite(id)));
|
||||
}
|
||||
}
|
||||
];
|
||||
}> = React.memo(({ selectedRowKeys, onSelectChange }) => {
|
||||
const dropdownOptions = useThreeDotFavoritesOptions({
|
||||
itemIds: selectedRowKeys,
|
||||
assetType: ShareAssetType.METRIC,
|
||||
onFinish: () => onSelectChange([])
|
||||
});
|
||||
|
||||
return (
|
||||
<Dropdown items={dropdownOptions}>
|
||||
<Button prefix={<Dots />} />
|
||||
</Dropdown>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
ThreeDotButton.displayName = 'ThreeDotButton';
|
||||
|
|
|
@ -36,7 +36,6 @@ import { getShareAssetConfig } from '@/components/features/ShareMenu/helpers';
|
|||
import { useDashboardContentStore } from '@/context/Dashboards';
|
||||
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
||||
import { BusterRoutes, createBusterRoute } from '@/routes/busterRoutes';
|
||||
import { assetParamsToRoute } from '@/layouts/ChatLayout/ChatLayoutContext/helpers';
|
||||
|
||||
export const DashboardThreeDotMenu = React.memo(({ dashboardId }: { dashboardId: string }) => {
|
||||
const versionHistoryItems = useVersionHistorySelectMenu({ dashboardId });
|
||||
|
|
Loading…
Reference in New Issue