HookList.tsx147 lines · main
1import { PermissionAction } from '@supabase/shared-types/out/constants'
2import { useParams } from 'common'
3import { includes } from 'lodash'
4import { Edit3, MoreVertical, Trash } from 'lucide-react'
5import Image from 'next/legacy/image'
6import { parseAsString, useQueryState } from 'nuqs'
7import {
8 Badge,
9 Button,
10 DropdownMenu,
11 DropdownMenuContent,
12 DropdownMenuItem,
13 DropdownMenuSeparator,
14 DropdownMenuTrigger,
15} from 'ui'
16
17import Table from '@/components/to-be-cleaned/Table'
18import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
19import { useDatabaseHooksQuery } from '@/data/database-triggers/database-triggers-query'
20import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
21import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
22import { BASE_PATH } from '@/lib/constants'
23
24export interface HookListProps {
25 schema: string
26 filterString: string
27}
28
29export const HookList = ({ schema, filterString }: HookListProps) => {
30 const { ref } = useParams()
31 const { data: project } = useSelectedProjectQuery()
32 const { data: hooks } = useDatabaseHooksQuery({
33 projectRef: project?.ref,
34 connectionString: project?.connectionString,
35 })
36
37 const [, setSelectedHookIdToEdit] = useQueryState('edit', parseAsString.withDefault(''))
38 const [, setSelectedHookIdToDelete] = useQueryState('delete', parseAsString.withDefault(''))
39
40 const restUrl = project?.restUrl
41 const restUrlTld = restUrl ? new URL(restUrl).hostname.split('.').pop() : 'co'
42
43 const filteredHooks = (hooks ?? []).filter(
44 (x) =>
45 includes(x.name.toLowerCase(), filterString.toLowerCase()) &&
46 x.schema === schema &&
47 x.function_args.length >= 2
48 )
49 const { can: canUpdateWebhook } = useAsyncCheckPermissions(
50 PermissionAction.TENANT_SQL_ADMIN_WRITE,
51 'triggers'
52 )
53
54 return (
55 <>
56 {filteredHooks.map((x) => {
57 const isEdgeFunction = (url: string) =>
58 url.includes(`https://${ref}.functions.briven.${restUrlTld}/`) ||
59 url.includes(`https://${ref}.briven.${restUrlTld}/functions/`)
60 const [url, method] = x.function_args
61
62 return (
63 <Table.tr key={x.id}>
64 <Table.td>
65 <div className="flex items-center space-x-4">
66 <div>
67 <Image
68 src={
69 isEdgeFunction(url)
70 ? `${BASE_PATH}/img/function-providers/briven-severless-function.png`
71 : `${BASE_PATH}/img/function-providers/http-request.png`
72 }
73 alt="hook-type"
74 layout="fixed"
75 width="20"
76 height="20"
77 title={isEdgeFunction(url) ? 'Briven Edge Function' : 'HTTP Request'}
78 />
79 </div>
80 <p title={x.name} className="truncate">
81 {x.name}
82 </p>
83 </div>
84 </Table.td>
85 <Table.td className="hidden space-x-2 lg:table-cell">
86 <p title={x.table}>{x.table}</p>
87 </Table.td>
88 <Table.td className="hidden space-x-1 xl:table-cell">
89 {x.events.map((event: string) => (
90 <Badge key={event}>{event}</Badge>
91 ))}
92 </Table.td>
93 <Table.td className="hidden xl:table-cell">
94 <p className="truncate" title={url}>
95 <code className="text-code-inline">{method}</code>: {url}
96 </p>
97 </Table.td>
98 <Table.td className="text-right">
99 <div className="flex justify-end gap-4">
100 {canUpdateWebhook ? (
101 <DropdownMenu>
102 <DropdownMenuTrigger asChild>
103 <Button type="default" className="px-1" icon={<MoreVertical />} />
104 </DropdownMenuTrigger>
105
106 <DropdownMenuContent side="left">
107 <>
108 <DropdownMenuItem
109 className="space-x-2"
110 onClick={() => setSelectedHookIdToEdit(x.id.toString())}
111 >
112 <Edit3 size="14" />
113 <p>Edit hook</p>
114 </DropdownMenuItem>
115 <DropdownMenuSeparator />
116 <DropdownMenuItem
117 className="space-x-2"
118 onClick={() => setSelectedHookIdToDelete(x.id.toString())}
119 >
120 <Trash stroke="red" size="14" />
121 <p>Delete hook</p>
122 </DropdownMenuItem>
123 </>
124 </DropdownMenuContent>
125 </DropdownMenu>
126 ) : (
127 <ButtonTooltip
128 disabled
129 type="default"
130 className="px-1"
131 icon={<MoreVertical />}
132 tooltip={{
133 content: {
134 side: 'bottom',
135 text: 'You need additional permissions to update webhooks',
136 },
137 }}
138 />
139 )}
140 </div>
141 </Table.td>
142 </Table.tr>
143 )
144 })}
145 </>
146 )
147}