mirror of
https://github.com/supabase/supabase.git
synced 2026-09-06 09:59:03 +08:00
## Summary - require an explicit choice before saving a notebook that diverged while dirty - let users save over assistant changes or discard their local edits, with deleted notebooks recreating safely - keep dismissals side-effect free and close deleted notebook tabs when edits are discarded ## Testing - pnpm --filter studio exec vitest run components/interfaces/Explorer/__tests__/ExplorerNotebookTab.assistant-cache-invalidation.test.tsx data/content/notebooks/notebook-cache.test.ts --reporter=dot - pnpm --filter studio typecheck <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added conflict handling when server-side notebook changes overlap with local edits. - Users can overwrite, recreate, discard, or dismiss changes through a confirmation dialog. - Deleted notebooks can be recreated when saved, while discarded deleted notebooks are automatically removed from open tabs. - Conflict dialogs remain open while an action is in progress. - **Bug Fixes** - Improved notebook cache cleanup to remove stale and unsaved notebook data reliably. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import type { QueryClient } from '@tanstack/react-query'
|
|
import type { Snapshot } from 'valtio'
|
|
|
|
import { contentKeys } from '@/data/content/keys'
|
|
import { notebooksState } from '@/state/notebooks/notebooks-state'
|
|
import type { StateNotebook } from '@/state/notebooks/types'
|
|
import { hasUnsavedChanges } from '@/state/sql-editor/sql-editor-lifecycle'
|
|
|
|
/**
|
|
* Whether a notebook has edits worth discarding on close: anything not yet
|
|
* saved, except a never-persisted notebook that's still empty (nothing to
|
|
* lose by closing it).
|
|
*/
|
|
export function hasDiscardableChanges(
|
|
stateNotebook: StateNotebook | Snapshot<StateNotebook> | undefined
|
|
): boolean {
|
|
if (!hasUnsavedChanges(stateNotebook?.status)) return false
|
|
|
|
const isEmptyNewNotebook =
|
|
stateNotebook?.status === 'new' && (stateNotebook.notebook.content?.cells.length ?? 0) === 0
|
|
return !isEmptyNewNotebook
|
|
}
|
|
|
|
/**
|
|
* Evicts a notebook from the React Query cache and the Valtio store together.
|
|
* Callers are responsible for confirming before discarding unsaved edits.
|
|
*
|
|
* Removes the query entry outright rather than invalidating it: a mounted
|
|
* `useNotebookQuery` observer would otherwise read the stale cached value
|
|
* synchronously, before its refetch lands, and `notebooksState.setNotebook`'s
|
|
* merge guard would treat that stale merge as already-loaded and drop the
|
|
* real update.
|
|
*
|
|
*/
|
|
export function evictNotebookFromCaches({
|
|
queryClient,
|
|
projectRef,
|
|
id,
|
|
}: {
|
|
queryClient: QueryClient
|
|
projectRef: string
|
|
id: string
|
|
}): boolean {
|
|
notebooksState.removeNotebook({ id })
|
|
queryClient.removeQueries({ queryKey: contentKeys.resource(projectRef, id) })
|
|
|
|
return true
|
|
}
|