IntegrationSettings.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // @ts-nocheck
  2. import { PermissionAction } from '@supabase/shared-types/out/constants'
  3. import { useRouter } from 'next/router'
  4. import { useCallback } from 'react'
  5. import { toast } from 'sonner'
  6. import { GenericSkeletonLoader } from 'ui-patterns'
  7. import { IntegrationConnectionItem } from '../../Integrations/VercelGithub/IntegrationConnection'
  8. import SidePanelVercelProjectLinker from './SidePanelVercelProjectLinker'
  9. import { EmptyIntegrationConnection } from '@/components/interfaces/Integrations/VercelGithub/IntegrationPanels'
  10. import { IntegrationImageHandler } from '@/components/interfaces/Settings/Integrations/IntegrationsSettings'
  11. import { VercelSection } from '@/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection'
  12. import {
  13. ScaffoldContainer,
  14. ScaffoldContainerLegacy,
  15. ScaffoldDivider,
  16. ScaffoldSection,
  17. ScaffoldSectionContent,
  18. ScaffoldSectionDetail,
  19. ScaffoldTitle,
  20. } from '@/components/layouts/Scaffold'
  21. import { InlineLink } from '@/components/ui/InlineLink'
  22. import NoPermission from '@/components/ui/NoPermission'
  23. import { useGitHubAuthorizationQuery } from '@/data/integrations/github-authorization-query'
  24. import { useGitHubConnectionDeleteMutation } from '@/data/integrations/github-connection-delete-mutation'
  25. import {
  26. useGitHubConnectionsQuery,
  27. type GitHubConnection,
  28. } from '@/data/integrations/github-connections-query'
  29. import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types'
  30. import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
  31. import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
  32. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  33. import {
  34. GITHUB_INTEGRATION_INSTALLATION_URL,
  35. GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL,
  36. } from '@/lib/github'
  37. type GitHubSectionProps = {
  38. canCreateGitHubConnection: boolean
  39. canReadGithubConnection: boolean
  40. canUpdateGitHubConnection: boolean
  41. connections?: GitHubConnection[]
  42. isGitHubAuthorized: boolean
  43. isLoadingPermissions: boolean
  44. onAddGitHubConnection: () => void
  45. onDeleteGitHubConnection: (connection: IntegrationProjectConnection) => void | Promise<void>
  46. }
  47. const GitHubSection = ({
  48. canCreateGitHubConnection,
  49. canReadGithubConnection,
  50. canUpdateGitHubConnection,
  51. connections,
  52. isGitHubAuthorized,
  53. isLoadingPermissions,
  54. onAddGitHubConnection,
  55. onDeleteGitHubConnection,
  56. }: GitHubSectionProps) => (
  57. <ScaffoldContainer>
  58. <ScaffoldSection className="py-12">
  59. <ScaffoldSectionDetail title="GitHub Connections">
  60. <p>Connect any of your GitHub repositories to a project.</p>
  61. <IntegrationImageHandler title="github" />
  62. </ScaffoldSectionDetail>
  63. <ScaffoldSectionContent>
  64. {isLoadingPermissions ? (
  65. <GenericSkeletonLoader />
  66. ) : !canReadGithubConnection ? (
  67. <NoPermission resourceText="view this organization's GitHub connections" />
  68. ) : (
  69. <div className="space-y-6">
  70. <div className="space-y-1">
  71. <h3 className="text-sm font-medium text-foreground">
  72. How do GitHub connections work?
  73. </h3>
  74. <p className="text-sm text-foreground-light">
  75. Connect a GitHub repository to a Briven project. The GitHub app watches file,
  76. branch, and pull request activity in your repository.
  77. </p>
  78. </div>
  79. <div>
  80. <ul className="flex flex-col gap-y-2">
  81. {connections?.map((connection) => (
  82. <IntegrationConnectionItem
  83. key={connection.id}
  84. disabled={!canUpdateGitHubConnection}
  85. connection={{
  86. id: String(connection.id),
  87. added_by: {
  88. id: String(connection.user?.id),
  89. primary_email: connection.user?.primary_email ?? '',
  90. username: connection.user?.username ?? '',
  91. },
  92. foreign_project_id: String(connection.repository.id),
  93. briven_project_ref: connection.project.ref,
  94. organization_integration_id: 'unused',
  95. inserted_at: connection.inserted_at,
  96. updated_at: connection.updated_at,
  97. metadata: {
  98. name: connection.repository.name,
  99. } as IntegrationProjectConnection['metadata'],
  100. }}
  101. type="GitHub"
  102. onDeleteConnection={onDeleteGitHubConnection}
  103. />
  104. ))}
  105. </ul>
  106. <EmptyIntegrationConnection
  107. onClick={onAddGitHubConnection}
  108. showNode={false}
  109. disabled={!canCreateGitHubConnection}
  110. >
  111. Add new project connection
  112. </EmptyIntegrationConnection>
  113. </div>
  114. {isGitHubAuthorized && (
  115. <p className="text-sm text-foreground-light">
  116. You are authorized with the Briven GitHub App. You can configure your{' '}
  117. <InlineLink href={GITHUB_INTEGRATION_INSTALLATION_URL}>
  118. GitHub App installations and repository access
  119. </InlineLink>
  120. , or{' '}
  121. <InlineLink href={GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL}>
  122. revoke your authorization
  123. </InlineLink>
  124. .
  125. </p>
  126. )}
  127. </div>
  128. )}
  129. </ScaffoldSectionContent>
  130. </ScaffoldSection>
  131. </ScaffoldContainer>
  132. )
  133. export const IntegrationSettings = () => {
  134. const router = useRouter()
  135. const { data: org } = useSelectedOrganizationQuery()
  136. const showVercelIntegration = useIsFeatureEnabled('integrations:vercel')
  137. const { can: canReadGithubConnection, isLoading: isLoadingPermissions } =
  138. useAsyncCheckPermissions(PermissionAction.READ, 'integrations.github_connections')
  139. const { can: canCreateGitHubConnection } = useAsyncCheckPermissions(
  140. PermissionAction.CREATE,
  141. 'integrations.github_connections'
  142. )
  143. const { can: canUpdateGitHubConnection } = useAsyncCheckPermissions(
  144. PermissionAction.UPDATE,
  145. 'integrations.github_connections'
  146. )
  147. const { data: gitHubAuthorization } = useGitHubAuthorizationQuery()
  148. const { data: connections } = useGitHubConnectionsQuery({ organizationId: org?.id })
  149. const { mutate: deleteGitHubConnection } = useGitHubConnectionDeleteMutation({
  150. onSuccess: () => {
  151. toast.success('Successfully deleted GitHub connection')
  152. },
  153. })
  154. const onAddGitHubConnection = useCallback(() => {
  155. router.push('/project/_/settings/integrations')
  156. }, [router])
  157. const onDeleteGitHubConnection = useCallback(
  158. async (connection: IntegrationProjectConnection) => {
  159. if (!org?.id) {
  160. toast.error('Organization not found')
  161. return
  162. }
  163. deleteGitHubConnection({
  164. connectionId: connection.id,
  165. organizationId: org.id,
  166. })
  167. },
  168. [deleteGitHubConnection, org?.id]
  169. )
  170. return (
  171. <>
  172. <ScaffoldContainerLegacy>
  173. <ScaffoldTitle>Integrations</ScaffoldTitle>
  174. </ScaffoldContainerLegacy>
  175. <GitHubSection
  176. canCreateGitHubConnection={canCreateGitHubConnection}
  177. canReadGithubConnection={canReadGithubConnection}
  178. canUpdateGitHubConnection={canUpdateGitHubConnection}
  179. connections={connections}
  180. isGitHubAuthorized={Boolean(gitHubAuthorization)}
  181. isLoadingPermissions={isLoadingPermissions}
  182. onAddGitHubConnection={onAddGitHubConnection}
  183. onDeleteGitHubConnection={onDeleteGitHubConnection}
  184. />
  185. {showVercelIntegration && (
  186. <>
  187. <ScaffoldDivider />
  188. <VercelSection isProjectScoped={false} />
  189. <SidePanelVercelProjectLinker />
  190. </>
  191. )}
  192. </>
  193. )
  194. }