EmptyBucketModal.tsx83 lines · main
1import { useParams } from 'common'
2import { toast } from 'sonner'
3import {
4 Button,
5 Dialog,
6 DialogContent,
7 DialogFooter,
8 DialogHeader,
9 DialogSection,
10 DialogSectionSeparator,
11 DialogTitle,
12} from 'ui'
13import { Admonition } from 'ui-patterns'
14
15import { useBucketEmptyMutation } from '@/data/storage/bucket-empty-mutation'
16import type { Bucket } from '@/data/storage/buckets-query'
17import { useStorageExplorerStateSnapshot } from '@/state/storage-explorer'
18
19export interface EmptyBucketModalProps {
20 visible: boolean
21 bucket?: Bucket
22 onClose: () => void
23}
24
25export const EmptyBucketModal = ({ visible, bucket, onClose }: EmptyBucketModalProps) => {
26 const { ref: projectRef } = useParams()
27 const { fetchFolderContents } = useStorageExplorerStateSnapshot()
28
29 const { mutate: emptyBucket, isPending } = useBucketEmptyMutation({
30 onSuccess: async () => {
31 if (bucket === undefined) return
32 await fetchFolderContents({
33 bucketId: bucket.id,
34 folderId: bucket.id,
35 folderName: bucket.name,
36 index: -1,
37 })
38 toast.success(`Successfully emptied bucket ${bucket!.name}`)
39 onClose()
40 },
41 })
42
43 const onEmptyBucket = async () => {
44 if (!projectRef) return console.error('Project ref is required')
45 if (!bucket) return console.error('No bucket is selected')
46 emptyBucket({ projectRef, id: bucket.id })
47 }
48
49 return (
50 <Dialog
51 open={visible}
52 onOpenChange={(open) => {
53 if (!open) onClose()
54 }}
55 >
56 <DialogContent>
57 <DialogHeader>
58 <DialogTitle>{`Empty bucket “${bucket?.name}”`}</DialogTitle>
59 </DialogHeader>
60 <DialogSectionSeparator />
61 <Admonition
62 type="destructive"
63 className="rounded-none border-x-0 border-t-0"
64 title="This action cannot be undone"
65 description="The contents of your bucket cannot be recovered once deleted."
66 />
67 <DialogSection>
68 <p className="text-sm">
69 Are you sure you want to remove all contents from the bucket “{bucket?.name}”?
70 </p>
71 </DialogSection>
72 <DialogFooter>
73 <Button type="default" disabled={isPending} onClick={onClose}>
74 Cancel
75 </Button>
76 <Button type="danger" loading={isPending} onClick={onEmptyBucket}>
77 Empty bucket
78 </Button>
79 </DialogFooter>
80 </DialogContent>
81 </Dialog>
82 )
83}