import { useDebounce } from '@uidotdev/usehooks' import { ArrowDownNarrowWide, Search } from 'lucide-react' import { useCallback, useMemo, useState } from 'react' import { useParams } from 'common' import AlertError from 'components/ui/AlertError' import { InlineLink } from 'components/ui/InlineLink' import { useProjectStorageConfigQuery } from 'data/config/project-storage-config-query' import { usePaginatedBucketsQuery } from 'data/storage/buckets-query' import { IS_PLATFORM } from 'lib/constants' import { formatBytes } from 'lib/helpers' import { parseAsBoolean, useQueryState } from 'nuqs' import { useStorageExplorerStateSnapshot } from 'state/storage-explorer' import { Button, Card, DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from 'ui' import { Admonition } from 'ui-patterns' import { Input } from 'ui-patterns/DataInputs/Input' import { PageContainer } from 'ui-patterns/PageContainer' import { PageSection, PageSectionContent } from 'ui-patterns/PageSection' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { CreateBucketModal } from '../CreateBucketModal' import { EmptyBucketState } from '../EmptyBucketState' import { CreateBucketButton } from '../NewBucketButton' import { STORAGE_BUCKET_SORT } from '../Storage.constants' import { BucketsTable } from './BucketsTable' export const FilesBuckets = () => { const { ref } = useParams() const snap = useStorageExplorerStateSnapshot() const [filterString, setFilterString] = useState('') const debouncedFilterString = useDebounce(filterString, 250) const normalizedSearch = debouncedFilterString.trim() const sortColumn = snap.sortBucket === STORAGE_BUCKET_SORT.ALPHABETICAL ? 'name' : 'created_at' const sortOrder = snap.sortBucket === STORAGE_BUCKET_SORT.ALPHABETICAL ? 'asc' : 'desc' const [visible, setVisible] = useQueryState( 'new', parseAsBoolean.withDefault(false).withOptions({ history: 'push', clearOnDefault: true }) ) const { data } = useProjectStorageConfigQuery({ projectRef: ref }, { enabled: IS_PLATFORM }) const { data: bucketsData, error: bucketsError, isError: isErrorBuckets, isPending: isLoadingBuckets, isSuccess: isSuccessBuckets, isFetching: isFetchingBuckets, fetchNextPage, hasNextPage, } = usePaginatedBucketsQuery({ projectRef: ref, search: normalizedSearch.length > 0 ? normalizedSearch : undefined, sortColumn, sortOrder, }) const buckets = useMemo(() => bucketsData?.pages.flatMap((page) => page) ?? [], [bucketsData]) const fileBuckets = buckets.filter((bucket) => !('type' in bucket) || bucket.type === 'STANDARD') const hasNoBuckets = fileBuckets.length === 0 && normalizedSearch.length === 0 const formattedGlobalUploadLimit = formatBytes(data?.fileSizeLimit ?? 0) const hasNoApiKeys = isErrorBuckets && bucketsError.message.includes('Project has no active API keys') const handleLoadMoreBuckets = useCallback(() => { if (hasNextPage && !isFetchingBuckets) { fetchNextPage() } }, [hasNextPage, isFetchingBuckets, fetchNextPage]) return ( <> {isLoadingBuckets && } {isErrorBuckets && ( <> {hasNoApiKeys ? (

The Dashboard relies on having active API keys on the project to function. If you'd like to use Storage through the Dashboard, create a set of API keys{' '} here.

) : ( )} )} {isSuccessBuckets && ( <> {hasNoBuckets ? ( setVisible(true)} /> ) : ( <>
setFilterString(e.target.value)} icon={} /> snap.setSortBucket(value as STORAGE_BUCKET_SORT) } > Sort by name Sort by created at
setVisible(true)} />
)} )}
) }