DeleteVectorTableModal.tsx98 lines · main
1import { useParams } from 'common'
2import { parseAsString, useQueryState } from 'nuqs'
3import { useEffect } from 'react'
4import { toast } from 'sonner'
5import { ConfirmationModal } from 'ui-patterns/Dialogs/ConfirmationModal'
6
7import { useS3VectorsWrapperInstance } from './useS3VectorsWrapperInstance'
8import { useFDWDropForeignTableMutation } from '@/data/fdw/fdw-drop-foreign-table-mutation'
9import { useVectorBucketIndexDeleteMutation } from '@/data/storage/vector-bucket-index-delete-mutation'
10import { useVectorBucketsIndexesQuery } from '@/data/storage/vector-buckets-indexes-query'
11import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
12
13export const DeleteVectorTableModal = () => {
14 const { ref: projectRef, bucketId } = useParams()
15 const { data: project } = useSelectedProjectQuery()
16
17 const [selectedTableIdToDelete, setSelectedTableIdToDelete] = useQueryState(
18 'deleteTable',
19 parseAsString.withOptions({ history: 'push', clearOnDefault: true })
20 )
21
22 const { data, isSuccess: isSuccessIndexes } = useVectorBucketsIndexesQuery({
23 projectRef,
24 vectorBucketName: bucketId,
25 })
26 const allIndexes = data?.indexes ?? []
27 const table = allIndexes.find((index) => index.indexName === selectedTableIdToDelete)
28
29 const { data: wrapperInstance } = useS3VectorsWrapperInstance({ bucketId })
30 const foreignTable = wrapperInstance?.tables?.find((x) => x.name === table?.indexName)
31
32 const { mutateAsync: deleteForeignTable } = useFDWDropForeignTableMutation({
33 onError: () => {},
34 })
35
36 const {
37 mutate: deleteIndex,
38 isPending: isDeleting,
39 isSuccess: isSuccessDelete,
40 } = useVectorBucketIndexDeleteMutation({
41 onSuccess: (_, vars) => {
42 try {
43 if (!!foreignTable) {
44 deleteForeignTable({
45 projectRef: project?.ref,
46 connectionString: project?.connectionString,
47 schemaName: foreignTable.schema,
48 tableName: foreignTable.name,
49 })
50 }
51 toast.success(`Table "${vars.indexName}" deleted successfully`)
52 setSelectedTableIdToDelete(null)
53 } catch (error: any) {
54 toast.success(
55 `Table "${vars.indexName}" deleted successfully, but its corresponding foreign table failed to clean up: ${error.message}`
56 )
57 }
58 },
59 })
60
61 const onConfirmDelete = () => {
62 if (!project?.ref) return console.error('Project ref is required')
63 if (!table) return console.error('Vector table is required')
64
65 deleteIndex({
66 projectRef: project?.ref,
67 bucketName: table.vectorBucketName,
68 indexName: table.indexName,
69 })
70 }
71
72 useEffect(() => {
73 if (!!selectedTableIdToDelete && isSuccessIndexes && !table && !isSuccessDelete) {
74 toast(`Table ${selectedTableIdToDelete} cannot be found in your bucket`)
75 setSelectedTableIdToDelete(null)
76 }
77 }, [
78 isSuccessIndexes,
79 selectedTableIdToDelete,
80 table,
81 setSelectedTableIdToDelete,
82 isSuccessDelete,
83 ])
84
85 return (
86 <ConfirmationModal
87 visible={!!table}
88 loading={isDeleting}
89 variant="destructive"
90 title={`Confirm to delete table "${table?.indexName}"`}
91 onConfirm={onConfirmDelete}
92 onCancel={() => setSelectedTableIdToDelete(null)}
93 >
94 {/* [Joshen] Can probably beef up more details here - what are potential side effects of deleting a table */}
95 <p className="text-sm">This action cannot be undone.</p>
96 </ConfirmationModal>
97 )
98}