moved things around. billing badges updated. compute added

This commit is contained in:
Jonathan Summers-Muir committed 2024-10-22 12:03:40 +08:00
1 parent 9e02c81f6b
commit c5a32fb534
8 files changed
+342 -178

No files matched your search

@@ -8,6 +8,7 @@ interface BillingChangeBadgeProps {
afterPrice?: number
show: boolean | undefined
tooltip?: string
className?: string
}
const BillingChangeBadge = ({
@@ -15,17 +16,21 @@ const BillingChangeBadge = ({
afterPrice,
show,
tooltip,
className,
}: BillingChangeBadgeProps) => {
return (
<AnimatePresence>
{beforePrice !== undefined && afterPrice !== undefined && show && (
<motion.div
initial={{ opacity: 0, x: -4 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -4 }}
transition={{ duration: 0.15 }}
initial={{ opacity: 0, x: -4, height: 0 }}
animate={{ opacity: 1, x: 0, height: 'auto' }}
exit={{ opacity: 0, x: -4, height: 0 }}
transition={{ type: 'spring', stiffness: 800, damping: 40, duration: 0.3 }}
// key={afterPrice} // This key will change whenever any form value changes
// whileHover={{ scale: 1.05 }}
// whileTap={{ scale: 0.95 }}
>
<Badge variant="default" className="bg-alternative bg-opacity-100">
<Badge variant="default" className={`bg-alternative bg-opacity-100 ${className}`}>
<Tooltip_Shadcn_>
<TooltipTrigger_Shadcn_ asChild>
<div className="flex items-center gap-1">
@@ -33,9 +38,14 @@ const BillingChangeBadge = ({
{formatCurrency(beforePrice)}
</span>
<ChevronRight size={12} strokeWidth={2} className="text-foreground-muted" />
<span className="text-xs font-mono text-foreground">
<motion.span
key={afterPrice} // This key will change whenever any form value changes
className="text-xs font-mono text-foreground"
animate={{ scale: [1, 1.1, 1] }}
transition={{ duration: 0.12 }}
>
{formatCurrency(afterPrice)}
</span>
</motion.span>
</div>
</TooltipTrigger_Shadcn_>
{tooltip !== undefined && (
@@ -1,4 +1,8 @@
import { components } from 'api-types'
import { DISK_LIMITS, DISK_PRICING, DiskType, PLAN_DETAILS } from './DiskManagement.constants'
import { INSTANCE_MICRO_SPECS } from 'lib/constants'
import { ProjectAddonVariantMeta } from 'data/subscriptions/types'
import { useMemo } from 'react'
// Included disk size only applies to primary, not replicas
export const calculateDiskSizePrice = ({
@@ -31,6 +35,29 @@ export const calculateDiskSizePrice = ({
}
}
export const calculateComputeSizePrice = ({
availableOptions,
oldComputeSize,
newComputeSize,
}: {
availableOptions: {
identifier: string
price: number
}[]
oldComputeSize: string
newComputeSize: string
}) => {
console.log('newComputeSize', newComputeSize)
const oldPrice = availableOptions.find((x) => x.identifier === oldComputeSize)?.price * 720
const newPrice = availableOptions.find((x) => x.identifier === newComputeSize)?.price * 720
return {
oldPrice,
newPrice,
}
}
// Included IOPS applies to both primary and replicas
export const calculateIOPSPrice = ({
oldStorageType,
@@ -109,3 +136,51 @@ export const calculateThroughputPrice = ({
}
return { oldPrice: '0.00', newPrice: '0.00' }
}
export function getAvailableComputeOptions(availableAddons: any[], projectCloudProvider?: string) {
const computeOptions =
availableAddons
.find((addon) => addon.type === 'compute_instance')
?.variants.filter((option) => {
if (!projectCloudProvider) {
return true
}
const meta = option.meta as ProjectAddonVariantMeta
return (
!meta.supported_cloud_providers ||
meta.supported_cloud_providers.includes(projectCloudProvider)
)
}) ?? []
function hasMicroOptionFromApi() {
return (
availableAddons.find((addon) => addon.type === 'compute_instance')?.variants ?? []
).some((variant: any) => variant.identifier === 'ci_micro')
}
// Backwards comp until API is deployed
if (!hasMicroOptionFromApi) {
// Unshift to push to start of array
computeOptions.unshift({
identifier: 'ci_micro',
name: 'Micro',
price_description: '$0.01344/hour (~$10/month)',
price: 0.01344,
price_interval: 'hourly',
price_type: 'usage',
meta: {
cpu_cores: INSTANCE_MICRO_SPECS.cpu_cores,
cpu_dedicated: INSTANCE_MICRO_SPECS.cpu_dedicated,
memory_gb: INSTANCE_MICRO_SPECS.memory_gb,
baseline_disk_io_mbs: INSTANCE_MICRO_SPECS.baseline_disk_io_mbs,
max_disk_io_mbs: INSTANCE_MICRO_SPECS.max_disk_io_mbs,
connections_direct: INSTANCE_MICRO_SPECS.connections_direct,
connections_pooler: INSTANCE_MICRO_SPECS.connections_pooler,
} as ProjectAddonVariantMeta,
})
}
return computeOptions
}
@@ -29,7 +29,7 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { GB } from 'lib/constants'
import { GB, INSTANCE_MICRO_SPECS } from 'lib/constants'
import {
Alert_Shadcn_,
AlertDescription_Shadcn_,
@@ -38,6 +38,7 @@ import {
Button,
Card,
CardContent,
cn,
Form_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
@@ -63,9 +64,11 @@ import {
THROUGHPUT_RANGE,
} from './DiskManagement.constants'
import {
calculateComputeSizePrice,
calculateDiskSizePrice,
calculateIOPSPrice,
calculateThroughputPrice,
getAvailableComputeOptions,
} from './DiskManagement.utils'
import { DiskStorageSchema, DiskStorageSchemaType } from './DiskManagementPanelSchema'
import { DiskManagementPlanUpgradeRequired } from './DiskManagementPlanUpgradeRequired'
@@ -80,6 +83,7 @@ import { ProjectAddonVariantMeta } from 'data/subscriptions/types'
import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils'
import { ComputeBadge } from 'ui-patterns'
import { components } from 'api-types'
import { MAX_WIDTH_CLASSES, PADDING_CLASSES, ScaffoldContainer } from 'components/layouts/Scaffold'
export function DiskManagementForm() {
const { project } = useProjectContext()
@@ -170,54 +174,12 @@ export function DiskManagementForm() {
return addons?.available_addons ?? []
}, [addons])
const hasMicroOptionFromApi = useMemo(() => {
return (
availableAddons.find((addon) => addon.type === 'compute_instance')?.variants ?? []
).some((variant) => variant.identifier === 'ci_micro')
}, [availableAddons])
const selectedAddons = addons?.selected_addons ?? []
const subscriptionCompute = selectedAddons.find((addon) => addon.type === 'compute_instance')
const availableOptions = useMemo(() => {
const computeOptions =
availableAddons
.find((addon) => addon.type === 'compute_instance')
?.variants.filter((option) => {
if (!project?.cloud_provider) {
return true
}
const meta = option.meta as ProjectAddonVariantMeta
return (
!meta.supported_cloud_providers ||
meta.supported_cloud_providers.includes(project.cloud_provider)
)
}) ?? []
// Backwards comp until API is deployed
// if (!hasMicroOptionFromApi) {
// // Unshift to push to start of array
// computeOptions.unshift({
// identifier: 'ci_micro',
// name: 'Micro',
// price_description: '$0.01344/hour (~$10/month)',
// price: 0.01344,
// price_interval: 'hourly',
// price_type: 'usage',
// // @ts-ignore API types it as Record<string, never>
// meta: {
// cpu_cores: INSTANCE_MICRO_SPECS.cpu_cores,
// cpu_dedicated: INSTANCE_MICRO_SPECS.cpu_dedicated,
// memory_gb: INSTANCE_MICRO_SPECS.memory_gb,
// baseline_disk_io_mbs: INSTANCE_MICRO_SPECS.baseline_disk_io_mbs,
// max_disk_io_mbs: INSTANCE_MICRO_SPECS.max_disk_io_mbs,
// connections_direct: INSTANCE_MICRO_SPECS.connections_direct,
// connections_pooler: INSTANCE_MICRO_SPECS.connections_pooler,
// } as ProjectAddonVariantMeta,
// })
// }
return computeOptions
}, [availableAddons, hasMicroOptionFromApi])
return getAvailableComputeOptions(availableAddons, project?.cloud_provider)
}, [availableAddons, project?.cloud_provider])
/**
* Handle default values
@@ -229,10 +191,9 @@ export function DiskManagementForm() {
provisionedIOPS: iops,
throughput: throughput_mbps,
totalSize: size_gb,
computeSize: subscriptionCompute?.variant.identifier ?? 'ci_micro',
}
console.log('type', type)
const form = useForm<DiskStorageSchemaType>({
resolver: zodResolver(DiskStorageSchema),
defaultValues,
@@ -311,6 +272,12 @@ export function DiskManagementForm() {
/**
* Price calculations
*/
const computeSizePrice = calculateComputeSizePrice({
availableOptions: availableOptions,
oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
newComputeSize: form.getValues('computeSize'),
})
const diskSizePrice = calculateDiskSizePrice({
planId,
oldSize: form.formState.defaultValues?.totalSize || 0,
@@ -423,71 +390,105 @@ export function DiskManagementForm() {
// return <></>
const isDirty = !!Object.keys(form.formState.dirtyFields).length
return (
<div id="disk-management">
{/* <FormHeader
title="Disk Management"
docsUrl="https://supabase.com/docs/guides/platform/database-size#disk-management"
/> */}
<Form_Shadcn_ {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-8">
<ScaffoldContainer className="relative flex flex-col gap-10" bottomPadding>
{/* {showNewDiskManagementUI ? <DiskManagementForm /> : null} */}
<Separator />
<Form_Shadcn_ {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-8">
<RadioGroupCard className="flex flex-wrap gap-3">
{availableOptions.map((compute) => {
const cpuArchitecture = getCloudProviderArchitecture(project?.cloud_provider)
<FormField_Shadcn_
name="computeSize"
control={form.control}
render={({ field }) => (
<>
<FormItemLayout
layout="horizontal"
label={'Compute size'}
labelOptional={
<>
<BillingChangeBadge
className={'mb-2'}
show={
formState.isDirty &&
formState.dirtyFields.computeSize &&
!formState.errors.computeSize
}
beforePrice={Number(computeSizePrice.oldPrice)}
afterPrice={Number(computeSizePrice.newPrice)}
/>
<p>hardware resources allocated to your postgres database</p>
</>
}
>
<RadioGroupCard
className="grid grid-cols-3 flex-wrap gap-3"
onValueChange={(value) => {
setValue('computeSize', value, {
shouldDirty: true,
shouldValidate: true,
})
}}
defaultValue={field.value}
value={field.value}
>
{availableOptions.map((compute) => {
const cpuArchitecture = getCloudProviderArchitecture(project?.cloud_provider)
return (
<RadioGroupCardItem
// label={compute.name}
disabled={disableInput}
showIndicator={false}
value={compute.identifier}
className="text-sm text-left flex flex-col gap-0 px-0 py-3 overflow-hidden [&_label]:w-full group] min-w-[250px]"
// @ts-ignore
label={
<div className="w-full flex flex-col gap-3">
<div className="px-3 opacity-50 group-data-[state=checked]:opacity-100 flex justify-between">
<ComputeBadge
className="inline-flex font-semibold"
infraComputeSize={compute.name as components['schemas']['DbInstanceSize']}
/>
<div className="flex items-center space-x-1">
<span className="text-foreground text-sm font-semibold">
{/* Price needs to be exact here */}${compute.price}
</span>
<span className="text-foreground-light translate-y-[1px]">
{' '}
/ {compute.price_interval === 'monthly' ? 'month' : 'hour'}
</span>
</div>
</div>
{/* <Separator className="bg-border group-data-[state=checked]:bg-foreground-muted" /> */}
<div className="w-full">
<div className="px-3 text-sm flex flex-col gap-1">
<div className="text-foreground-light flex gap-2 items-center">
<Microchip
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>{compute.meta?.memory_gb ?? 0} GB memory</span>
</div>
<div className="text-foreground-light flex gap-2 items-center">
<CpuIcon
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>
{compute.meta?.cpu_cores ?? 0}-core {cpuArchitecture} CPU
</span>
</div>
</div>
{/* <div className="px-2">
return (
<RadioGroupCardItem
showIndicator={false}
value={compute.identifier}
className="text-sm text-left flex flex-col gap-0 px-0 py-3 overflow-hidden [&_label]:w-full group] w-full"
// @ts-ignore
label={
<div className="w-full flex flex-col gap-3">
<div className="px-3 opacity-50 group-data-[state=checked]:opacity-100 flex justify-between">
<ComputeBadge
className="inline-flex font-semibold"
infraComputeSize={
compute.name as components['schemas']['DbInstanceSize']
}
/>
<div className="flex items-center space-x-1">
<span className="text-foreground text-sm font-semibold">
{/* Price needs to be exact here */}${compute.price}
</span>
<span className="text-foreground-light translate-y-[1px]">
{' '}
/ {compute.price_interval === 'monthly' ? 'month' : 'hour'}
</span>
</div>
</div>
{/* <Separator className="bg-border group-data-[state=checked]:bg-foreground-muted" /> */}
<div className="w-full">
<div className="px-3 text-sm flex flex-col gap-1">
<div className="text-foreground-light flex gap-2 items-center">
<Microchip
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>{compute.meta?.memory_gb ?? 0} GB memory</span>
</div>
<div className="text-foreground-light flex gap-2 items-center">
<CpuIcon
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>
{compute.meta?.cpu_cores ?? 0}-core {cpuArchitecture} CPU
</span>
</div>
</div>
{/* <div className="px-2">
<span>{compute.meta?.cpu_dedicated ? 'Dedicated' : 'Shared'}</span>
</div> */}
{/* <div className="px-3 py-1">
{/* <div className="px-3 py-1">
<div className="flex items-center space-x-1">
<span className="text-foreground text-sm">
${compute.price}
@@ -498,13 +499,17 @@ export function DiskManagementForm() {
</span>
</div>
</div> */}
</div>
</div>
}
></RadioGroupCardItem>
)
})}
</RadioGroupCard>
</div>
</div>
}
></RadioGroupCardItem>
)
})}
</RadioGroupCard>
</FormItemLayout>
</>
)}
/>
{/* <Card className="bg-surface-100 rounded-b-none">
<CardContent className="transition-all duration-500 ease-in-out py-10 flex flex-col gap-10 px-8"> */}
@@ -661,7 +666,24 @@ export function DiskManagementForm() {
)}
</div>
}
labelOptional="Input/output operations per second. Higher IOPS is suitable for applications requiring high throughput."
labelOptional={
<>
<BillingChangeBadge
show={
(watchedStorageType !== type ||
(watchedStorageType === 'gp3' && field.value !== iops)) &&
!formState.errors.provisionedIOPS
}
beforePrice={Number(iopsPrice.oldPrice)}
afterPrice={Number(iopsPrice.newPrice)}
className="mb-2"
/>
<p>
Input/output operations per second. Higher IOPS is suitable for applications
requiring high throughput.
</p>
</>
}
>
<div className="flex gap-3 items-center">
<div className="flex -space-x-px">
@@ -684,15 +706,6 @@ export function DiskManagementForm() {
<span className="text-foreground-lighter text-xs font-mono">IOPS</span>
</div>
</div>
<BillingChangeBadge
show={
(watchedStorageType !== type ||
(watchedStorageType === 'gp3' && field.value !== iops)) &&
!formState.errors.provisionedIOPS
}
beforePrice={Number(iopsPrice.oldPrice)}
afterPrice={Number(iopsPrice.newPrice)}
/>
</div>
</FormItemLayout>
)}
@@ -758,6 +771,25 @@ export function DiskManagementForm() {
)}
</div>
}
labelOptional={
<>
<BillingChangeBadge
show={
formState.isDirty &&
formState.dirtyFields.throughput &&
!formState.errors.throughput
}
beforePrice={Number(throughputPrice.oldPrice)}
afterPrice={Number(throughputPrice.newPrice)}
className="mb-2"
/>
<p>
Throughput is the amount of data that can be read or written to the disk
per second. Higher throughput is suitable for applications requiring
high throughput.
</p>
</>
}
>
<div className="flex gap-3 items-center">
<div className="flex -space-x-px">
@@ -779,15 +811,6 @@ export function DiskManagementForm() {
<span className="text-foreground-lighter text-xs font-mono">MB/s</span>
</div>
</div>
<BillingChangeBadge
show={
formState.isDirty &&
formState.dirtyFields.throughput &&
!formState.errors.throughput
}
beforePrice={Number(throughputPrice.oldPrice)}
afterPrice={Number(throughputPrice.newPrice)}
/>
</div>
</FormItemLayout>
)}
@@ -910,28 +933,48 @@ export function DiskManagementForm() {
)}
{isPlanUpgradeRequired && <DiskManagementPlanUpgradeRequired />}
</ScaffoldContainer>
{/* <Card className="bg-surface-100 rounded-t-none">
{/* <Card className="bg-surface-100 rounded-t-none">
<CardContent className="flex items-center pb-0 py-3 px-8 gap-3 justify-end"> */}
<FormFooterChangeBadge formState={formState} />
<div className="flex gap-2">
<Button type="default" onClick={() => form.reset()} disabled={!form.formState.isDirty}>
Cancel
</Button>
<DiskManagementReviewAndSubmitDialog
loading={isUpdatingDiskConfiguration}
form={form}
numReplicas={readReplicas.length}
isDialogOpen={isDialogOpen}
isWithinCooldown={disableInput}
onSubmit={onSubmit}
setIsDialogOpen={setIsDialogOpen}
/>
</div>
{/* </CardContent> */}
{/* </Card> */}
</form>
</Form_Shadcn_>
</div>
<AnimatePresence>
{isDirty ? (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 20 }}
transition={{ duration: 0.1, delay: 0.4 }}
className="z-10 w-full left-0 right-0 sticky bottom-0 bg-surface-100 border-t h-16 items-center flex"
>
<div
className={cn(
MAX_WIDTH_CLASSES,
PADDING_CLASSES,
'flex items-center gap-3 justify-end'
)}
>
<FormFooterChangeBadge formState={formState} />
<Button type="default" onClick={() => form.reset()} disabled={!isDirty}>
Cancel
</Button>
<DiskManagementReviewAndSubmitDialog
loading={isUpdatingDiskConfiguration}
form={form}
numReplicas={readReplicas.length}
isDialogOpen={isDialogOpen}
isWithinCooldown={disableInput}
onSubmit={onSubmit}
setIsDialogOpen={setIsDialogOpen}
/>
</div>
</motion.div>
) : null}
</AnimatePresence>
{/* </CardContent> */}
{/* </Card> */}
</form>
</Form_Shadcn_>
)
}
@@ -9,10 +9,11 @@ const baseSchema = z.object({
.describe('Allocated disk size in GB'),
provisionedIOPS: z.number().describe('Provisioned IOPS for storage type'),
throughput: z.number().optional().describe('Throughput in MB/s for gp3'),
computeSize: z.string().describe('Compute size'),
})
export const DiskStorageSchema = baseSchema.superRefine((data, ctx) => {
const { storageType, totalSize, provisionedIOPS, throughput } = data
const { storageType, totalSize, provisionedIOPS, throughput, computeSize } = data
if (storageType === 'io2') {
// Validation rules for io2
@@ -28,13 +28,17 @@ import {
import BillingChangeBadge from './BillingChangeBadge'
import { DiskType } from './DiskManagement.constants'
import {
calculateComputeSizePrice,
calculateDiskSizePrice,
calculateIOPSPrice,
calculateThroughputPrice,
getAvailableComputeOptions,
} from './DiskManagement.utils'
import { DiskMangementCoolDownSection } from './DiskManagementCoolDownSection'
import { DiskStorageSchemaType } from './DiskManagementPanelSchema'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import { useMemo } from 'react'
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
const TableHeaderRow = () => (
<TableRow>
@@ -127,7 +131,17 @@ export const DiskManagementReviewAndSubmitDialog = ({
}: DiskSizeMeterProps) => {
const { project } = useProjectContext()
const org = useSelectedOrganization()
/**
* Queries
* */
const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: org?.slug })
const {
data: addons,
isLoading: isAddonsLoading,
error: addonsError,
isSuccess: isAddonsSuccess,
} = useProjectAddonsQuery({ projectRef: project?.ref })
const canUpdateDiskConfiguration = useCheckPermissions(PermissionAction.UPDATE, 'projects', {
resource: {
@@ -136,10 +150,26 @@ export const DiskManagementReviewAndSubmitDialog = ({
})
const planId = subscription?.plan.id ?? ''
const isDirty = Object.keys(form.formState.dirtyFields).length > 0
const isDirty = !!Object.keys(form.formState.dirtyFields).length
const replicaTooltipText = `Price change includes primary database and ${numReplicas} replica${numReplicas > 1 ? 's' : ''}`
/**
* Handle compute instances
*/
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'),
})
const diskSizePrice = calculateDiskSizePrice({
planId,
oldSize: form.formState.defaultValues?.totalSize || 0,
@@ -190,7 +220,7 @@ export const DiskManagementReviewAndSubmitDialog = ({
Review changes
</ButtonTooltip>
</DialogTrigger>
<DialogContent size="large">
<DialogContent className="min-w-[620px]">
<DialogHeader>
<DialogTitle>Review changes</DialogTitle>
<DialogDescription>
@@ -204,6 +234,14 @@ export const DiskManagementReviewAndSubmitDialog = ({
<TableHeaderRow />
</TableHeader>
<TableBody className="[&_td]:py-0 [&_tr]:h-[50px] [&_tr]:border-dotted">
<TableDataRow
attribute="Compute size"
defaultValue={form.formState.defaultValues?.computeSize ?? ''}
newValue={form.getValues('computeSize')}
unit="-"
beforePrice={computeSizePrice.oldPrice}
afterPrice={computeSizePrice.newPrice}
/>
<TableDataRow
hidePrice
attribute="Storage Type"
@@ -149,7 +149,7 @@ const ProjectLayout = ({
/>
<ResizablePanel id="panel-right" className="h-full flex flex-col">
{!navLayoutV2 && !hideHeader && IS_PLATFORM && <LayoutHeader />}
<main className="h-full flex flex-col flex-1 w-full overflow-x-hidden">
<main className="h-screen flex flex-col flex-1 w-full overflow-x-hidden">
{showPausedState ? (
<div className="mx-auto my-16 w-full h-full max-w-7xl flex items-center">
<div className="w-full">
+6 -6
View File
@@ -1,9 +1,9 @@
import React from 'react'
import { cn } from 'ui'
const maxWidthClasses = 'mx-auto w-full max-w-[1200px]'
const paddingClasses = 'px-6 lg:px-14 xl:px-24 2xl:px-32'
const maxWidthClassesColumn = 'min-w-[420px]'
export const MAX_WIDTH_CLASSES = 'mx-auto w-full max-w-[1200px]'
export const PADDING_CLASSES = 'px-6 lg:px-14 xl:px-24 2xl:px-32'
export const MAX_WIDTH_CLASSES_COLUMN = 'min-w-[420px]'
const ScaffoldHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => {
@@ -39,7 +39,7 @@ const ScaffoldContainer = React.forwardRef<
<div
ref={ref}
{...props}
className={cn(maxWidthClasses, paddingClasses, bottomPadding && 'pb-16', className)}
className={cn(MAX_WIDTH_CLASSES, PADDING_CLASSES, bottomPadding && 'pb-16', className)}
/>
)
})
@@ -68,7 +68,7 @@ const ScaffoldColumn = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTM
<div
ref={ref}
{...props}
className={cn('flex flex-col gap-3', maxWidthClassesColumn, className)}
className={cn('flex flex-col gap-3', MAX_WIDTH_CLASSES_COLUMN, className)}
/>
)
}
@@ -131,7 +131,7 @@ const ScaffoldContainerLegacy = React.forwardRef<
<div
ref={ref}
{...props}
className={cn(maxWidthClasses, paddingClasses, 'my-8 flex flex-col gap-8', className)}
className={cn(MAX_WIDTH_CLASSES, PADDING_CLASSES, 'my-8 flex flex-col gap-8', className)}
/>
)
})
@@ -35,11 +35,8 @@ const AuthSettings: NextPageWithLayout = () => {
</ScaffoldDescription>
</ScaffoldHeader>
</ScaffoldContainer>
<ScaffoldContainer className="flex flex-col gap-10" bottomPadding>
{/* {showNewDiskManagementUI ? <DiskManagementForm /> : null} */}
<Separator />
<DiskManagementForm />
</ScaffoldContainer>
<DiskManagementForm />
</>
)
}