EnableIndexAdvisorButton.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { useState } from 'react'
  2. import { toast } from 'sonner'
  3. import {
  4. AlertDialog,
  5. AlertDialogAction,
  6. AlertDialogCancel,
  7. AlertDialogContent,
  8. AlertDialogDescription,
  9. AlertDialogFooter,
  10. AlertDialogHeader,
  11. AlertDialogTitle,
  12. Button,
  13. } from 'ui'
  14. import { getIndexAdvisorExtensions } from './index-advisor.utils'
  15. import { useDatabaseExtensionEnableMutation } from '@/data/database-extensions/database-extension-enable-mutation'
  16. import { useDatabaseExtensionsQuery } from '@/data/database-extensions/database-extensions-query'
  17. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  18. import { useTrack } from '@/lib/telemetry/track'
  19. export const EnableIndexAdvisorButton = () => {
  20. const track = useTrack()
  21. const [isDialogOpen, setIsDialogOpen] = useState(false)
  22. return (
  23. <>
  24. <Button
  25. type="primary"
  26. onClick={() => {
  27. setIsDialogOpen(true)
  28. track('index_advisor_enable_button_clicked', { origin: 'banner' })
  29. }}
  30. >
  31. Enable
  32. </Button>
  33. <EnableIndexAdvisorDialog open={isDialogOpen} setOpen={setIsDialogOpen} />
  34. </>
  35. )
  36. }
  37. export const EnableIndexAdvisorDialog = ({
  38. open,
  39. setOpen,
  40. }: {
  41. open: boolean
  42. setOpen: (value: boolean) => void
  43. }) => {
  44. const track = useTrack()
  45. const { data: project } = useSelectedProjectQuery()
  46. const { data: extensions } = useDatabaseExtensionsQuery({
  47. projectRef: project?.ref,
  48. connectionString: project?.connectionString,
  49. })
  50. const { hypopg, indexAdvisor } = getIndexAdvisorExtensions(extensions)
  51. const { mutateAsync: enableExtension, isPending: isEnablingExtension } =
  52. useDatabaseExtensionEnableMutation()
  53. const onEnableIndexAdvisor = async () => {
  54. if (project === undefined) return toast.error('Project is required')
  55. try {
  56. // Enable hypopg extension if not already installed
  57. if (hypopg?.installed_version === null) {
  58. await enableExtension({
  59. projectRef: project?.ref,
  60. connectionString: project?.connectionString,
  61. name: hypopg.name,
  62. schema: hypopg?.schema ?? 'extensions',
  63. version: hypopg.default_version,
  64. })
  65. }
  66. // Enable index_advisor extension if not already installed
  67. if (indexAdvisor?.installed_version === null) {
  68. await enableExtension({
  69. projectRef: project?.ref,
  70. connectionString: project?.connectionString,
  71. name: indexAdvisor.name,
  72. schema: indexAdvisor?.schema ?? 'extensions',
  73. version: indexAdvisor.default_version,
  74. })
  75. }
  76. toast.success('Successfully enabled Index Advisor!')
  77. setOpen(false)
  78. } catch (error: any) {
  79. toast.error(`Failed to enable Index Advisor: ${error.message}`)
  80. }
  81. }
  82. return (
  83. <AlertDialog open={open} onOpenChange={() => setOpen(!open)}>
  84. <AlertDialogContent size="medium">
  85. <AlertDialogHeader>
  86. <AlertDialogTitle>Enable Index Advisor</AlertDialogTitle>
  87. <AlertDialogDescription className="flex flex-col gap-y-2">
  88. <p>
  89. The Index Advisor recommends indexes to improve query performance on your tables based
  90. on your actual query patterns.
  91. </p>
  92. <p>
  93. Enable this will install the <code className="text-code-inline">index_advisor</code>{' '}
  94. and <code className="text-code-inline">hypopg</code> Postgres extensions so Index
  95. Advisor can analyse queries and suggest performance-improving indexes.
  96. </p>
  97. </AlertDialogDescription>
  98. </AlertDialogHeader>
  99. <AlertDialogFooter>
  100. <AlertDialogCancel>Cancel</AlertDialogCancel>
  101. <AlertDialogAction
  102. onClick={(e) => {
  103. e.preventDefault()
  104. onEnableIndexAdvisor()
  105. track('index_advisor_enable_button_clicked', { origin: 'dialog' })
  106. }}
  107. disabled={isEnablingExtension}
  108. >
  109. {isEnablingExtension ? 'Enabling...' : 'Enable'}
  110. </AlertDialogAction>
  111. </AlertDialogFooter>
  112. </AlertDialogContent>
  113. </AlertDialog>
  114. )
  115. }