diff --git a/apps/studio/lib/slider-helpers.ts b/apps/studio/lib/slider-helpers.ts index 3826580d8c..f06f442325 100644 --- a/apps/studio/lib/slider-helpers.ts +++ b/apps/studio/lib/slider-helpers.ts @@ -1,5 +1,23 @@ +export type SliderKey = 'vcpu' | 'ram' | 'iops' | 'nvme' | 'storage' + +const FULL_VCPU_THRESHOLD = 8 +const FULL_RAM_THRESHOLD = 16 + export function calculateSliderDefault(min: number, max: number, step: number, factor: number): number { const baseMaximum = Math.max(min, max * factor) const cleanDivisor = Math.floor(baseMaximum / step) return cleanDivisor * step } + +export function snapValue(key: SliderKey, value: number) { + if (key === 'vcpu' && value > FULL_VCPU_THRESHOLD) { + return Math.round(value) + } + + if (key === 'ram' && value > FULL_RAM_THRESHOLD) { + return Math.round(value) + } + + return value +} + diff --git a/apps/studio/pages/new/[slug]/index.tsx b/apps/studio/pages/new/[slug]/index.tsx index 0fcd21bba7..d746b1030b 100644 --- a/apps/studio/pages/new/[slug]/index.tsx +++ b/apps/studio/pages/new/[slug]/index.tsx @@ -48,13 +48,13 @@ import { components } from 'data/vela/vela-schema' import { useOrgAvailableCreationResourcesQuery } from 'data/resource-limits/org-available-creation-resources-query' import { useOrganizationLimitsQuery } from 'data/resource-limits/organization-limits-query' import { put } from 'data/fetchers' -import { calculateSliderDefault } from '../../../lib/slider-helpers' +import { calculateSliderDefault, SliderKey,snapValue } from '../../../lib/slider-helpers' /* ------------------------------------------------------------------ */ /* Types / labels */ /* ------------------------------------------------------------------ */ -type SliderKey = 'vcpu' | 'ram' | 'iops' | 'nvme' | 'storage' + type CreateProjectStep = 1 | 2 | 3 const sliderOrder = ['vcpu', 'ram', 'iops', 'nvme', 'storage'] as const @@ -631,26 +631,50 @@ const CreateProjectPage: NextPageWithLayout = () => { } // Slider onChange creators (clamp + sync rules) - const handlePerBranchChange = (key: SliderKey) => (v: number[]) => { - if (!limitConfig) return - const cfg = limitConfig[key]! - const next = v[0] ?? cfg.min - const safe = Math.max(cfg.min, Math.min(next, cfg.max)) - form.setValue(`perBranchLimits.${key}`, safe, { shouldDirty: true, shouldValidate: false }) - const projVal = form.getValues(`projectLimits.${key}`) - if (safe > projVal) { - form.setValue(`projectLimits.${key}`, safe, { shouldDirty: true, shouldValidate: false }) - } - } +const handlePerBranchChange = (key: SliderKey) => (v: number[]) => { + if (!limitConfig) return + const cfg = limitConfig[key]! - const handleProjectChange = (key: SliderKey) => (v: number[]) => { - if (!limitConfig) return - const cfg = limitConfig[key]! - const next = v[0] ?? cfg.min - const branchVal = form.getValues(`perBranchLimits.${key}`) - const clamped = Math.max(branchVal, Math.max(cfg.min, Math.min(next, cfg.max))) - form.setValue(`projectLimits.${key}`, clamped, { shouldDirty: true, shouldValidate: false }) + let next = v[0] ?? cfg.min + next = snapValue(key, next) + + const safe = Math.max(cfg.min, Math.min(next, cfg.max)) + + form.setValue(`perBranchLimits.${key}`, safe, { + shouldDirty: true, + shouldValidate: false, + }) + + const projVal = form.getValues(`projectLimits.${key}`) + if (safe > projVal) { + form.setValue(`projectLimits.${key}`, safe, { + shouldDirty: true, + shouldValidate: false, + }) } +} + + +const handleProjectChange = (key: SliderKey) => (v: number[]) => { + if (!limitConfig) return + const cfg = limitConfig[key]! + + let next = v[0] ?? cfg.min + next = snapValue(key, next) + + const branchVal = form.getValues(`perBranchLimits.${key}`) + + const clamped = Math.max( + branchVal, + Math.max(cfg.min, Math.min(next, cfg.max)) + ) + + form.setValue(`projectLimits.${key}`, clamped, { + shouldDirty: true, + shouldValidate: false, + }) +} + /* ------------------------------------------------------------------ */ /* Render */