mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 10:25:06 +03:00
* Moved sync status admonition to the settings page. * The **Install integration** and **Uninstall integration** buttons now show loading states during installation/uninstallation. * Made the content of the `StripeSyncChangesCard` dynamic based on the installation status. * Fixed a bug in which the comment on the stripe schema was not parsed correctly. Screenshots for each state: **Not installed** <img width="897" height="884" alt="image" src="https://github.com/user-attachments/assets/be567059-1deb-47d1-86df-af9f1c3b4fde" /> **Installing** <img width="897" height="884" alt="image" src="https://github.com/user-attachments/assets/664af71e-9407-4236-b4e5-1e7170a2f31f" /> **Install Error** <img width="897" height="933" alt="image" src="https://github.com/user-attachments/assets/0d6e4fbd-107a-4f95-8a5e-6bd1a1d6a1be" /> **Installed** <img width="897" height="901" alt="image" src="https://github.com/user-attachments/assets/e686e050-b3d2-42d0-bd3c-11d81540433a" /> **Uninstalling** <img width="897" height="901" alt="image" src="https://github.com/user-attachments/assets/7cd90d1c-ff83-4e7d-884e-4e340a1dcc75" /> **Uninstall Error** <img width="897" height="938" alt="image" src="https://github.com/user-attachments/assets/de0c1bc8-11c5-4c3f-a0ca-00b1f9e32ed3" /> **Settings Page (Sync Done)** <img width="897" height="572" alt="image" src="https://github.com/user-attachments/assets/ec5dd2a3-d183-42e1-8953-13bcf70082f5" /> **Settings Page (Sync in Progress)** <img width="897" height="572" alt="image" src="https://github.com/user-attachments/assets/7400c479-3e4f-4490-8857-414a93ebdc51" /> The idea behind these changes is that in future: * We allow users to configure sync interval from the settings page. * The overview page is mainly for the install/uninstall behaviour only, rest everything goes to the settings page. * We can show more granular progress during install/uninstall by showing what is being installed/uninstalled: migrations are running, edge functions are being deployed and so on. * We can show more accurate error messages: migrations succeeded but edge functions could not be deployed. This helps users troubleshoot and in the worst case recover via manual actions. --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
119 lines
4.0 KiB
TypeScript
119 lines
4.0 KiB
TypeScript
import { useParams } from 'common'
|
|
import { useDatabaseExtensionsQuery } from 'data/database-extensions/database-extensions-query'
|
|
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
|
|
import { PropsWithChildren, ReactNode } from 'react'
|
|
import { Badge, Card, CardContent, cn, Separator } from 'ui'
|
|
|
|
import { INTEGRATIONS } from '../Landing/Integrations.constants'
|
|
import { BuiltBySection } from './BuildBySection'
|
|
import { MarkdownContent } from './MarkdownContent'
|
|
import { MissingExtensionAlert } from './MissingExtensionAlert'
|
|
|
|
interface IntegrationOverviewTabProps {
|
|
actions?: ReactNode
|
|
status?: string | ReactNode
|
|
alert?: ReactNode
|
|
}
|
|
|
|
export const IntegrationOverviewTab = ({
|
|
actions,
|
|
alert,
|
|
status,
|
|
children,
|
|
}: PropsWithChildren<IntegrationOverviewTabProps>) => {
|
|
const { id } = useParams()
|
|
const { data: project } = useSelectedProjectQuery()
|
|
|
|
const integration = INTEGRATIONS.find((i) => i.id === id)
|
|
|
|
const { data: extensions } = useDatabaseExtensionsQuery({
|
|
projectRef: project?.ref,
|
|
connectionString: project?.connectionString,
|
|
})
|
|
|
|
if (!integration) {
|
|
return <div>Unsupported integration type</div>
|
|
}
|
|
|
|
const dependsOnExtension = (integration.requiredExtensions ?? []).length > 0
|
|
|
|
const installableExtensions = (extensions ?? []).filter((ext) =>
|
|
(integration.requiredExtensions ?? []).includes(ext.name)
|
|
)
|
|
const hasToInstallExtensions = installableExtensions.some((x) => !x.installed_version)
|
|
|
|
// The integration requires extensions that are not available to install on the current database image
|
|
const hasMissingExtensions =
|
|
installableExtensions.length !== integration.requiredExtensions.length
|
|
|
|
return (
|
|
<div className="flex flex-col gap-8 py-10">
|
|
<BuiltBySection integration={integration} status={status} />
|
|
|
|
{!!alert && <div className="px-10 max-w-4xl">{alert}</div>}
|
|
|
|
<MarkdownContent key={integration.id} integrationId={integration.id} />
|
|
|
|
<Separator />
|
|
|
|
{dependsOnExtension && (
|
|
<div className="px-4 md:px-10 max-w-4xl flex flex-col gap-y-4">
|
|
<h4>Required extensions</h4>
|
|
<Card>
|
|
<CardContent className="p-0">
|
|
<ul className="text-foreground-light text-sm">
|
|
{(integration.requiredExtensions ?? []).map((requiredExtension, idx) => {
|
|
const extension = (extensions ?? []).find((ext) => ext.name === requiredExtension)
|
|
const isInstalled = !!extension?.installed_version
|
|
const isLastRow = idx === (integration.requiredExtensions?.length ?? 0) - 1
|
|
|
|
return (
|
|
<li
|
|
key={requiredExtension}
|
|
className={cn(
|
|
'flex items-center justify-between gap-3 py-2 px-3',
|
|
!isLastRow ? 'border-b' : ''
|
|
)}
|
|
>
|
|
<code className="text-xs">{requiredExtension}</code>
|
|
|
|
<div className="shrink-0">
|
|
{extension ? (
|
|
isInstalled ? (
|
|
<Badge>Installed</Badge>
|
|
) : (
|
|
<MissingExtensionAlert extension={extension} />
|
|
)
|
|
) : (
|
|
<span className="text-foreground-muted">Unavailable</span>
|
|
)}
|
|
</div>
|
|
</li>
|
|
)
|
|
})}
|
|
</ul>
|
|
|
|
{hasMissingExtensions && (
|
|
<div className="py-3 px-4 border-t">{integration.missingExtensionsAlert}</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)}
|
|
|
|
{!!actions && (
|
|
<div
|
|
aria-disabled={hasToInstallExtensions}
|
|
className={cn(
|
|
'px-10 max-w-4xl',
|
|
hasToInstallExtensions && 'opacity-25 [&_button]:pointer-events-none'
|
|
)}
|
|
>
|
|
{actions}
|
|
</div>
|
|
)}
|
|
{children}
|
|
</div>
|
|
)
|
|
}
|