Home / Function/ DiskManagementReviewAndSubmitDialog() — supabase Function Reference

DiskManagementReviewAndSubmitDialog() — supabase Function Reference

Architecture documentation for the DiskManagementReviewAndSubmitDialog() function in DiskManagementReviewAndSubmitDialog.tsx from the supabase codebase.

Entity Profile

Dependency Diagram

graph TD
  123688a6_401c_ee61_a6d4_f7478222cf84["DiskManagementReviewAndSubmitDialog()"]
  615adce6_538e_53e8_d90c_1aa23c10d40c["getAvailableComputeOptions()"]
  123688a6_401c_ee61_a6d4_f7478222cf84 -->|calls| 615adce6_538e_53e8_d90c_1aa23c10d40c
  e956c7de_38d1_c092_0776_7cdf6ab921bb["calculateComputeSizePrice()"]
  123688a6_401c_ee61_a6d4_f7478222cf84 -->|calls| e956c7de_38d1_c092_0776_7cdf6ab921bb
  d41389fd_6aaa_c3c5_2a46_1dc46dac56c5["calculateDiskSizePrice()"]
  123688a6_401c_ee61_a6d4_f7478222cf84 -->|calls| d41389fd_6aaa_c3c5_2a46_1dc46dac56c5
  358afe46_09fa_dd8b_54eb_6c8758ac6b45["calculateIOPSPrice()"]
  123688a6_401c_ee61_a6d4_f7478222cf84 -->|calls| 358afe46_09fa_dd8b_54eb_6c8758ac6b45
  82fbd301_9a53_6173_3379_5ab985e7d49c["calculateThroughputPrice()"]
  123688a6_401c_ee61_a6d4_f7478222cf84 -->|calls| 82fbd301_9a53_6173_3379_5ab985e7d49c
  b53797de_ebc6_57df_780c_1f609f8111e4["mapAddOnVariantIdToComputeSize()"]
  123688a6_401c_ee61_a6d4_f7478222cf84 -->|calls| b53797de_ebc6_57df_780c_1f609f8111e4
  style 123688a6_401c_ee61_a6d4_f7478222cf84 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

apps/studio/components/interfaces/DiskManagement/DiskManagementReviewAndSubmitDialog.tsx lines 140–455

export const DiskManagementReviewAndSubmitDialog = ({
  isDialogOpen,
  setIsDialogOpen,
  disabled,
  form,
  numReplicas,
  loading,
  onSubmit,
  message,
  buttonSize = 'medium',
}: DiskSizeMeterProps) => {
  const { data: project } = useSelectedProjectQuery()
  const { data: org } = useSelectedOrganizationQuery()
  const isAwsNimbus = useIsAwsNimbusCloudProvider()

  const isAwsK8sProject = project?.cloud_provider === 'AWS_K8S'

  const { formState, getValues } = form

  const { can: canUpdateDiskConfiguration } = useAsyncCheckPermissions(
    PermissionAction.UPDATE,
    'projects',
    {
      resource: {
        project_id: project?.id,
      },
    }
  )

  /**
   * Queries
   * */
  const {
    data: addons,
    // request deps in Form handle errors and loading
  } = useProjectAddonsQuery({ projectRef: project?.ref })

  const planId = org?.plan.id ?? 'free'
  const isDirty = !!Object.keys(form.formState.dirtyFields).length
  const replicaTooltipText = `Price change includes primary database and ${numReplicas} replica${numReplicas > 1 ? 's' : ''}`

  const availableAddons = useMemo(() => {
    return addons?.available_addons ?? []
  }, [addons])
  const availableOptions = useMemo(() => {
    return getAvailableComputeOptions(availableAddons, project?.cloud_provider)
  }, [availableAddons, project?.cloud_provider])

  const computeSizePrice = calculateComputeSizePrice({
    availableOptions,
    oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
    newComputeSize: form.getValues('computeSize'),
    plan: org?.plan.id ?? 'free',
  })
  const diskSizePrice = calculateDiskSizePrice({
    planId: planId,
    oldSize: formState.defaultValues?.totalSize || 0,
    oldStorageType: formState.defaultValues?.storageType as DiskType,
    newSize: getValues('totalSize'),
    newStorageType: 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 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')

  const hasDiskConfigChanges =
    hasIOPSChanges ||
    (hasThroughputChanges && form.getValues('storageType') === 'gp3') ||
    hasTotalSizeChanges

  return (
    <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
      <DialogTrigger asChild>
        <ButtonTooltip
          size={buttonSize}
          htmlType="submit"
          type="primary"
          onClick={async (e) => {
            e.preventDefault()
            const isValid = await form.trigger()
            if (isValid) setIsDialogOpen(true)
          }}
          disabled={disabled || !isDirty}
          tooltip={{
            content: {
              side: 'bottom',
              text: !canUpdateDiskConfiguration
                ? 'You need additional permissions to update disk configuration'
                : disabled
                  ? 'Current form values are invalid'
                  : undefined,
            },
          }}
        >
          Review changes
        </ButtonTooltip>
      </DialogTrigger>
      <DialogContent className="min-w-[620px]">
        <DialogHeader>
          <DialogTitle>Review changes</DialogTitle>
          <DialogDescription>Changes will be applied shortly once confirmed.</DialogDescription>
        </DialogHeader>
        <DialogSectionSeparator />
        {(hasComputeChanges || hasDiskConfigChanges) && (
          <>
            <div className="flex flex-col gap-2 p-5">
              <DiskMangementRestartRequiredSection
                visible={hasComputeChanges}
                title="Resizing your Compute will trigger a project restart"
                description="Project will restart automatically on confirmation."
              />
              <DiskMangementCoolDownSection visible={hasDiskConfigChanges} />
            </div>
            <DialogSectionSeparator />
          </>
        )}
        <Table>
          <TableHeader className="font-mono uppercase text-xs [&_th]:h-auto [&_th]:pb-2 [&_th]:pt-4">
            <TableHeaderRow />
          </TableHeader>
          <TableBody className="[&_td]:py-0 [&_tr]:h-[50px] [&_tr]:border-dotted">
            {hasComputeChanges && (
              <TableDataRow
                attribute="Compute size"
                defaultValue={mapAddOnVariantIdToComputeSize(
                  form.formState.defaultValues?.computeSize ?? 'ci_nano'
                )}
                newValue={mapAddOnVariantIdToComputeSize(form.getValues('computeSize'))}
                unit="-"
                beforePrice={Number(computeSizePrice.oldPrice)}
                afterPrice={Number(computeSizePrice.newPrice)}
                upgradeIncluded={
                  org?.plan.id !== 'free' &&
                  project?.infra_compute_size === 'nano' &&
                  form.getValues('computeSize') === 'ci_micro'
                }
              />
            )}
            {hasStorageTypeChanges && (
              <TableDataRow
                hidePrice
                attribute="Storage Type"
                defaultValue={form.formState.defaultValues?.storageType ?? ''}
                newValue={form.getValues('storageType')}
                unit="-"
                beforePrice={0}
                afterPrice={0}
              />
            )}
            {(hasIOPSChanges || hasStorageTypeChanges) && (
              <TableDataRow
                attribute="IOPS"
                defaultValue={form.formState.defaultValues?.provisionedIOPS?.toLocaleString() ?? 0}
                newValue={form.getValues('provisionedIOPS')?.toLocaleString()}
                unit="IOPS"
                beforePrice={Number(iopsPrice.oldPrice)}
                afterPrice={Number(iopsPrice.newPrice)}
                priceTooltip={numReplicas > 0 ? replicaTooltipText : undefined}
              />
            )}
            {form.getValues('storageType') === 'gp3' && hasThroughputChanges && (
              <TableDataRow
                attribute="Throughput"
                defaultValue={form.formState.defaultValues?.throughput?.toLocaleString() ?? 0}
                newValue={form.getValues('throughput')?.toLocaleString() ?? 0}
                unit="MB/s"
                beforePrice={Number(throughputPrice.oldPrice)}
                afterPrice={Number(throughputPrice.newPrice)}
                priceTooltip={numReplicas > 0 ? replicaTooltipText : undefined}
              />
            )}
            {(hasTotalSizeChanges || hasStorageTypeChanges) && (
              <TableDataRow
                attribute="Disk size"
                defaultValue={form.formState.defaultValues?.totalSize?.toLocaleString() ?? 0}
                newValue={form.getValues('totalSize')?.toLocaleString()}
                unit="GB"
                beforePrice={Number(diskSizePrice.oldPrice)}
                afterPrice={Number(diskSizePrice.newPrice)}
                priceTooltip={numReplicas > 0 ? replicaTooltipText : undefined}
              />
            )}
            {hasGrowthPercentChanges && (
              <TableDataRow
                attribute="Growth percent"
                defaultValue={
                  form.formState.defaultValues?.growthPercent ??
                  DISK_AUTOSCALE_CONFIG_DEFAULTS.growthPercent
                }
                newValue={
                  form.getValues('growthPercent') ?? DISK_AUTOSCALE_CONFIG_DEFAULTS.growthPercent
                }
                unit="%"
                beforePrice={0}
                afterPrice={0}
              />
            )}
            {hasMinIncrementChanges && (
              <TableDataRow
                attribute="Min increment"
                defaultValue={
                  form.formState.defaultValues?.minIncrementGb ??
                  DISK_AUTOSCALE_CONFIG_DEFAULTS.minIncrementSize
                }
                newValue={
                  form.getValues('minIncrementGb') ??
                  DISK_AUTOSCALE_CONFIG_DEFAULTS.minIncrementSize
                }
                unit="GB"
                beforePrice={0}
                afterPrice={0}
              />
            )}
            {hasMaxSizeChanges && (
              <TableDataRow
                attribute="Max disk size"
                defaultValue={
                  form.formState.defaultValues?.maxSizeGb?.toLocaleString() ??
                  DISK_AUTOSCALE_CONFIG_DEFAULTS.maxSizeGb
                }
                newValue={
                  form.getValues('maxSizeGb')?.toLocaleString() ??
                  DISK_AUTOSCALE_CONFIG_DEFAULTS.maxSizeGb
                }
                unit="GB"
                beforePrice={0}
                afterPrice={0}
              />
            )}
          </TableBody>
        </Table>

        {numReplicas > 0 && (
          <div className="border-t px-4 py-2 text-sm text-foreground-lighter">
            {replicaTooltipText}
          </div>
        )}

        <DialogFooter>
          <Button block size="large" type="default" onClick={() => setIsDialogOpen(false)}>
            Cancel
          </Button>
          <Button
            block
            type={'warning'}
            size="large"
            htmlType="submit"
            loading={loading}
            onClick={async () => {
              await onSubmit(form.getValues())
            }}
          >
            Confirm changes
          </Button>
        </DialogFooter>
        {message && (
          <>
            <DialogSectionSeparator />
            <DialogSection>
              <Alert_Shadcn_
                variant={message.type === 'error' ? 'destructive' : 'default'}
                className=""
              >
                <WarningIcon />
                <AlertTitle_Shadcn_>{message.message}</AlertTitle_Shadcn_>
              </Alert_Shadcn_>
            </DialogSection>
          </>
        )}
      </DialogContent>
    </Dialog>
  )
}

Subdomains

Frequently Asked Questions

What does DiskManagementReviewAndSubmitDialog() do?
DiskManagementReviewAndSubmitDialog() is a function in the supabase codebase.
What does DiskManagementReviewAndSubmitDialog() call?
DiskManagementReviewAndSubmitDialog() calls 6 function(s): calculateComputeSizePrice, calculateDiskSizePrice, calculateIOPSPrice, calculateThroughputPrice, getAvailableComputeOptions, mapAddOnVariantIdToComputeSize.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free