Files
supabase/apps/studio/components/ui/AlertError.tsx
T
Raminder SinghandJoshen Lim 65237597e4 feat: upgrade flow and other improvements (#43289)
This PR:

* Adds an upgrade flow to the stripe sync engine, allowing users to
upgrade to the latest version when it becomes available.
* When a new version of sync engine becomes available, users will see an
upgrade button instead of install button.
* Bumps `supabase-management-js` to version 2.0.2 and
`stripe-experiment-sync` to version 1.0.27.
* Uses `parseSchemaComment` and related logic from the
`stripe-experiment-sync` package in order to avoid writing duplicate
code in supabase ui.
* Allows installation/uninstallation to timeout after 5 minutes to avoid
these operations from getting stuck in case an error occurs in their
processing. This allows users to retry the operation, as opposed to the
older behaviour where the users always see a spinner on the
install/uninstall button and couldn't do anything.
* Remove the SSL enforcement admonition as it is no longer required.
Sync engine can now be installed with or without SSL enforcement
enabled.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-03-18 08:29:03 +00:00

112 lines
2.8 KiB
TypeScript

import { SupportCategories } from '@supabase/shared-types/out/constants'
import { SupportLink } from 'components/interfaces/Support/SupportLink'
import { useTrack } from 'lib/telemetry/track'
import { PropsWithChildren, useEffect, useRef } from 'react'
import { Button } from 'ui'
import { Admonition } from 'ui-patterns/admonition'
export interface AlertErrorProps {
projectRef?: string
subject?: string
description?: string
error?: { message: string } | null
layout?: 'vertical' | 'horizontal' | 'responsive'
className?: string
showIcon?: boolean
showInstructions?: boolean
showErrorPrefix?: boolean
additionalActions?: React.ReactNode
}
export const ContactSupportButton = ({
projectRef,
subject,
error,
}: {
projectRef?: string
subject?: string
error?: { message: string } | null
}) => {
return (
<Button asChild type="default" className="w-min">
<SupportLink
queryParams={{
category: SupportCategories.DASHBOARD_BUG,
projectRef,
subject,
error: error?.message,
}}
>
Contact support
</SupportLink>
</Button>
)
}
// [Joshen] To standardize the language for all error UIs
export const AlertError = ({
projectRef,
subject,
description = 'Try refreshing your browser, but if the issue persists for more than a few minutes, please reach out to us via support.',
error,
className,
showIcon = true,
layout = 'responsive',
showInstructions = true,
showErrorPrefix = true,
children,
additionalActions,
}: PropsWithChildren<AlertErrorProps>) => {
const track = useTrack()
const hasTrackedRef = useRef(false)
const formattedErrorMessage = error?.message?.includes('503')
? '503 Service Temporarily Unavailable'
: error?.message
useEffect(() => {
if (!hasTrackedRef.current) {
hasTrackedRef.current = true
if (Math.random() < 0.1) {
track('dashboard_error_created', {
source: 'admonition',
})
}
}
}, [track])
return (
<Admonition
type="warning"
layout={additionalActions ? 'vertical' : layout}
showIcon={showIcon}
title={subject}
description={
<>
{error?.message && (
<p>
{showErrorPrefix && 'Error: '}
{formattedErrorMessage}
</p>
)}
{showInstructions && <p>{description}</p>}
{children}
</>
}
actions={
additionalActions ? (
<>
{additionalActions}
<ContactSupportButton projectRef={projectRef} subject={subject} error={error} />
</>
) : (
<ContactSupportButton projectRef={projectRef} subject={subject} error={error} />
)
}
className={className}
/>
)
}
export default AlertError