mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore(studio + docs) improve project integrations (#45200)
## What kind of change does this PR introduce? Docs update and UI copy improvement. ## What is the current behavior? The GitHub integration working directory helper uses an inline tooltip for examples. In the form layout, the tooltip alignment and inline code wrapping can make the helper harder to scan. The integration settings pages also mix markdown-rendered copy with JSX copy, duplicate the integration cover image helper, and use slightly different heading, spacing, and button copy patterns across GitHub, Vercel, and AWS PrivateLink. ## What is the new behavior? The GitHub working directory field now keeps the helper copy concise and links to a dedicated docs section with examples for repository root and nested `supabase/` directories. The integration settings sections now use a more consistent JSX structure and copy treatment across GitHub, Vercel, and AWS PrivateLink, including shared cover imagery and matching explanatory section hierarchy. | Before | After | | --- | --- | | <img width="1838" height="696" alt="CleanShot 2026-04-24 at 14 35 32@2x" src="https://github.com/user-attachments/assets/f9843018-fbf5-4c18-a0c3-1842b665f3fd" /> | <img width="1842" height="700" alt="CleanShot 2026-04-24 at 14 30 21@2x-64E8726E-0B89-4C5A-8A47-CE1AA24F3D1A" src="https://github.com/user-attachments/assets/bb017464-2b43-4dfe-94b8-a586aedea318" /> | | <img width="1884" height="1432" alt="CleanShot 2026-04-24 at 14 40 19@2x" src="https://github.com/user-attachments/assets/b34e4573-cd7c-4588-83a0-0e1941019552" /> | <img width="1844" height="1424" alt="CleanShot 2026-04-24 at 14 39 02@2x" src="https://github.com/user-attachments/assets/4f82b01c-cb27-4f01-b2da-76b7f6e298a5" /> | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Clarified GitHub integration setup: provide a Working directory value, how to compute it from the repo root (including "." for root), examples, and updated “initialize” spelling. * **Refactor** * Simplified integration form descriptions (tooltips → inline text + Learn more link). * Reworked GitHub and Vercel integration content to use consistent headings, layout, and shared image handling. * Reorganized integration settings rendering for clearer UI states. * **Style** * Minor copy, casing, and button text/spacing adjustments. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
8347877957
commit
b37272cdd7
6 files changed
+268
-275
No files matched your search
@@ -13,13 +13,19 @@ In the Supabase Dashboard:
|
||||
2. Under **GitHub Integration**, click **Authorize GitHub**.
|
||||
3. You are redirected to a GitHub authorization page. Click **Authorize Supabase**.
|
||||
4. You are redirected back to the Integrations page. Choose a GitHub repository to connect your project to.
|
||||
5. Fill in the relative path to the Supabase directory from your repository root.
|
||||
5. Set the **Working directory** field.
|
||||
6. Configure the other options as needed to automate your GitHub connection.
|
||||
7. Click **Enable integration**.
|
||||
|
||||
### Set the working directory
|
||||
|
||||
The working directory is the path from your repository root to the directory that contains the `supabase/` folder. Enter `.` when `supabase/` is at the repository root.
|
||||
|
||||
If `supabase/` is nested deeper in your repository, enter its parent directory instead. For example, if your layout is `apps/web/supabase/`, enter `apps/web`.
|
||||
|
||||
## Preparing your Git repository
|
||||
|
||||
You will be using the [Supabase CLI](/docs/guides/cli) to initialise your local `./supabase` directory:
|
||||
You will be using the [Supabase CLI](/docs/guides/cli) to initialize your local `./supabase` directory:
|
||||
|
||||
<StepHikeCompact>
|
||||
<StepHikeCompact.Step step={1}>
|
||||
|
||||
+116
-103
@@ -7,7 +7,7 @@ import { GenericSkeletonLoader } from 'ui-patterns'
|
||||
import { IntegrationConnectionItem } from '../../Integrations/VercelGithub/IntegrationConnection'
|
||||
import SidePanelVercelProjectLinker from './SidePanelVercelProjectLinker'
|
||||
import { EmptyIntegrationConnection } from '@/components/interfaces/Integrations/VercelGithub/IntegrationPanels'
|
||||
import { Markdown } from '@/components/interfaces/Markdown'
|
||||
import { IntegrationImageHandler } from '@/components/interfaces/Settings/Integrations/IntegrationsSettings'
|
||||
import { VercelSection } from '@/components/interfaces/Settings/Integrations/VercelIntegration/VercelSection'
|
||||
import {
|
||||
ScaffoldContainer,
|
||||
@@ -18,31 +18,124 @@ import {
|
||||
ScaffoldSectionDetail,
|
||||
ScaffoldTitle,
|
||||
} from '@/components/layouts/Scaffold'
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
import NoPermission from '@/components/ui/NoPermission'
|
||||
import { useGitHubAuthorizationQuery } from '@/data/integrations/github-authorization-query'
|
||||
import { useGitHubConnectionDeleteMutation } from '@/data/integrations/github-connection-delete-mutation'
|
||||
import { useGitHubConnectionsQuery } from '@/data/integrations/github-connections-query'
|
||||
import {
|
||||
useGitHubConnectionsQuery,
|
||||
type GitHubConnection,
|
||||
} from '@/data/integrations/github-connections-query'
|
||||
import type { IntegrationProjectConnection } from '@/data/integrations/integrations.types'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
||||
import { BASE_PATH } from '@/lib/constants'
|
||||
import {
|
||||
GITHUB_INTEGRATION_INSTALLATION_URL,
|
||||
GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL,
|
||||
} from '@/lib/github'
|
||||
import { useSidePanelsStateSnapshot } from '@/state/side-panels'
|
||||
|
||||
const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => {
|
||||
return (
|
||||
<img
|
||||
className="border rounded-lg shadow w-full sm:w-48 mt-6 border-body"
|
||||
src={`${BASE_PATH}/img/integrations/covers/${title}-cover.png`}
|
||||
alt={`${title} cover`}
|
||||
/>
|
||||
)
|
||||
type GitHubSectionProps = {
|
||||
canCreateGitHubConnection: boolean
|
||||
canReadGithubConnection: boolean
|
||||
canUpdateGitHubConnection: boolean
|
||||
connections?: GitHubConnection[]
|
||||
isGitHubAuthorized: boolean
|
||||
isLoadingPermissions: boolean
|
||||
onAddGitHubConnection: () => void
|
||||
onDeleteGitHubConnection: (connection: IntegrationProjectConnection) => void | Promise<void>
|
||||
}
|
||||
|
||||
const GitHubSection = ({
|
||||
canCreateGitHubConnection,
|
||||
canReadGithubConnection,
|
||||
canUpdateGitHubConnection,
|
||||
connections,
|
||||
isGitHubAuthorized,
|
||||
isLoadingPermissions,
|
||||
onAddGitHubConnection,
|
||||
onDeleteGitHubConnection,
|
||||
}: GitHubSectionProps) => (
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldSection className="py-12">
|
||||
<ScaffoldSectionDetail title="GitHub Connections">
|
||||
<p>Connect any of your GitHub repositories to a project.</p>
|
||||
<IntegrationImageHandler title="github" />
|
||||
</ScaffoldSectionDetail>
|
||||
<ScaffoldSectionContent>
|
||||
{isLoadingPermissions ? (
|
||||
<GenericSkeletonLoader />
|
||||
) : !canReadGithubConnection ? (
|
||||
<NoPermission resourceText="view this organization's GitHub connections" />
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-1">
|
||||
<h3 className="text-sm font-medium text-foreground">
|
||||
How do GitHub connections work?
|
||||
</h3>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Connect a GitHub repository to a Supabase project. The GitHub app watches file,
|
||||
branch, and pull request activity in your repository.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul className="flex flex-col gap-y-2">
|
||||
{connections?.map((connection) => (
|
||||
<IntegrationConnectionItem
|
||||
key={connection.id}
|
||||
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,
|
||||
} as IntegrationProjectConnection['metadata'],
|
||||
}}
|
||||
type="GitHub"
|
||||
onDeleteConnection={onDeleteGitHubConnection}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<EmptyIntegrationConnection
|
||||
onClick={onAddGitHubConnection}
|
||||
showNode={false}
|
||||
disabled={!canCreateGitHubConnection}
|
||||
>
|
||||
Add new project connection
|
||||
</EmptyIntegrationConnection>
|
||||
</div>
|
||||
|
||||
{isGitHubAuthorized && (
|
||||
<p className="text-sm text-foreground-light">
|
||||
You are authorized with the Supabase GitHub App. You can configure your{' '}
|
||||
<InlineLink href={GITHUB_INTEGRATION_INSTALLATION_URL}>
|
||||
GitHub App installations and repository access
|
||||
</InlineLink>
|
||||
, or{' '}
|
||||
<InlineLink href={GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL}>
|
||||
revoke your authorization
|
||||
</InlineLink>
|
||||
.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</ScaffoldSectionContent>
|
||||
</ScaffoldSection>
|
||||
</ScaffoldContainer>
|
||||
)
|
||||
|
||||
export const IntegrationSettings = () => {
|
||||
const router = useRouter()
|
||||
const { data: org } = useSelectedOrganizationQuery()
|
||||
@@ -69,11 +162,9 @@ export const IntegrationSettings = () => {
|
||||
},
|
||||
})
|
||||
|
||||
const sidePanelsStateSnapshot = useSidePanelsStateSnapshot()
|
||||
|
||||
const onAddGitHubConnection = useCallback(() => {
|
||||
router.push('/project/_/settings/integrations')
|
||||
}, [sidePanelsStateSnapshot])
|
||||
}, [router])
|
||||
|
||||
const onDeleteGitHubConnection = useCallback(
|
||||
async (connection: IntegrationProjectConnection) => {
|
||||
@@ -90,99 +181,21 @@ export const IntegrationSettings = () => {
|
||||
[deleteGitHubConnection, org?.id]
|
||||
)
|
||||
|
||||
/**
|
||||
* GitHub markdown content
|
||||
*/
|
||||
|
||||
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 GitHubContentSectionBottom = gitHubAuthorization
|
||||
? `You are authorized with Supabase GitHub App. You can configure your GitHub App installations and repository access [here](${GITHUB_INTEGRATION_INSTALLATION_URL}). You can revoke your authorization [here](${GITHUB_INTEGRATION_REVOKE_AUTHORIZATION_URL}).`
|
||||
: ''
|
||||
|
||||
const GitHubSection = () => (
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldSection>
|
||||
<ScaffoldSectionDetail title={GitHubTitle}>
|
||||
<Markdown content={GitHubDetailsSection} />
|
||||
<IntegrationImageHandler title="github" />
|
||||
</ScaffoldSectionDetail>
|
||||
<ScaffoldSectionContent>
|
||||
{isLoadingPermissions ? (
|
||||
<GenericSkeletonLoader />
|
||||
) : !canReadGithubConnection ? (
|
||||
<NoPermission resourceText="view this organization's GitHub connections" />
|
||||
) : (
|
||||
<>
|
||||
<Markdown content={GitHubContentSectionTop} />
|
||||
|
||||
<ul className="flex flex-col gap-y-2">
|
||||
{connections?.map((connection) => (
|
||||
<IntegrationConnectionItem
|
||||
key={connection.id}
|
||||
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,
|
||||
} as any,
|
||||
}}
|
||||
type="GitHub"
|
||||
onDeleteConnection={onDeleteGitHubConnection}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<EmptyIntegrationConnection
|
||||
onClick={onAddGitHubConnection}
|
||||
showNode={false}
|
||||
disabled={!canCreateGitHubConnection}
|
||||
>
|
||||
Add new project connection
|
||||
</EmptyIntegrationConnection>
|
||||
|
||||
{GitHubContentSectionBottom && (
|
||||
<Markdown
|
||||
extLinks
|
||||
content={GitHubContentSectionBottom}
|
||||
className="text-foreground-lighter"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ScaffoldSectionContent>
|
||||
</ScaffoldSection>
|
||||
</ScaffoldContainer>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<ScaffoldContainerLegacy>
|
||||
<ScaffoldTitle>Integrations</ScaffoldTitle>
|
||||
</ScaffoldContainerLegacy>
|
||||
<GitHubSection />
|
||||
<GitHubSection
|
||||
canCreateGitHubConnection={canCreateGitHubConnection}
|
||||
canReadGithubConnection={canReadGithubConnection}
|
||||
canUpdateGitHubConnection={canUpdateGitHubConnection}
|
||||
connections={connections}
|
||||
isGitHubAuthorized={Boolean(gitHubAuthorization)}
|
||||
isLoadingPermissions={isLoadingPermissions}
|
||||
onAddGitHubConnection={onAddGitHubConnection}
|
||||
onDeleteGitHubConnection={onDeleteGitHubConnection}
|
||||
/>
|
||||
{showVercelIntegration && (
|
||||
<>
|
||||
<ScaffoldDivider />
|
||||
|
||||
+26
-25
@@ -15,6 +15,7 @@ import {
|
||||
import { ResourceList } from '@/components/ui/Resource/ResourceList'
|
||||
import { UpgradeToPro } from '@/components/ui/UpgradeToPro'
|
||||
import { useAWSAccountDeleteMutation } from '@/data/aws-accounts/aws-account-delete-mutation'
|
||||
import type { AWSAccount } from '@/data/aws-accounts/aws-accounts-query'
|
||||
import { useAWSAccountsQuery } from '@/data/aws-accounts/aws-accounts-query'
|
||||
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
|
||||
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
||||
@@ -24,7 +25,7 @@ export const AWSPrivateLinkSection = () => {
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
const { data: accounts } = useAWSAccountsQuery({ projectRef: project?.ref })
|
||||
|
||||
const [selectedAccount, setSelectedAccount] = useState<any>(null)
|
||||
const [selectedAccount, setSelectedAccount] = useState<AWSAccount>()
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false)
|
||||
|
||||
@@ -32,7 +33,7 @@ export const AWSPrivateLinkSection = () => {
|
||||
onSuccess: () => {
|
||||
toast.success('Account will be deleted shortly')
|
||||
setShowDeleteModal(false)
|
||||
setSelectedAccount(null)
|
||||
setSelectedAccount(undefined)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -40,16 +41,16 @@ export const AWSPrivateLinkSection = () => {
|
||||
const promptPlanUpgrade = IS_PLATFORM && !hasPrivateLinkAccess
|
||||
|
||||
const onAddAccount = () => {
|
||||
setSelectedAccount(null)
|
||||
setSelectedAccount(undefined)
|
||||
setShowForm(true)
|
||||
}
|
||||
|
||||
const onEditAccount = (account: any) => {
|
||||
const onEditAccount = (account: AWSAccount) => {
|
||||
setSelectedAccount(account)
|
||||
setShowForm(true)
|
||||
}
|
||||
|
||||
const onDeleteAccount = (account: any) => {
|
||||
const onDeleteAccount = (account: AWSAccount) => {
|
||||
setSelectedAccount(account)
|
||||
setShowDeleteModal(true)
|
||||
}
|
||||
@@ -70,31 +71,31 @@ export const AWSPrivateLinkSection = () => {
|
||||
</ScaffoldSectionDetail>
|
||||
<ScaffoldSectionContent>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h5 className="text-foreground mb-2">
|
||||
How does the AWS PrivateLink integration work?
|
||||
</h5>
|
||||
<p className="text-foreground-light text-sm mb-6">
|
||||
Connecting to AWS PrivateLink allows you to create a private connection between
|
||||
your AWS VPC and your Supabase project.
|
||||
</p>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-1">
|
||||
<h3 className="text-sm font-medium text-foreground">
|
||||
How does the AWS PrivateLink integration work?
|
||||
</h3>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Connecting to AWS PrivateLink allows you to create a private connection between
|
||||
your AWS VPC and your Supabase project.
|
||||
</p>
|
||||
</div>
|
||||
{promptPlanUpgrade && (
|
||||
<div className="mb-6">
|
||||
<UpgradeToPro
|
||||
layout="vertical"
|
||||
primaryText="Only available on Team or Enterprise Plan and above"
|
||||
secondaryText="Connect your AWS VPC privately to your Supabase project using AWS PrivateLink."
|
||||
buttonText="Upgrade to Team"
|
||||
source="aws-privatelink-integration"
|
||||
/>
|
||||
</div>
|
||||
<UpgradeToPro
|
||||
layout="vertical"
|
||||
primaryText="Only available on Team or Enterprise Plan and above"
|
||||
secondaryText="Connect your AWS VPC privately to your Supabase project using AWS PrivateLink."
|
||||
buttonText="Upgrade to Team"
|
||||
source="aws-privatelink-integration"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className={cn(promptPlanUpgrade && 'opacity-25 pointer-events-none')}>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h3 className="text-foreground text-sm">AWS Accounts</h3>
|
||||
<Button type={promptPlanUpgrade ? 'default' : 'primary'} onClick={onAddAccount}>
|
||||
Add Account
|
||||
<h3 className="text-sm font-medium text-foreground">AWS Accounts</h3>
|
||||
<Button type="default" onClick={onAddAccount}>
|
||||
Add account
|
||||
</Button>
|
||||
</div>
|
||||
{(accounts?.length ?? 0) > 0 ? (
|
||||
|
||||
+12
-26
@@ -30,7 +30,6 @@ import {
|
||||
import { Admonition } from 'ui-patterns/admonition'
|
||||
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
|
||||
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
|
||||
import { InfoTooltip } from 'ui-patterns/info-tooltip'
|
||||
import * as z from 'zod'
|
||||
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
@@ -461,7 +460,7 @@ export const GitHubIntegrationConnectionForm = ({
|
||||
render={({ field }) => (
|
||||
<FormItemLayout
|
||||
layout="flex-row-reverse"
|
||||
label="GitHub Repository"
|
||||
label="GitHub repository"
|
||||
description={
|
||||
connection
|
||||
? 'Change the connected repository'
|
||||
@@ -489,7 +488,7 @@ export const GitHubIntegrationConnectionForm = ({
|
||||
>
|
||||
{selectedRepository || connection
|
||||
? selectedRepository?.name || connection?.repository.name
|
||||
: 'Choose GitHub Repository'}
|
||||
: 'Choose GitHub repository'}
|
||||
</Button>
|
||||
</FormControl_Shadcn_>
|
||||
</PopoverTrigger_Shadcn_>
|
||||
@@ -584,29 +583,16 @@ export const GitHubIntegrationConnectionForm = ({
|
||||
layout="flex-row-reverse"
|
||||
label="Working directory"
|
||||
description={
|
||||
<span>
|
||||
Relative path to the directory that contains your{' '}
|
||||
<code className="text-code-inline !break-keep">supabase</code> folder{' '}
|
||||
<span className="inline-flex align-middle [&>button]:ml-1 [&>button]:-translate-y-[2px]">
|
||||
<InfoTooltip side="bottom" className="w-72">
|
||||
<p>Examples:</p>
|
||||
<ul className="list-disc pl-4 space-y-1">
|
||||
<li>
|
||||
<code className="text-code-inline">.</code> if repository root
|
||||
contains <code className="text-code-inline">supabase/</code>
|
||||
</li>
|
||||
<li>
|
||||
<code className="text-code-inline">apps/web</code> if{' '}
|
||||
<code className="text-code-inline">supabase/</code> is nested
|
||||
at{' '}
|
||||
<code className="text-code-inline !break-keep">
|
||||
apps/web/supabase/
|
||||
</code>
|
||||
</li>
|
||||
</ul>
|
||||
</InfoTooltip>
|
||||
</span>
|
||||
</span>
|
||||
<>
|
||||
Relative path to the directory containing your{' '}
|
||||
<code className="text-code-inline whitespace-nowrap">supabase/</code>{' '}
|
||||
folder.{' '}
|
||||
<InlineLink
|
||||
href={`${DOCS_URL}/guides/deployment/branching/github-integration#set-the-working-directory`}
|
||||
>
|
||||
Learn more
|
||||
</InlineLink>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<FormControl_Shadcn_>
|
||||
|
||||
+15
-19
@@ -1,8 +1,9 @@
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import { IS_PLATFORM, useParams } from 'common'
|
||||
import { useParams } from 'common'
|
||||
import { useMemo } from 'react'
|
||||
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
|
||||
|
||||
import { IntegrationImageHandler } from '../IntegrationsSettings'
|
||||
import { GitHubIntegrationConnectionForm } from './GitHubIntegrationConnectionForm'
|
||||
import {
|
||||
ScaffoldContainer,
|
||||
@@ -14,17 +15,6 @@ import NoPermission from '@/components/ui/NoPermission'
|
||||
import { useGitHubConnectionsQuery } from '@/data/integrations/github-connections-query'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
||||
import { BASE_PATH } from '@/lib/constants'
|
||||
|
||||
const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => {
|
||||
return (
|
||||
<img
|
||||
className="border rounded-lg shadow w-full sm:w-48 mt-6 border-body"
|
||||
src={`${BASE_PATH}/img/integrations/covers/${title}-cover.png`}
|
||||
alt={`${title} cover`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const GitHubSection = () => {
|
||||
const { ref: projectRef } = useParams()
|
||||
@@ -59,13 +49,19 @@ export const GitHubSection = () => {
|
||||
<NoPermission resourceText="view this organization's GitHub connections" />
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
<h5 className="text-foreground mb-2">How does the GitHub integration work?</h5>
|
||||
<p className="text-foreground-light text-sm mb-6">
|
||||
Connecting to GitHub allows you to sync preview branches with a chosen GitHub
|
||||
branch, keep your production branch in sync, and automatically create preview
|
||||
branches for every pull request.
|
||||
</p>
|
||||
<GitHubIntegrationConnectionForm connection={existingConnection} />
|
||||
<div className="space-y-1">
|
||||
<h3 className="text-sm font-medium text-foreground">
|
||||
How does the GitHub integration work?
|
||||
</h3>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Connecting to GitHub allows you to sync preview branches with a chosen GitHub
|
||||
branch, keep your production branch in sync, and automatically create preview
|
||||
branches for every pull request.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<GitHubIntegrationConnectionForm connection={existingConnection} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</ScaffoldSectionContent>
|
||||
|
||||
+91
-100
@@ -14,13 +14,13 @@ import {
|
||||
IntegrationConnectionHeader,
|
||||
IntegrationInstallation,
|
||||
} from '@/components/interfaces/Integrations/VercelGithub/IntegrationPanels'
|
||||
import { Markdown } from '@/components/interfaces/Markdown'
|
||||
import {
|
||||
ScaffoldContainer,
|
||||
ScaffoldSection,
|
||||
ScaffoldSectionContent,
|
||||
ScaffoldSectionDetail,
|
||||
} from '@/components/layouts/Scaffold'
|
||||
import { InlineLink } from '@/components/ui/InlineLink'
|
||||
import NoPermission from '@/components/ui/NoPermission'
|
||||
import { useOrgIntegrationsQuery } from '@/data/integrations/integrations-query-org-only'
|
||||
import { useIntegrationsVercelInstalledConnectionDeleteMutation } from '@/data/integrations/integrations-vercel-installed-connection-delete-mutation'
|
||||
@@ -119,31 +119,8 @@ export const VercelSection = ({ isProjectScoped }: { isProjectScoped: boolean })
|
||||
[deleteVercelConnection, org?.slug]
|
||||
)
|
||||
|
||||
// Markdown Content
|
||||
const VercelTitle = `Vercel Integration`
|
||||
|
||||
const VercelDetailsSection = `
|
||||
|
||||
Connect your Vercel teams to your Supabase organization.
|
||||
`
|
||||
|
||||
const VercelContentSectionTop = `
|
||||
|
||||
### How does the Vercel integration work?
|
||||
|
||||
Supabase will keep your environment variables up to date in each of the projects you assign to a Supabase project.
|
||||
You can also link multiple Vercel Projects to the same Supabase project.
|
||||
`
|
||||
|
||||
const VercelContentSectionBottom =
|
||||
vercelProjectCount > 0 && vercelIntegration !== undefined
|
||||
? `
|
||||
Your Vercel connection has access to ${vercelProjectCount} Vercel Projects.
|
||||
You can change the scope of the access for Supabase by configuring
|
||||
[here](${getIntegrationConfigurationUrl(vercelIntegration)}).
|
||||
`
|
||||
: ''
|
||||
|
||||
const integrationUrl =
|
||||
process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod'
|
||||
? 'https://vercel.com/integrations/supabase'
|
||||
@@ -167,7 +144,7 @@ You can change the scope of the access for Supabase by configuring
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldSection className="py-12">
|
||||
<ScaffoldSectionDetail title={VercelTitle}>
|
||||
<Markdown content={VercelDetailsSection} />
|
||||
<p>Connect your Vercel teams to your Supabase organization.</p>
|
||||
<IntegrationImageHandler title="vercel" />
|
||||
</ScaffoldSectionDetail>
|
||||
<ScaffoldSectionContent>
|
||||
@@ -176,87 +153,101 @@ You can change the scope of the access for Supabase by configuring
|
||||
) : !canReadVercelConnection ? (
|
||||
<NoPermission resourceText="view this organization's Vercel connections" />
|
||||
) : (
|
||||
<>
|
||||
<Markdown content={VercelContentSectionTop} />
|
||||
{vercelIntegration ? (
|
||||
<div key={vercelIntegration.id}>
|
||||
<IntegrationInstallation title={'Vercel'} integration={vercelIntegration} />
|
||||
{connections.length > 0 ? (
|
||||
<>
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-1">
|
||||
<h3 className="text-sm font-medium text-foreground">
|
||||
How does the Vercel integration work?
|
||||
</h3>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Supabase will keep your environment variables up to date in each of the projects
|
||||
you assign to a Supabase project. You can also link multiple Vercel projects to
|
||||
the same Supabase project.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
{vercelIntegration ? (
|
||||
<div key={vercelIntegration.id}>
|
||||
<IntegrationInstallation title={'Vercel'} integration={vercelIntegration} />
|
||||
{connections.length > 0 ? (
|
||||
<>
|
||||
<IntegrationConnectionHeader
|
||||
title={ConnectionHeaderTitle}
|
||||
markdown={`Repository connections for Vercel`}
|
||||
/>
|
||||
<ul className="flex flex-col">
|
||||
{connections.map((connection) => (
|
||||
<div
|
||||
key={connection.id}
|
||||
className={cn(
|
||||
isProjectScoped && 'relative flex flex-col -gap-[1px] [&>li]:pb-0'
|
||||
)}
|
||||
>
|
||||
<IntegrationConnectionItem
|
||||
connection={connection}
|
||||
disabled={isBranch || !canUpdateVercelConnection}
|
||||
type={'Vercel' as IntegrationName}
|
||||
onDeleteConnection={onDeleteVercelConnection}
|
||||
className={cn(isProjectScoped && '!rounded-b-none !mb-0')}
|
||||
/>
|
||||
{isProjectScoped ? (
|
||||
<div className="relative pl-8 ml-6 border-l border-muted pb-6">
|
||||
<div className="border-b border-l border-r rounded-b-lg">
|
||||
<VercelIntegrationConnectionForm
|
||||
connection={connection}
|
||||
integration={vercelIntegration}
|
||||
disabled={isBranch || !canUpdateVercelConnection}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : (
|
||||
<IntegrationConnectionHeader
|
||||
title={ConnectionHeaderTitle}
|
||||
className="pb-0"
|
||||
markdown={`Repository connections for Vercel`}
|
||||
/>
|
||||
<ul className="flex flex-col">
|
||||
{connections.map((connection) => (
|
||||
<div
|
||||
key={connection.id}
|
||||
className={cn(
|
||||
isProjectScoped && 'relative flex flex-col -gap-[1px] [&>li]:pb-0'
|
||||
)}
|
||||
>
|
||||
<IntegrationConnectionItem
|
||||
connection={connection}
|
||||
disabled={isBranch || !canUpdateVercelConnection}
|
||||
type={'Vercel' as IntegrationName}
|
||||
onDeleteConnection={onDeleteVercelConnection}
|
||||
className={cn(isProjectScoped && '!rounded-b-none !mb-0')}
|
||||
/>
|
||||
{isProjectScoped ? (
|
||||
<div className="relative pl-8 ml-6 border-l border-muted pb-6">
|
||||
<div className="border-b border-l border-r rounded-b-lg">
|
||||
<VercelIntegrationConnectionForm
|
||||
connection={connection}
|
||||
integration={vercelIntegration}
|
||||
disabled={isBranch || !canUpdateVercelConnection}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
) : (
|
||||
<IntegrationConnectionHeader
|
||||
title={ConnectionHeaderTitle}
|
||||
className="pb-0"
|
||||
markdown={`Repository connections for Vercel`}
|
||||
/>
|
||||
)}
|
||||
<EmptyIntegrationConnection
|
||||
disabled={isBranch || !canCreateVercelConnection}
|
||||
onClick={() => onAddVercelConnection(vercelIntegration.id)}
|
||||
>
|
||||
Add new project connection
|
||||
</EmptyIntegrationConnection>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Button
|
||||
icon={<ExternalLink />}
|
||||
asChild={!isBranch}
|
||||
type="default"
|
||||
disabled={isBranch}
|
||||
>
|
||||
{isBranch ? (
|
||||
<p>Install Vercel Integration</p>
|
||||
) : (
|
||||
<Link href={integrationUrl} target="_blank" rel="noreferrer">
|
||||
Install Vercel Integration
|
||||
</Link>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<EmptyIntegrationConnection
|
||||
disabled={isBranch || !canCreateVercelConnection}
|
||||
onClick={() => onAddVercelConnection(vercelIntegration.id)}
|
||||
>
|
||||
Add new project connection
|
||||
</EmptyIntegrationConnection>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Button
|
||||
icon={<ExternalLink />}
|
||||
asChild={!isBranch}
|
||||
type="default"
|
||||
disabled={isBranch}
|
||||
>
|
||||
{isBranch ? (
|
||||
<p>Install Vercel Integration</p>
|
||||
) : (
|
||||
<Link href={integrationUrl} target="_blank" rel="noreferrer">
|
||||
Install Vercel Integration
|
||||
</Link>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{vercelProjectCount > 0 && vercelIntegration !== undefined && (
|
||||
<p className="text-sm text-foreground-light">
|
||||
Your Vercel connection can access {vercelProjectCount} Vercel projects. To change
|
||||
which projects Supabase may use, open your organization’s{' '}
|
||||
<InlineLink href={getIntegrationConfigurationUrl(vercelIntegration)}>
|
||||
Vercel integration settings
|
||||
</InlineLink>
|
||||
.
|
||||
</p>
|
||||
)}
|
||||
{VercelContentSectionBottom && (
|
||||
<Markdown
|
||||
extLinks
|
||||
content={VercelContentSectionBottom}
|
||||
className="text-foreground-lighter"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</ScaffoldSectionContent>
|
||||
</ScaffoldSection>
|
||||
|
||||
Reference in new issue
Block a user