OAuthAppRow.tsx120 lines · main
1import { PermissionAction } from '@supabase/shared-types/out/constants'
2import { Edit, MoreVertical, Trash } from 'lucide-react'
3import {
4 Button,
5 DropdownMenu,
6 DropdownMenuContent,
7 DropdownMenuItem,
8 DropdownMenuSeparator,
9 DropdownMenuTrigger,
10 TableCell,
11 TableRow,
12 Tooltip,
13 TooltipContent,
14 TooltipTrigger,
15} from 'ui'
16import { TimestampInfo } from 'ui-patterns'
17
18import CopyButton from '@/components/ui/CopyButton'
19import type { OAuthApp } from '@/data/oauth/oauth-apps-query'
20import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
21
22export interface OAuthAppRowProps {
23 app: OAuthApp
24 onSelectEdit: () => void
25 onSelectDelete: () => void
26}
27
28export const OAuthAppRow = ({ app, onSelectEdit, onSelectDelete }: OAuthAppRowProps) => {
29 const { can: canUpdateOAuthApps } = useAsyncCheckPermissions(
30 PermissionAction.UPDATE,
31 'approved_oauth_apps'
32 )
33 const { can: canDeleteOAuthApps } = useAsyncCheckPermissions(
34 PermissionAction.DELETE,
35 'approved_oauth_apps'
36 )
37
38 return (
39 <TableRow>
40 <TableCell className="w-[62px] min-w-[62px] max-w-[62px]">
41 <div
42 className="w-[30px] h-[30px] rounded-full bg-no-repeat bg-cover bg-center border border-control flex items-center justify-center text-xs"
43 style={{ backgroundImage: app.icon ? `url('${app.icon}')` : 'none' }}
44 >
45 {!!app.icon ? '' : `${app.name[0]}`}
46 </div>
47 </TableCell>
48 <TableCell>
49 <p title={app.name} className="truncate">
50 {app.name}
51 </p>
52 </TableCell>
53 <TableCell>
54 <div className="flex items-center gap-x-2">
55 <p className="text-xs font-mono truncate" title={app.client_id}>
56 {app.client_id}
57 </p>
58 <CopyButton type="default" iconOnly text={app.client_id ?? ''} className="px-1" />
59 </div>
60 </TableCell>
61 <TableCell>
62 <TimestampInfo
63 utcTimestamp={app.created_at ?? ''}
64 labelFormat="DD/MM/YYYY, HH:mm:ss"
65 className="text-sm"
66 />
67 </TableCell>
68 <TableCell className="text-right">
69 <DropdownMenu>
70 <DropdownMenuTrigger asChild>
71 <Button type="default" icon={<MoreVertical />} className="px-1" />
72 </DropdownMenuTrigger>
73 <DropdownMenuContent align="end" side="bottom" className="w-32">
74 <Tooltip>
75 <TooltipTrigger asChild>
76 <DropdownMenuItem
77 key="edit"
78 disabled={!canUpdateOAuthApps}
79 className="space-x-2 pointer-events-auto!"
80 onClick={() => {
81 if (canUpdateOAuthApps) onSelectEdit()
82 }}
83 >
84 <Edit size={16} />
85 <p>Edit app</p>
86 </DropdownMenuItem>
87 </TooltipTrigger>
88 {!canUpdateOAuthApps && (
89 <TooltipContent side="left">
90 You need additional permissions to edit apps
91 </TooltipContent>
92 )}
93 </Tooltip>
94 <DropdownMenuSeparator />
95 <Tooltip>
96 <TooltipTrigger asChild>
97 <DropdownMenuItem
98 disabled={!canDeleteOAuthApps}
99 className="space-x-2 pointer-events-auto!"
100 key="delete"
101 onClick={() => {
102 if (canDeleteOAuthApps) onSelectDelete()
103 }}
104 >
105 <Trash size={16} />
106 <p>Delete app</p>
107 </DropdownMenuItem>
108 </TooltipTrigger>
109 {!canDeleteOAuthApps && (
110 <TooltipContent side="left">
111 You need additional permissions to delete apps
112 </TooltipContent>
113 )}
114 </Tooltip>
115 </DropdownMenuContent>
116 </DropdownMenu>
117 </TableCell>
118 </TableRow>
119 )
120}