hooks.ts153 lines · main
1import { PermissionAction } from '@supabase/shared-types/out/constants'
2import { useParams } from 'common'
3import { useRouter } from 'next/router'
4import { useCallback, useEffect, useMemo, useState } from 'react'
5import { toast } from 'sonner'
6
7import { ContentDiff, DiffType } from './SQLEditor.types'
8import {
9 compareAsAddition,
10 compareAsModification,
11 compareAsNewSnippet,
12 createSqlSnippetSkeletonV2,
13} from './SQLEditor.utils'
14import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
15import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
16import { useProfile } from '@/lib/profile'
17import { useSqlEditorV2StateSnapshot } from '@/state/sql-editor-v2'
18
19export const useNewQuery = () => {
20 const router = useRouter()
21 const { ref } = useParams()
22 const { profile } = useProfile()
23 const { data: project } = useSelectedProjectQuery()
24 const snapV2 = useSqlEditorV2StateSnapshot()
25
26 const { can: canCreateSQLSnippet } = useAsyncCheckPermissions(
27 PermissionAction.CREATE,
28 'user_content',
29 {
30 resource: { type: 'sql', owner_id: profile?.id },
31 subject: { id: profile?.id },
32 }
33 )
34
35 const newQuery = async (sql: string, name: string, shouldRedirect: boolean = true) => {
36 if (!ref) return console.error('Project ref is required')
37 if (!project) return console.error('Project is required')
38 if (!profile) return console.error('Profile is required')
39
40 if (!canCreateSQLSnippet) {
41 toast('Your queries will not be saved as you do not have sufficient permissions')
42 return undefined
43 }
44
45 try {
46 const snippet = createSqlSnippetSkeletonV2({
47 name,
48 sql,
49 owner_id: profile?.id,
50 project_id: project?.id,
51 })
52 snapV2.addSnippet({ projectRef: ref, snippet })
53 snapV2.addNeedsSaving(snippet.id)
54 if (shouldRedirect) {
55 router.push(`/project/${ref}/sql/${snippet.id}`)
56 return undefined
57 } else {
58 return snippet.id
59 }
60 } catch (error: any) {
61 toast.error(`Failed to create new query: ${error.message}`)
62 return undefined
63 }
64 }
65
66 return { newQuery }
67}
68
69export function useSqlEditorDiff() {
70 const [sourceSqlDiff, setSourceSqlDiff] = useState<ContentDiff>()
71 const [selectedDiffType, setSelectedDiffType] = useState<DiffType>()
72 const [isAcceptDiffLoading, setIsAcceptDiffLoading] = useState(false)
73
74 const isDiffOpen = !!sourceSqlDiff
75
76 const defaultSqlDiff = useMemo(() => {
77 if (!sourceSqlDiff) {
78 return { original: '', modified: '' }
79 }
80
81 switch (selectedDiffType) {
82 case DiffType.Modification:
83 return compareAsModification(sourceSqlDiff)
84 case DiffType.Addition:
85 return compareAsAddition(sourceSqlDiff)
86 case DiffType.NewSnippet:
87 return compareAsNewSnippet(sourceSqlDiff)
88 default:
89 return { original: '', modified: '' }
90 }
91 }, [selectedDiffType, sourceSqlDiff])
92
93 const closeDiff = useCallback(() => {
94 setSourceSqlDiff(undefined)
95 setSelectedDiffType(undefined)
96 }, [])
97
98 return {
99 sourceSqlDiff,
100 setSourceSqlDiff,
101 selectedDiffType,
102 setSelectedDiffType,
103 isAcceptDiffLoading,
104 setIsAcceptDiffLoading,
105 isDiffOpen,
106 defaultSqlDiff,
107 closeDiff,
108 }
109}
110
111interface PromptState {
112 isOpen: boolean
113 selection: string
114 beforeSelection: string
115 afterSelection: string
116 startLineNumber: number
117 endLineNumber: number
118}
119
120const initialPromptState: PromptState = {
121 isOpen: false,
122 selection: '',
123 beforeSelection: '',
124 afterSelection: '',
125 startLineNumber: 0,
126 endLineNumber: 0,
127}
128
129export function useSqlEditorPrompt() {
130 const [promptState, setPromptState] = useState<PromptState>(initialPromptState)
131 const [promptInput, setPromptInput] = useState('')
132
133 useEffect(() => {
134 if (!promptState.isOpen) {
135 setPromptInput('')
136 }
137 }, [promptState.isOpen])
138
139 const resetPrompt = () => {
140 setPromptState(initialPromptState)
141 setPromptInput('')
142 }
143
144 return {
145 promptState,
146 setPromptState,
147 promptInput,
148 setPromptInput,
149 resetPrompt,
150 }
151}
152
153export default useNewQuery