OAuthAppRow.tsx 3.9 KB

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