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