mirror of https://github.com/buster-so/buster.git
110 lines
3.8 KiB
TypeScript
110 lines
3.8 KiB
TypeScript
import { Dropdown, type DropdownItem, type DropdownProps } from '@/components/ui/dropdown';
|
|
import { AppTooltip } from '@/components/ui/tooltip';
|
|
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
|
import { BusterRoutes, createBusterRoute } from '@/routes/busterRoutes';
|
|
import { useMemoizedFn } from '@/hooks';
|
|
import React, { useMemo } from 'react';
|
|
import type { BusterCollectionListItem } from '@/api/asset_interfaces/collection';
|
|
import { NewCollectionModal } from '../modal/NewCollectionModal';
|
|
import { Plus } from '@/components/ui/icons';
|
|
import { Button } from '@/components/ui/buttons';
|
|
import { useGetCollectionsList } from '@/api/buster_rest/collections';
|
|
|
|
export const SaveToCollectionsDropdown: React.FC<{
|
|
children: React.ReactNode;
|
|
selectedCollections: string[];
|
|
onSaveToCollection: (collectionId: string[]) => Promise<void>;
|
|
onRemoveFromCollection: (collectionId: string) => Promise<void>;
|
|
}> = React.memo(({ children, onRemoveFromCollection, onSaveToCollection, selectedCollections }) => {
|
|
const { data: collectionsList, isPending: isCreatingCollection } = useGetCollectionsList({});
|
|
const onChangePage = useAppLayoutContextSelector((s) => s.onChangePage);
|
|
const [openCollectionModal, setOpenCollectionModal] = React.useState(false);
|
|
const [showDropdown, setShowDropdown] = React.useState(false);
|
|
|
|
const items: DropdownProps['items'] = useMemo(() => {
|
|
const collectionsItems = (collectionsList || []).map<DropdownItem>((collection) => {
|
|
return {
|
|
value: collection.id,
|
|
label: collection.name,
|
|
selected: selectedCollections.some((id) => id === collection.id),
|
|
onClick: () => onClickItem(collection),
|
|
link: createBusterRoute({
|
|
route: BusterRoutes.APP_COLLECTIONS_ID,
|
|
collectionId: collection.id
|
|
})
|
|
};
|
|
});
|
|
return collectionsItems;
|
|
}, [collectionsList, selectedCollections]);
|
|
|
|
const onClickItem = useMemoizedFn((collection: BusterCollectionListItem) => {
|
|
const isSelected = selectedCollections.some((id) => id === collection.id);
|
|
if (isSelected) {
|
|
onRemoveFromCollection(collection.id);
|
|
} else {
|
|
const allCollectionsAndSelected = selectedCollections.map((id) => id).concat(collection.id);
|
|
onSaveToCollection(allCollectionsAndSelected);
|
|
}
|
|
});
|
|
|
|
const onCollectionCreated = useMemoizedFn(async (collectionId: string) => {
|
|
await onSaveToCollection([collectionId]);
|
|
onChangePage({
|
|
route: BusterRoutes.APP_COLLECTIONS_ID,
|
|
collectionId
|
|
});
|
|
});
|
|
|
|
const onCloseCollectionModal = useMemoizedFn(() => {
|
|
setOpenCollectionModal(false);
|
|
setShowDropdown(false);
|
|
});
|
|
|
|
const onOpenChange = useMemoizedFn((open: boolean) => {
|
|
setShowDropdown(open);
|
|
});
|
|
|
|
const onOpenNewCollectionModal = useMemoizedFn(() => {
|
|
setOpenCollectionModal(true);
|
|
setShowDropdown(false);
|
|
});
|
|
|
|
const memoizedButton = useMemo(() => {
|
|
return (
|
|
<Button
|
|
variant="ghost"
|
|
block
|
|
loading={isCreatingCollection}
|
|
className="justify-start!"
|
|
prefix={<Plus />}
|
|
onClick={onOpenNewCollectionModal}>
|
|
New collection
|
|
</Button>
|
|
);
|
|
}, [onOpenNewCollectionModal]);
|
|
|
|
return (
|
|
<>
|
|
<Dropdown
|
|
side="bottom"
|
|
align="center"
|
|
menuHeader={items.length > 0 ? 'Save to a collection' : undefined}
|
|
onOpenChange={onOpenChange}
|
|
footerContent={memoizedButton}
|
|
emptyStateText="No collections found"
|
|
items={items}>
|
|
<AppTooltip title={showDropdown ? '' : 'Save to collection'}>{children} </AppTooltip>
|
|
</Dropdown>
|
|
|
|
<NewCollectionModal
|
|
open={openCollectionModal}
|
|
onClose={onCloseCollectionModal}
|
|
useChangePage={false}
|
|
onCollectionCreated={onCollectionCreated}
|
|
/>
|
|
</>
|
|
);
|
|
});
|
|
|
|
SaveToCollectionsDropdown.displayName = 'SaveToCollectionsDropdown';
|