Files
supabase/apps/studio/components/interfaces/Settings/Integrations/GithubIntegration/GithubSection.tsx
Alaister Young 70da0f1d1d chore: cleanup packages (#27770)
* chore: cleanup packages

- Avoid circular imports
- Export API-types as types
- pg-format without depending on Node internal Buffer (not browser-compatible)
- Avoid importing from barrel files in ui dir

* chore: avoid barrel file imports in studio (#27771)

* chore: avoid barrel file imports

- Removes some unused imports
- Avoids barrel file import for faster builds + less memory

* add eslint rule

* type fixes

* delete layouts barrel

* delete components/grid barrel file

* delete components/grid/utils barrel file

* delete components/grid/components/common barrel file

* delete components/grid/components/editor barrel file

* delete components/grid/components/formatter barrel file

* delete components/grid/components/grid barrel file

* delete components/grid/components/header/filter barrel file

* remote components/grid/store barrel file

* remove components/interfaces/Auth/Policies barrel file

* delete components/interfaces/Settings/Logs barrel file

* delete components/ui/CodeEditor barrel file

* delete components/ui/Forms barrel file

* delete components/ui/Shimmers barrel file

* delete data/analytics barrel file

* delete hooks barrel file

* cleanup lib/common/fetch barrel file

* final * barral files cleanup

* global react-data-grid styles

* remove console.log

---------

Co-authored-by: Kevin Grüneberg <k.grueneberg1994@gmail.com>

* fix build

---------

Co-authored-by: Kevin Grüneberg <k.grueneberg1994@gmail.com>
2024-07-04 14:48:10 +08:00

203 lines
8.0 KiB
TypeScript

import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useCallback } from 'react'
import toast from 'react-hot-toast'
import { useParams } from 'common'
import { IntegrationConnectionItem } from 'components/interfaces/Integrations/IntegrationConnection'
import { EmptyIntegrationConnection } from 'components/interfaces/Integrations/IntegrationPanels'
import { Markdown } from 'components/interfaces/Markdown'
import {
ScaffoldContainer,
ScaffoldSection,
ScaffoldSectionContent,
ScaffoldSectionDetail,
} from 'components/layouts/Scaffold'
import NoPermission from 'components/ui/NoPermission'
import { useGitHubConnectionDeleteMutation } from 'data/integrations/github-connection-delete-mutation'
import { useGitHubConnectionsQuery } from 'data/integrations/github-connections-query'
import type {
IntegrationName,
IntegrationProjectConnection,
} from 'data/integrations/integrations.types'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProject } from 'hooks/misc/useSelectedProject'
import { useFlag } from 'hooks/ui/useFlag'
import { useSidePanelsStateSnapshot } from 'state/side-panels'
import { IntegrationImageHandler } from '../IntegrationsSettings'
import GitHubIntegrationConnectionForm from './GitHubIntegrationConnectionForm'
const GitHubTitle = `GitHub Connections`
const GitHubDetailsSection = `
Connect any of your GitHub repositories to a project.
`
const GitHubContentSectionTop = `
### How will GitHub connections work?
You will be able to connect a GitHub repository to a Supabase project.
The GitHub app will watch for changes in your repository such as file changes, branch changes as well as pull request activity.
`
const GitHubSection = () => {
const { ref: projectRef } = useParams()
const project = useSelectedProject()
const org = useSelectedOrganization()
const sidePanelsStateSnapshot = useSidePanelsStateSnapshot()
const canReadGitHubConnection = useCheckPermissions(
PermissionAction.READ,
'integrations.github_connections'
)
const canCreateGitHubConnection = useCheckPermissions(
PermissionAction.CREATE,
'integrations.github_connections'
)
const canUpdateGitHubConnection = useCheckPermissions(
PermissionAction.UPDATE,
'integrations.github_connections'
)
const { data: allConnections } = useGitHubConnectionsQuery({ organizationId: org?.id })
const { mutateAsync: deleteGitHubConnection } = useGitHubConnectionDeleteMutation({
onSuccess: () => {
toast.success('Successfully deleted Github connection')
},
})
const hasAccessToBranching = useFlag<boolean>('branchManagement')
const isBranch = project?.parent_project_ref !== undefined
const connections =
allConnections?.filter((connection) =>
isBranch
? connection.project.ref === project.parent_project_ref
: connection.project.ref === projectRef
) ?? []
const onAddGitHubConnection = useCallback(() => {
sidePanelsStateSnapshot.setGithubConnectionsOpen(true)
}, [sidePanelsStateSnapshot])
const onDeleteGitHubConnection = useCallback(
async (connection: IntegrationProjectConnection) => {
if (!org?.id) {
toast.error('Organization not found')
return
}
await deleteGitHubConnection({ connectionId: connection.id, organizationId: org.id })
},
[deleteGitHubConnection, org?.id]
)
return (
<ScaffoldContainer>
<ScaffoldSection>
<ScaffoldSectionDetail title={GitHubTitle}>
<Markdown content={GitHubDetailsSection} />
<IntegrationImageHandler title="github" />
</ScaffoldSectionDetail>
<ScaffoldSectionContent>
{!canReadGitHubConnection ? (
<NoPermission resourceText="view this organization's GitHub connections" />
) : (
<>
<Markdown content={GitHubContentSectionTop} />
{connections.length > 0 ? (
<ul className="flex flex-col">
{connections.map((connection) => (
<div
key={connection.id}
className="relative flex flex-col -gap-[1px] [&>li]:pb-0"
>
<IntegrationConnectionItem
showNode={false}
disabled={isBranch || !canUpdateGitHubConnection}
key={connection.id}
connection={{
id: String(connection.id),
added_by: {
id: String(connection.user?.id),
primary_email: connection.user?.primary_email ?? '',
username: connection.user?.username ?? '',
},
foreign_project_id: String(connection.repository.id),
supabase_project_ref: connection.project.ref,
organization_integration_id: 'unused',
inserted_at: connection.inserted_at,
updated_at: connection.updated_at,
metadata: {
name: connection.repository.name,
} as any,
}}
type={'GitHub' as IntegrationName}
onDeleteConnection={onDeleteGitHubConnection}
className="!rounded-b-none !mb-0"
/>
<div className="border-b border-l border-r rounded-b-lg">
<GitHubIntegrationConnectionForm
disabled={!canUpdateGitHubConnection}
connection={{
id: String(connection.id),
added_by: {
id: String(connection.user?.id),
primary_email: connection.user?.primary_email ?? '',
username: connection.user?.username ?? '',
},
foreign_project_id: String(connection.repository.id),
supabase_project_ref: connection.project.ref,
organization_integration_id: 'unused',
inserted_at: connection.inserted_at,
updated_at: connection.updated_at,
metadata: {
name: connection.repository.name,
supabaseConfig: {
supabaseDirectory: connection.workdir,
supabaseChangesOnly: connection.supabase_changes_only,
branchLimit: connection.branch_limit,
},
} as any,
}}
/>
</div>
</div>
))}
</ul>
) : hasAccessToBranching ? (
<EmptyIntegrationConnection
onClick={onAddGitHubConnection}
orgSlug={org?.slug}
showNode={false}
disabled={!canCreateGitHubConnection}
>
Add new project connection
</EmptyIntegrationConnection>
) : (
<p className="text-sm text-foreground-light">
Access to{' '}
<a
href="https://supabase.com/docs/guides/platform/branching"
target="_blank"
rel="noreferrer"
className="text-foreground"
>
branching
</a>{' '}
is required to add GitHub connections.
</p>
)}
</>
)}
</ScaffoldSectionContent>
</ScaffoldSection>
</ScaffoldContainer>
)
}
export default GitHubSection