mirror of
https://github.com/supabase/supabase.git
synced 2026-10-16 22:59:11 +03:00
## This PR Adds **Show archived** to the file explorer's view options and list them in the file explorer. - `useStoragePreference` — `showArchivedInline`, stored per project - `ArchivedFilesContext` — owns the archived list and which object is selected - `FileExplorer` — merges archived rows into each column and re-sorts, since the server-side sort never sees them - `FileExplorerRow` — dimmed striped rendering, no checkbox, no context menu - `FileExplorerHeader` — the toggle, rendered only behind the feature preview - `StorageExplorer` — mounts the provider https://github.com/user-attachments/assets/a26551b4-b22d-485e-9d23-3e78c4a89315 Clicking an archived row opens a preview panel: where the file used to live, when it was archived, its retained versions, and the actions to bring it back or delete it permanently. - `ArchivedFilePreviewPane` — the pane, replacing `PreviewPane` while an archived row is selected - `ArchivedVersionRestoreWidget` — takes over the top of the pane when a specific retained version is selected - `ArchivedVersionRow` — one version, with its restore / delete actions - `StorageExplorerContent` — the pane swap https://github.com/user-attachments/assets/03c9eae6-e9e3-4bd0-8145-953625e125d1 Other additions behind the feature preview: - The buckets list show a **Versioning** column. - `BucketVersioningPill` — a `file-stack` badge beside the bucket name in the breadcrumbs, brand when versioning is enabled and warning when it is suspended, so the bucket's state is visible from inside the explorer rather than only from the buckets list. https://github.com/user-attachments/assets/f4827aac-a9ff-4300-92ac-073848d63606 --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
86 lines
3.1 KiB
TypeScript
86 lines
3.1 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
getBucketVersioningState,
|
|
hasVersioningHistory,
|
|
isVersioningActive,
|
|
willRetainVersionOnWrite,
|
|
} from './StorageVersioning.constants'
|
|
import type { Bucket } from '@/data/storage/buckets-query'
|
|
|
|
const bucket = (versioning_status?: Bucket['versioning_status']) =>
|
|
({ id: 'bucket', name: 'bucket', versioning_status }) as Bucket
|
|
|
|
describe('getBucketVersioningState', () => {
|
|
it('maps the API statuses', () => {
|
|
expect(getBucketVersioningState(bucket('ENABLED'))).toBe('enabled')
|
|
expect(getBucketVersioningState(bucket('SUSPENDED'))).toBe('suspended')
|
|
expect(getBucketVersioningState(bucket('DISABLED'))).toBe('disabled')
|
|
})
|
|
|
|
it('treats a bucket that never reported a status as disabled', () => {
|
|
expect(getBucketVersioningState(bucket(undefined))).toBe('disabled')
|
|
expect(getBucketVersioningState(undefined)).toBe('disabled')
|
|
})
|
|
})
|
|
|
|
describe('isVersioningActive', () => {
|
|
it('only lets an enabled bucket soft-delete', () => {
|
|
expect(isVersioningActive(bucket('ENABLED'))).toBe(true)
|
|
expect(isVersioningActive(bucket('SUSPENDED'))).toBe(false)
|
|
expect(isVersioningActive(bucket('DISABLED'))).toBe(false)
|
|
expect(isVersioningActive(undefined)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('hasVersioningHistory', () => {
|
|
it('keeps a suspended bucket in, since it can still be retaining versions', () => {
|
|
expect(hasVersioningHistory(bucket('ENABLED'))).toBe(true)
|
|
expect(hasVersioningHistory(bucket('SUSPENDED'))).toBe(true)
|
|
expect(hasVersioningHistory(bucket('DISABLED'))).toBe(false)
|
|
expect(hasVersioningHistory(undefined)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('willRetainVersionOnWrite', () => {
|
|
it('always retains on an enabled bucket, whatever the object reports', () => {
|
|
expect(willRetainVersionOnWrite({ versioningState: 'enabled', isObjectVersioned: true })).toBe(
|
|
true
|
|
)
|
|
expect(willRetainVersionOnWrite({ versioningState: 'enabled', isObjectVersioned: false })).toBe(
|
|
true
|
|
)
|
|
expect(
|
|
willRetainVersionOnWrite({ versioningState: 'enabled', isObjectVersioned: undefined })
|
|
).toBe(true)
|
|
})
|
|
|
|
it('retains on a suspended bucket only for an object that predates the suspension', () => {
|
|
expect(
|
|
willRetainVersionOnWrite({ versioningState: 'suspended', isObjectVersioned: true })
|
|
).toBe(true)
|
|
expect(
|
|
willRetainVersionOnWrite({ versioningState: 'suspended', isObjectVersioned: false })
|
|
).toBe(false)
|
|
})
|
|
|
|
it('falls back to no retention when the listing omits the field', () => {
|
|
// An older storage build may not send `is_versioned`; "replace in place" is the safe read.
|
|
expect(
|
|
willRetainVersionOnWrite({ versioningState: 'suspended', isObjectVersioned: undefined })
|
|
).toBe(false)
|
|
expect(
|
|
willRetainVersionOnWrite({ versioningState: 'suspended', isObjectVersioned: null })
|
|
).toBe(false)
|
|
})
|
|
|
|
it('never retains on a disabled bucket', () => {
|
|
expect(willRetainVersionOnWrite({ versioningState: 'disabled', isObjectVersioned: true })).toBe(
|
|
false
|
|
)
|
|
expect(
|
|
willRetainVersionOnWrite({ versioningState: 'disabled', isObjectVersioned: false })
|
|
).toBe(false)
|
|
})
|
|
})
|