mirror of
https://github.com/supabase/supabase.git
synced 2026-10-09 19:35:06 +03:00
## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? When a user selects IO2 on compute upgrade, the `0/MB` isn't quite correct, whilst the costa delta of $0 is correct. We will hide the row as it adds noise. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed disk management UI to correctly display the throughput configuration row only when selecting GP3 storage type, ensuring the interface accurately reflects available options for the selected storage type. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
188 lines
6.2 KiB
TypeScript
188 lines
6.2 KiB
TypeScript
import { useMemo } from 'react'
|
|
import { UseFormReturn } from 'react-hook-form'
|
|
|
|
import { DiskStorageSchemaType } from '../DiskManagement.schema'
|
|
import {
|
|
calculateComputeSizePrice,
|
|
calculateDiskSizePrice,
|
|
calculateIOPSPrice,
|
|
calculateThroughputPrice,
|
|
getAvailableComputeOptions,
|
|
mapAddOnVariantIdToComputeSize,
|
|
} from '../DiskManagement.utils'
|
|
import { DiskType } from '../ui/DiskManagement.constants'
|
|
import { useProjectAddonsQuery } from '@/data/subscriptions/project-addons-query'
|
|
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
|
import {
|
|
useIsAwsNimbusCloudProvider,
|
|
useSelectedProjectQuery,
|
|
} from '@/hooks/misc/useSelectedProject'
|
|
|
|
export function useDiskManagementReviewChanges(
|
|
form: UseFormReturn<DiskStorageSchemaType>,
|
|
numReplicas: number
|
|
) {
|
|
const { data: project } = useSelectedProjectQuery()
|
|
const { data: org } = useSelectedOrganizationQuery()
|
|
const isAwsNimbus = useIsAwsNimbusCloudProvider()
|
|
const { data: addons } = useProjectAddonsQuery({ projectRef: project?.ref })
|
|
|
|
const isAwsK8sProject = project?.cloud_provider === 'AWS_K8S'
|
|
const planId = org?.plan.id ?? 'free'
|
|
|
|
const availableAddons = useMemo(() => addons?.available_addons ?? [], [addons])
|
|
const availableOptions = useMemo(
|
|
() => getAvailableComputeOptions(availableAddons, project?.cloud_provider),
|
|
[availableAddons, project?.cloud_provider]
|
|
)
|
|
|
|
// --- Prices ---
|
|
|
|
const computeSizePrice = calculateComputeSizePrice({
|
|
availableOptions,
|
|
oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
|
|
newComputeSize: form.getValues('computeSize'),
|
|
plan: planId,
|
|
})
|
|
const diskSizePrice = calculateDiskSizePrice({
|
|
planId,
|
|
oldSize: form.formState.defaultValues?.totalSize || 0,
|
|
oldStorageType: form.formState.defaultValues?.storageType as DiskType,
|
|
newSize: form.getValues('totalSize'),
|
|
newStorageType: form.getValues('storageType') as DiskType,
|
|
numReplicas,
|
|
})
|
|
const iopsPrice = calculateIOPSPrice({
|
|
oldStorageType: form.formState.defaultValues?.storageType as DiskType,
|
|
oldProvisionedIOPS: form.formState.defaultValues?.provisionedIOPS || 0,
|
|
newStorageType: form.getValues('storageType') as DiskType,
|
|
newProvisionedIOPS: form.getValues('provisionedIOPS'),
|
|
numReplicas,
|
|
})
|
|
const throughputPrice = calculateThroughputPrice({
|
|
storageType: form.getValues('storageType') as DiskType,
|
|
newThroughput: form.getValues('throughput') || 0,
|
|
oldThroughput: form.formState.defaultValues?.throughput || 0,
|
|
numReplicas,
|
|
})
|
|
|
|
const totalBeforePrice =
|
|
Number(computeSizePrice.oldPrice) +
|
|
Number(diskSizePrice.oldPrice) +
|
|
Number(iopsPrice.oldPrice) +
|
|
Number(throughputPrice.oldPrice)
|
|
|
|
const totalAfterPrice =
|
|
Number(computeSizePrice.newPrice) +
|
|
Number(diskSizePrice.newPrice) +
|
|
Number(iopsPrice.newPrice) +
|
|
Number(throughputPrice.newPrice)
|
|
|
|
// --- Change flags ---
|
|
|
|
const hasComputeChanges =
|
|
form.formState.defaultValues?.computeSize !== form.getValues('computeSize')
|
|
|
|
const hasTotalSizeChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.totalSize !== form.getValues('totalSize')
|
|
|
|
const hasStorageTypeChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.storageType !== form.getValues('storageType')
|
|
|
|
const hasThroughputChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.throughput !== form.getValues('throughput')
|
|
|
|
const hasIOPSChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.provisionedIOPS !== form.getValues('provisionedIOPS')
|
|
|
|
const hasGrowthPercentChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.growthPercent !== form.getValues('growthPercent')
|
|
|
|
const hasMinIncrementChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.minIncrementGb !== form.getValues('minIncrementGb')
|
|
|
|
const hasMaxSizeChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.maxSizeGb !== form.getValues('maxSizeGb')
|
|
|
|
// --- Derived predicates ---
|
|
|
|
const storageTypeAfter = form.getValues('storageType') as DiskType
|
|
|
|
// Show hero whenever any line-item price actually changes, not just compute
|
|
const anyBillableDiskChange =
|
|
Number(diskSizePrice.newPrice) !== Number(diskSizePrice.oldPrice) ||
|
|
Number(iopsPrice.newPrice) !== Number(iopsPrice.oldPrice) ||
|
|
Number(throughputPrice.newPrice) !== Number(throughputPrice.oldPrice)
|
|
|
|
// Show cooldown warning whenever any disk attribute that enforces the 4-hour lock changes
|
|
const anyDiskAttributeChange = hasIOPSChanges || hasStorageTypeChanges || hasTotalSizeChanges
|
|
|
|
// Throughput is only a user-configurable, separately-billed attribute for GP3. For IO2 it is
|
|
// derived from provisioned IOPS (0.256 MiB/s per IOPS) and isn't surfaced as its own value, so
|
|
// the form clears it to 0 — rendering a misleading "→ 0 MB/s". Only show the row when the
|
|
// resulting storage type is GP3; any GP3→IO2 throughput price delta still lands in the total.
|
|
const showThroughputRow =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
storageTypeAfter === 'gp3' &&
|
|
(hasThroughputChanges || hasStorageTypeChanges)
|
|
|
|
const hasAnyBreakdownRows =
|
|
hasComputeChanges ||
|
|
hasStorageTypeChanges ||
|
|
hasIOPSChanges ||
|
|
showThroughputRow ||
|
|
hasTotalSizeChanges ||
|
|
hasGrowthPercentChanges ||
|
|
hasMinIncrementChanges ||
|
|
hasMaxSizeChanges
|
|
|
|
// --- Labels ---
|
|
|
|
const oldComputeLabel = mapAddOnVariantIdToComputeSize(
|
|
form.formState.defaultValues?.computeSize ?? 'ci_nano'
|
|
)
|
|
const newComputeLabel = mapAddOnVariantIdToComputeSize(form.getValues('computeSize'))
|
|
|
|
return {
|
|
// prices
|
|
computeSizePrice,
|
|
diskSizePrice,
|
|
iopsPrice,
|
|
throughputPrice,
|
|
totalBeforePrice,
|
|
totalAfterPrice,
|
|
// change flags
|
|
hasComputeChanges,
|
|
hasTotalSizeChanges,
|
|
hasStorageTypeChanges,
|
|
hasThroughputChanges,
|
|
hasIOPSChanges,
|
|
hasGrowthPercentChanges,
|
|
hasMinIncrementChanges,
|
|
hasMaxSizeChanges,
|
|
// derived predicates
|
|
anyBillableDiskChange,
|
|
anyDiskAttributeChange,
|
|
showThroughputRow,
|
|
hasAnyBreakdownRows,
|
|
// labels
|
|
oldComputeLabel,
|
|
newComputeLabel,
|
|
}
|
|
}
|