mirror of
https://github.com/supabase/supabase.git
synced 2026-10-13 13:19:09 +03:00
integrations redesign
This commit is contained in:
1 parent
7e44382aec
commit
9e72ee2881
4 files changed
+148
-166
No files matched your search
+37
-38
@@ -3,10 +3,13 @@ import { useMemo } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import {
|
||||
ScaffoldContainer,
|
||||
ScaffoldDescription,
|
||||
ScaffoldSection,
|
||||
ScaffoldSectionContent,
|
||||
ScaffoldSectionDescription,
|
||||
ScaffoldSectionDetail,
|
||||
ScaffoldSectionTitle,
|
||||
ScaffoldTitle,
|
||||
} from 'components/layouts/Scaffold'
|
||||
import NoPermission from 'components/ui/NoPermission'
|
||||
import UpgradeToPro from 'components/ui/UpgradeToPro'
|
||||
@@ -21,7 +24,7 @@ import GitHubIntegrationConnectionForm from './GitHubIntegrationConnectionForm'
|
||||
const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => {
|
||||
return (
|
||||
<img
|
||||
className="border rounded-lg shadow w-full sm:w-48 mt-6 border-body"
|
||||
className="border rounded-lg shadow w-full sm:w-32 border-body"
|
||||
src={`${BASE_PATH}/img/integrations/covers/${title}-cover.png`}
|
||||
alt={`${title} cover`}
|
||||
/>
|
||||
@@ -51,44 +54,40 @@ const GitHubSection = () => {
|
||||
const GitHubTitle = `GitHub Integration`
|
||||
|
||||
return (
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldSection>
|
||||
<ScaffoldSectionDetail title={GitHubTitle}>
|
||||
<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>
|
||||
<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>
|
||||
{promptProPlanUpgrade && (
|
||||
<div className="mb-6">
|
||||
<UpgradeToPro
|
||||
primaryText="Upgrade to unlock GitHub integration"
|
||||
secondaryText="Connect your GitHub repository to automatically sync preview branches and deploy changes."
|
||||
source="github-integration"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={cn(promptProPlanUpgrade && 'opacity-25 pointer-events-none')}>
|
||||
<GitHubIntegrationConnectionForm connection={existingConnection} />
|
||||
</div>
|
||||
<ScaffoldSection isFullWidth>
|
||||
<div className="flex items-center gap-6 mb-8">
|
||||
<IntegrationImageHandler title="github" />
|
||||
<div>
|
||||
<ScaffoldSectionTitle>{GitHubTitle}</ScaffoldSectionTitle>
|
||||
<ScaffoldSectionDescription className="mb-0 mt-1 max-w-2xl">
|
||||
Connect your GitHub repositories to sync preview branches, keep production in sync, and
|
||||
automatically create preview branches for pull requests.
|
||||
</ScaffoldSectionDescription>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{isLoadingPermissions ? (
|
||||
<GenericSkeletonLoader />
|
||||
) : !canReadGitHubConnection ? (
|
||||
<NoPermission resourceText="view this organization's GitHub connections" />
|
||||
) : (
|
||||
<div>
|
||||
{promptProPlanUpgrade && (
|
||||
<div className="mb-6">
|
||||
<UpgradeToPro
|
||||
primaryText="Upgrade to unlock GitHub integration"
|
||||
secondaryText="Connect your GitHub repository to automatically sync preview branches and deploy changes."
|
||||
source="github-integration"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={cn(promptProPlanUpgrade && 'opacity-25 pointer-events-none')}>
|
||||
<GitHubIntegrationConnectionForm connection={existingConnection} />
|
||||
</div>
|
||||
)}
|
||||
</ScaffoldSectionContent>
|
||||
</ScaffoldSection>
|
||||
</ScaffoldContainer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</ScaffoldSection>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
import SidePanelVercelProjectLinker from 'components/interfaces/Organization/IntegrationSettings/SidePanelVercelProjectLinker'
|
||||
import { ScaffoldContainer, ScaffoldDivider } from 'components/layouts/Scaffold'
|
||||
import { ScaffoldDivider, ScaffoldSection } from 'components/layouts/Scaffold'
|
||||
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
|
||||
import { useProjectByRefQuery, useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { BASE_PATH } from 'lib/constants'
|
||||
@@ -12,7 +12,7 @@ import VercelSection from './VercelIntegration/VercelSection'
|
||||
export const IntegrationImageHandler = ({ title }: { title: 'vercel' | 'github' }) => {
|
||||
return (
|
||||
<img
|
||||
className="border rounded-lg shadow w-full sm:w-48 mt-6 border-body"
|
||||
className="border rounded-lg shadow w-full sm:w-32 border-body"
|
||||
src={`${BASE_PATH}/img/integrations/covers/${title}-cover.png`}
|
||||
alt={`${title} cover`}
|
||||
/>
|
||||
@@ -29,7 +29,7 @@ const IntegrationSettings = () => {
|
||||
return (
|
||||
<>
|
||||
{isBranch && (
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldSection isFullWidth>
|
||||
<Alert_Shadcn_ variant="default" className="mt-6">
|
||||
<WarningIcon />
|
||||
<AlertTitle_Shadcn_>
|
||||
@@ -43,12 +43,11 @@ const IntegrationSettings = () => {
|
||||
.
|
||||
</AlertDescription_Shadcn_>
|
||||
</Alert_Shadcn_>
|
||||
</ScaffoldContainer>
|
||||
</ScaffoldSection>
|
||||
)}
|
||||
<GitHubSection />
|
||||
{showVercelIntegration && (
|
||||
<>
|
||||
<ScaffoldDivider />
|
||||
<VercelSection isProjectScoped={true} />
|
||||
<SidePanelVercelProjectLinker />
|
||||
</>
|
||||
|
||||
+100
-108
@@ -12,10 +12,9 @@ import {
|
||||
} from 'components/interfaces/Integrations/VercelGithub/IntegrationPanels'
|
||||
import { Markdown } from 'components/interfaces/Markdown'
|
||||
import {
|
||||
ScaffoldContainer,
|
||||
ScaffoldSection,
|
||||
ScaffoldSectionContent,
|
||||
ScaffoldSectionDetail,
|
||||
ScaffoldSectionTitle,
|
||||
ScaffoldSectionDescription,
|
||||
} from 'components/layouts/Scaffold'
|
||||
import NoPermission from 'components/ui/NoPermission'
|
||||
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
|
||||
@@ -32,7 +31,7 @@ import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
||||
import { pluralize } from 'lib/helpers'
|
||||
import { getIntegrationConfigurationUrl } from 'lib/integration-utils'
|
||||
import { useSidePanelsStateSnapshot } from 'state/side-panels'
|
||||
import { Button, cn } from 'ui'
|
||||
import { Button, Card, CardContent, cn } from 'ui'
|
||||
import { IntegrationImageHandler } from '../IntegrationsSettings'
|
||||
import VercelIntegrationConnectionForm from './VercelIntegrationConnectionForm'
|
||||
|
||||
@@ -114,22 +113,9 @@ const VercelSection = ({ isProjectScoped }: { isProjectScoped: boolean }) => {
|
||||
[deleteVercelConnection, org?.slug]
|
||||
)
|
||||
|
||||
// Markdown Content
|
||||
// Section title
|
||||
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
|
||||
? `
|
||||
@@ -159,103 +145,109 @@ You can change the scope of the access for Supabase by configuring
|
||||
)} `
|
||||
|
||||
return (
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldSection>
|
||||
<ScaffoldSectionDetail title={VercelTitle}>
|
||||
<Markdown content={VercelDetailsSection} />
|
||||
<IntegrationImageHandler title="vercel" />
|
||||
</ScaffoldSectionDetail>
|
||||
<ScaffoldSectionContent>
|
||||
{isLoadingPermissions ? (
|
||||
<GenericSkeletonLoader />
|
||||
) : !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 ? (
|
||||
<>
|
||||
<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>
|
||||
</>
|
||||
) : (
|
||||
<ScaffoldSection isFullWidth>
|
||||
<div className="flex items-center gap-6 mb-8">
|
||||
<IntegrationImageHandler title="vercel" />
|
||||
<div>
|
||||
<ScaffoldSectionTitle>{VercelTitle}</ScaffoldSectionTitle>
|
||||
<ScaffoldSectionDescription className="mb-0 mt-1 max-w-2xl">
|
||||
Connect your Vercel team to keep environment variables in sync across linked projects,
|
||||
and link multiple Vercel projects to the same Supabase project.
|
||||
</ScaffoldSectionDescription>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{isLoadingPermissions ? (
|
||||
<GenericSkeletonLoader />
|
||||
) : !canReadVercelConnection ? (
|
||||
<NoPermission resourceText="view this organization's Vercel connections" />
|
||||
) : (
|
||||
<>
|
||||
{vercelIntegration ? (
|
||||
<div key={vercelIntegration.id}>
|
||||
<IntegrationInstallation title={'Vercel'} integration={vercelIntegration} />
|
||||
{connections.length > 0 ? (
|
||||
<>
|
||||
<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>
|
||||
) : (
|
||||
<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>
|
||||
) : (
|
||||
<Card>
|
||||
<CardContent className="flex flex-col items-center justify-center py-12">
|
||||
<p className="text-sm text-center">Install Vercel Integration</p>
|
||||
<p className="text-sm text-center text-foreground-light mb-4">
|
||||
Connect your Vercel account to link projects and sync environment variables.
|
||||
</p>
|
||||
{isBranch ? (
|
||||
<Button type="default" disabled>
|
||||
Install Vercel Integration
|
||||
</Button>
|
||||
) : (
|
||||
<Button icon={<ExternalLink />} asChild type="default">
|
||||
<Link href={integrationUrl} target="_blank" rel="noreferrer">
|
||||
Install Vercel Integration
|
||||
</Link>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{VercelContentSectionBottom && (
|
||||
<Markdown
|
||||
extLinks
|
||||
content={VercelContentSectionBottom}
|
||||
className="text-foreground-lighter"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ScaffoldSectionContent>
|
||||
</ScaffoldSection>
|
||||
</ScaffoldContainer>
|
||||
</Button>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{VercelContentSectionBottom && (
|
||||
<Markdown
|
||||
extLinks
|
||||
content={VercelContentSectionBottom}
|
||||
className="text-foreground-lighter"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</ScaffoldSection>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,23 @@
|
||||
import IntegrationSettings from 'components/interfaces/Settings/Integrations/IntegrationsSettings'
|
||||
import DefaultLayout from 'components/layouts/DefaultLayout'
|
||||
import SettingsLayout from 'components/layouts/ProjectSettingsLayout/SettingsLayout'
|
||||
import {
|
||||
ScaffoldContainer,
|
||||
ScaffoldDivider,
|
||||
ScaffoldHeader,
|
||||
ScaffoldTitle,
|
||||
} from 'components/layouts/Scaffold'
|
||||
import { PageLayout } from 'components/layouts/PageLayout/PageLayout'
|
||||
import { ScaffoldContainer } from 'components/layouts/Scaffold'
|
||||
import type { NextPageWithLayout } from 'types'
|
||||
|
||||
const OrgIntegrationSettings: NextPageWithLayout = () => {
|
||||
return (
|
||||
<>
|
||||
<ScaffoldContainer>
|
||||
<ScaffoldHeader>
|
||||
<ScaffoldTitle>Integrations</ScaffoldTitle>
|
||||
</ScaffoldHeader>
|
||||
</ScaffoldContainer>
|
||||
<ScaffoldDivider />
|
||||
<ScaffoldContainer bottomPadding>
|
||||
<IntegrationSettings />
|
||||
</>
|
||||
</ScaffoldContainer>
|
||||
)
|
||||
}
|
||||
|
||||
OrgIntegrationSettings.getLayout = (page) => (
|
||||
<DefaultLayout>
|
||||
<SettingsLayout>{page}</SettingsLayout>
|
||||
<SettingsLayout title="Integrations">
|
||||
<PageLayout title="Integrations">{page}</PageLayout>
|
||||
</SettingsLayout>
|
||||
</DefaultLayout>
|
||||
)
|
||||
export default OrgIntegrationSettings
|
||||
Reference in new issue
Block a user