IndexAdvisorDisabledState.tsx 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { useParams } from 'common'
  2. import Link from 'next/link'
  3. import { toast } from 'sonner'
  4. import { Alert, AlertDescription, AlertTitle, Button } from 'ui'
  5. import { Markdown } from '../../Markdown'
  6. import { getIndexAdvisorExtensions } from './index-advisor.utils'
  7. import { DocsButton } from '@/components/ui/DocsButton'
  8. import { useDatabaseExtensionEnableMutation } from '@/data/database-extensions/database-extension-enable-mutation'
  9. import { useDatabaseExtensionsQuery } from '@/data/database-extensions/database-extensions-query'
  10. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  11. import { DOCS_URL } from '@/lib/constants'
  12. export const IndexAdvisorDisabledState = () => {
  13. const { ref } = useParams()
  14. const { data: project } = useSelectedProjectQuery()
  15. const { data: extensions } = useDatabaseExtensionsQuery({
  16. projectRef: project?.ref,
  17. connectionString: project?.connectionString,
  18. })
  19. const { hypopg, indexAdvisor } = getIndexAdvisorExtensions(extensions)
  20. const { mutateAsync: enableExtension, isPending: isEnablingExtension } =
  21. useDatabaseExtensionEnableMutation()
  22. const onEnableIndexAdvisor = async () => {
  23. if (project === undefined) return console.error('Project is required')
  24. try {
  25. if (hypopg?.installed_version === null) {
  26. await enableExtension({
  27. projectRef: project?.ref,
  28. connectionString: project?.connectionString,
  29. name: hypopg.name,
  30. schema: hypopg?.schema ?? 'extensions',
  31. version: hypopg.default_version,
  32. })
  33. }
  34. if (indexAdvisor?.installed_version === null) {
  35. await enableExtension({
  36. projectRef: project?.ref,
  37. connectionString: project?.connectionString,
  38. name: indexAdvisor.name,
  39. schema: indexAdvisor?.schema ?? 'extensions',
  40. version: indexAdvisor.default_version,
  41. })
  42. }
  43. toast.success('Successfully enabled index advisor!')
  44. } catch (error: any) {
  45. toast.error(`Failed to enable index advisor: ${error.message}`)
  46. }
  47. }
  48. return (
  49. <Alert className="mb-6">
  50. <AlertTitle>
  51. <Markdown
  52. className="text-foreground"
  53. content={
  54. indexAdvisor === undefined
  55. ? 'Newer version of Postgres required'
  56. : 'Postgres extensions `index_advisor` and `hypopg` required'
  57. }
  58. />
  59. </AlertTitle>
  60. <AlertDescription>
  61. <Markdown
  62. content={
  63. indexAdvisor === undefined
  64. ? 'Upgrade to the latest version of Postgres to get recommendations on indexes for your queries'
  65. : 'These extensions can help in recommending database indexes to reduce the costs of your query.'
  66. }
  67. />
  68. </AlertDescription>
  69. <AlertDescription className="mt-3">
  70. <div className="flex items-center gap-x-2">
  71. {indexAdvisor === undefined ? (
  72. <Button asChild type="default">
  73. <Link href={`/project/${ref}/settings/infrastructure`}>Upgrade Postgres version</Link>
  74. </Button>
  75. ) : (
  76. <Button
  77. type="default"
  78. disabled={isEnablingExtension}
  79. loading={isEnablingExtension}
  80. onClick={() => onEnableIndexAdvisor()}
  81. >
  82. Enable extensions
  83. </Button>
  84. )}
  85. <DocsButton href={`${DOCS_URL}/guides/database/extensions/index_advisor`} />
  86. </div>
  87. </AlertDescription>
  88. </Alert>
  89. )
  90. }