import { SupportCategories } from '@supabase/shared-types/out/constants' import dayjs from 'dayjs' import { ExternalLink, Info } from 'lucide-react' import Link from 'next/link' import { SetStateAction } from 'react' import { toast } from 'sonner' import { number, object } from 'yup' import { useParams } from 'common' import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { DOCS_URL } from 'lib/constants' import { AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button, Form, InfoIcon, InputNumber, Modal, WarningIcon, } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' export interface DiskSizeConfigurationProps { visible: boolean hideModal: (value: SetStateAction) => void loading: boolean } const DiskSizeConfigurationModal = ({ visible, loading, hideModal, }: DiskSizeConfigurationProps) => { const { ref: projectRef } = useParams() const { data: organization } = useSelectedOrganizationQuery() const { data: project, isLoading: isLoadingProject } = useSelectedProjectQuery() const { lastDatabaseResizeAt } = project ?? {} const { data: projectSubscriptionData, isLoading: isLoadingSubscription } = useOrgSubscriptionQuery({ orgSlug: organization?.slug }, { enabled: visible }) const isLoading = isLoadingProject || isLoadingSubscription const timeTillNextAvailableDatabaseResize = lastDatabaseResizeAt === null ? 0 : 6 * 60 - dayjs().diff(lastDatabaseResizeAt, 'minutes') const isAbleToResizeDatabase = timeTillNextAvailableDatabaseResize <= 0 const formattedTimeTillNextAvailableResize = timeTillNextAvailableDatabaseResize < 60 ? `${timeTillNextAvailableDatabaseResize} minute(s)` : `${Math.floor(timeTillNextAvailableDatabaseResize / 60)} hours and ${ timeTillNextAvailableDatabaseResize % 60 } minute(s)` const { mutate: updateProjectUsage, isLoading: isUpdatingDiskSize } = useProjectDiskResizeMutation({ onSuccess: (res, variables) => { toast.success(`Successfully updated disk size to ${variables.volumeSize} GB`) hideModal(false) }, }) const confirmResetDbPass = async (values: { [prop: string]: any }) => { if (!projectRef) return console.error('Project ref is required') const volumeSize = values['new-disk-size'] updateProjectUsage({ projectRef, volumeSize }) } const currentDiskSize = project?.volumeSizeGb ?? 0 const maxDiskSize = 200 const INITIAL_VALUES = { 'new-disk-size': currentDiskSize, } const diskSizeValidationSchema = object({ 'new-disk-size': number() .required('Please enter a GB amount you want to resize the disk up to.') .min(Number(currentDiskSize ?? 0), `Must be more than ${currentDiskSize} GB`) // to do, update with max_disk_volume_size_gb .max(Number(maxDiskSize), 'Must not be more than 200 GB'), }) return ( hideModal(false)} hideFooter > {isLoading ? (
) : projectSubscriptionData?.usage_billing_enabled === true ? (
{() => currentDiskSize >= maxDiskSize ? ( Maximum manual disk size increase reached

You cannot manually expand the disk size any more than {maxDiskSize}GB. If you need more than this, contact us via support for help.

) : ( <> This operation is only possible every 6 hours
{isAbleToResizeDatabase ? `Upon updating your disk size, the next disk size update will only be available from ${dayjs().format( 'DD MMM YYYY, HH:mm (ZZ)' )}` : `Your database was last resized at ${dayjs(lastDatabaseResizeAt).format( 'DD MMM YYYY, HH:mm (ZZ)' )}. You can resize your database again in approximately ${formattedTimeTillNextAvailableResize}`}
) } ) : ( {projectSubscriptionData?.plan?.id === 'free' ? 'Disk size configuration is not available for projects on the Free Plan' : 'Disk size configuration is only available when the spend cap has been disabled'} {projectSubscriptionData?.plan?.id === 'free' ? (

If you are intending to use more than 500MB of disk space, then you will need to upgrade to at least the Pro Plan.

) : (

If you are intending to use more than 8GB of disk space, then you will need to disable your spend cap.

)}
)}
) } export default DiskSizeConfigurationModal