diff --git a/apps/studio/components/interfaces/Storage/BucketDataProtectionFields.tsx b/apps/studio/components/interfaces/Storage/BucketDataProtectionFields.tsx index a0aa873bf61..91aa1364c3b 100644 --- a/apps/studio/components/interfaces/Storage/BucketDataProtectionFields.tsx +++ b/apps/studio/components/interfaces/Storage/BucketDataProtectionFields.tsx @@ -96,8 +96,9 @@ export const BucketDataProtectionFields = ({ // Turning versioning off never deletes anything by itself — a bucket that's // ever had it enabled can only be suspended, not returned to a plain // "disabled" state, so nothing needs a destructive confirmation here. - // Both expiration fields default to empty (no limit) — the user opts in to - // each condition deliberately rather than receiving prefilled defaults. + // The two expiration fields come prefilled with sensible starter values + // (see CreateBucketModal / EditBucketModal defaults) — clearing a field + // removes that condition from the policy. const handleVersioningToggle = (checked: boolean, onChange: (value: boolean) => void) => { onChange(checked) } diff --git a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx index 3073b03c01d..833c58e44b4 100644 --- a/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/CreateBucketModal.tsx @@ -130,8 +130,11 @@ export const CreateBucketModal = ({ open, onOpenChange }: CreateBucketModalProps formatted_size_limit: undefined, allowed_mime_types: '', enable_versioning: false, - version_expiry_days: '', - max_noncurrent_versions: '', + // Prefill sensible defaults so the inputs aren't blank the moment + // versioning is toggled on. A no-policy bucket has to be an explicit + // opt-out — clear the field to remove that condition. + version_expiry_days: 30, + max_noncurrent_versions: 10, expiration_mode: 'and', }, }) diff --git a/apps/studio/components/interfaces/Storage/EditBucketModal.tsx b/apps/studio/components/interfaces/Storage/EditBucketModal.tsx index 67a48a5be1b..6a5dadffc43 100644 --- a/apps/studio/components/interfaces/Storage/EditBucketModal.tsx +++ b/apps/studio/components/interfaces/Storage/EditBucketModal.tsx @@ -126,6 +126,20 @@ export const EditBucketModal = ({ visible, bucket, onClose }: EditBucketModalPro }, }) + // Prefill the two expiration inputs with sensible starter values when the + // bucket has never had versioning turned on — so toggling versioning on + // for the first time surfaces a policy ready to save, matching the create + // form's defaults. If versioning is already on (or has been in the past) + // respect the bucket's own values, including `null` which means the user + // explicitly opted out of that particular condition. + const hasEverBeenVersioned = bucketProtection.versioning !== 'disabled' + const defaultVersionExpiryDays = hasEverBeenVersioned + ? (bucketProtection.versionExpiryDays ?? ('' as const)) + : 30 + const defaultMaxNoncurrentVersions = hasEverBeenVersioned + ? (bucketProtection.maxNoncurrentVersions ?? ('' as const)) + : 10 + const defaultValues = { name: bucket?.name ?? '', public: bucket?.public, @@ -133,8 +147,8 @@ export const EditBucketModal = ({ visible, bucket, onClose }: EditBucketModalPro formatted_size_limit: bucket?.file_size_limit ? (fileSizeLimit ?? 0) : undefined, allowed_mime_types: (bucket?.allowed_mime_types ?? []).join(', '), enable_versioning: !!planLimits && bucketProtection.versioning === 'enabled', - version_expiry_days: bucketProtection.versionExpiryDays ?? ('' as const), - max_noncurrent_versions: bucketProtection.maxNoncurrentVersions ?? ('' as const), + version_expiry_days: defaultVersionExpiryDays, + max_noncurrent_versions: defaultMaxNoncurrentVersions, expiration_mode: bucketProtection.expirationMode, }