DeleteVectorTableModal.tsx 3.4 KB

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