mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
155 lines
5.3 KiB
TypeScript
155 lines
5.3 KiB
TypeScript
import { MinusCircle, PauseCircle } from 'lucide-react'
|
|
|
|
import type { ProjectInfo } from 'data/projects/projects-query'
|
|
import type { OrgSubscription, ProjectAddon } from 'data/subscriptions/types'
|
|
import { PricingInformation } from 'shared-data'
|
|
import { Modal } from 'ui'
|
|
import { Admonition } from 'ui-patterns'
|
|
|
|
export interface DowngradeModalProps {
|
|
visible: boolean
|
|
selectedPlan?: PricingInformation
|
|
subscription?: OrgSubscription
|
|
onClose: () => void
|
|
onConfirm: () => void
|
|
projects: ProjectInfo[]
|
|
}
|
|
|
|
const ProjectDowngradeListItem = ({ projectAddon }: { projectAddon: ProjectAddon }) => {
|
|
const needsRestart = projectAddon.addons.find((addon) => addon.type === 'compute_instance')
|
|
|
|
/**
|
|
* We do not include Log Drains and Advanced MFA Phone for the following reasons:
|
|
* 1. These addons are not removed automatically. Instead, users have to remove the respective configuration themselves
|
|
* 2. It's not obvious to users that Log Drains and MFA Phone are addons
|
|
*/
|
|
const relevantAddonsToList = projectAddon.addons.filter(
|
|
(addon) => !['log_drain', 'auth_mfa_phone'].includes(addon.type)
|
|
)
|
|
|
|
const addonNames = relevantAddonsToList.map((addon) => {
|
|
if (addon.type === 'compute_instance') return `${addon.variant.name} Compute Instance`
|
|
return addon.variant.name
|
|
})
|
|
|
|
return (
|
|
<li className="list-disc ml-6">
|
|
{projectAddon.name}: {addonNames.join(', ')} will be removed.
|
|
{needsRestart ? (
|
|
<>
|
|
{' '}
|
|
Project will also <span className="font-bold">need to be restarted</span> due to change in
|
|
compute instance
|
|
</>
|
|
) : (
|
|
''
|
|
)}
|
|
</li>
|
|
)
|
|
}
|
|
|
|
const DowngradeModal = ({
|
|
visible,
|
|
selectedPlan,
|
|
subscription,
|
|
onClose,
|
|
onConfirm,
|
|
projects,
|
|
}: DowngradeModalProps) => {
|
|
// Filter out the micro addon as we're dealing with that separately
|
|
const previousProjectAddons =
|
|
subscription?.project_addons.flatMap((projectAddons) => {
|
|
const addons = projectAddons.addons.filter((it) => it.variant.identifier !== 'ci_micro')
|
|
if (!addons.length) {
|
|
return []
|
|
} else {
|
|
return {
|
|
...projectAddons,
|
|
// Overwrite addons, filtered out the micro addon
|
|
addons,
|
|
}
|
|
}
|
|
}) || []
|
|
|
|
const hasInstancesOnMicro = projects.some((project) => project.infra_compute_size === 'micro')
|
|
|
|
return (
|
|
<Modal
|
|
size="large"
|
|
alignFooter="right"
|
|
variant="warning"
|
|
visible={visible}
|
|
onCancel={onClose}
|
|
onConfirm={onConfirm}
|
|
header={`Confirm to downgrade to ${selectedPlan?.name} plan`}
|
|
>
|
|
<Modal.Content>
|
|
<div className="space-y-2">
|
|
<Admonition
|
|
type="warning"
|
|
title="Downgrading to the Free Plan will lead to reductions in your organization's quota"
|
|
description="If you're already past the limits of the Free Plan, your projects could become
|
|
unresponsive or enter read only mode."
|
|
/>
|
|
|
|
{((previousProjectAddons.length ?? 0) > 0 || hasInstancesOnMicro) && (
|
|
<Admonition type="warning" title="Projects affected by the downgrade">
|
|
<ul className="space-y-1 max-h-[100px] overflow-y-auto">
|
|
{previousProjectAddons.map((project) => (
|
|
<ProjectDowngradeListItem key={project.ref} projectAddon={project} />
|
|
))}
|
|
|
|
{projects
|
|
.filter((it) => it.infra_compute_size === 'micro')
|
|
.map((project) => (
|
|
<li className="list-disc ml-6" key={project.ref}>
|
|
{project.name}: Compute will be downgraded. Project will also{' '}
|
|
<span className="font-bold">need to be restarted</span>.
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</Admonition>
|
|
)}
|
|
</div>
|
|
|
|
<ul className="mt-4 space-y-5 text-sm">
|
|
<li className="flex items-center gap-3">
|
|
<PauseCircle size={18} />
|
|
<span>Projects will be paused after a week of inactivity</span>
|
|
</li>
|
|
|
|
<li className="flex items-center gap-3 mb-2">
|
|
<MinusCircle size={18} />
|
|
<span>Add ons from all projects under this organization will be removed.</span>
|
|
</li>
|
|
|
|
<li className="flex gap-3">
|
|
<div>
|
|
<strong>Before you downgrade to the {selectedPlan?.name} plan, consider:</strong>
|
|
<ul className="space-y-2 mt-2">
|
|
<li className="list-disc ml-6 text-foreground-light">
|
|
Your projects no longer require their respective add ons.
|
|
</li>
|
|
<li className="list-disc ml-6 text-foreground-light">
|
|
Your resource consumption are well within the {selectedPlan?.name} plan's quota.
|
|
</li>
|
|
<li className="list-disc ml-6 text-foreground-light">
|
|
Alternatively, you may also transfer projects across organizations.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
{subscription?.billing_via_partner === true && subscription.billing_partner === 'fly' && (
|
|
<p className="mt-4 text-sm">
|
|
Your organization will be downgraded at the end of your current billing cycle.
|
|
</p>
|
|
)}
|
|
</Modal.Content>
|
|
</Modal>
|
|
)
|
|
}
|
|
|
|
export default DowngradeModal
|