mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
fix: keep recent items labels in sync after renames (#44155)
## What kind of change does this PR introduce? Bug fix. ## What is the current behavior? The `Recent items` list shown in the table editor empty-state can keep showing an old label after a table or SQL snippet is renamed. That UI is mounted from: - `/project/[ref]/editor` - `/project/[ref]/editor/new` ## What is the new behavior? - Re-adding an existing recent item now refreshes its label and metadata instead of only bumping the timestamp. - Updating an open tab label now also updates the matching recent item, so rename flows stay aligned with the recent-items list. - The fix is applied in the shared tabs store, so table and SQL editor tab state stay consistent even though the visible `Recent items` UI currently appears in the table editor empty-state. - Adds a small store-level regression test for both cases. | Before | After | | --- | --- | | <img width="1024" height="563" alt="test Table Editor Mallet Toolshed Supabase-DA49998A-FE09-4197-8EE7-5D5366FABDC7" src="https://github.com/user-attachments/assets/d0475437-4486-4581-82f8-a84b97b08250" /> | <img width="1024" height="563" alt="test Table Editor Mallet Toolshed Supabase-8F2B6CC9-0721-4348-A094-EE94D6919B08" src="https://github.com/user-attachments/assets/f055be35-4373-4b1b-a2e1-ffe59f12c177" /> |
This commit is contained in:
1 parent
a337324c98
commit
585a4cedbf
2 files changed
+81
-2
No files matched your search
@@ -0,0 +1,62 @@
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { createTabsState } from './tabs'
|
||||
import { ENTITY_TYPE } from '@/data/entity-types/entity-type-constants'
|
||||
|
||||
describe('tabs recent items', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear()
|
||||
})
|
||||
|
||||
it('refreshes an existing recent item label when the tab is re-added', () => {
|
||||
const store = createTabsState('default')
|
||||
|
||||
store.addRecentItem({
|
||||
id: 'r-1',
|
||||
type: ENTITY_TYPE.TABLE,
|
||||
label: 'tasks',
|
||||
metadata: {
|
||||
schema: 'public',
|
||||
name: 'tasks',
|
||||
tableId: 1,
|
||||
},
|
||||
})
|
||||
|
||||
store.addRecentItem({
|
||||
id: 'r-1',
|
||||
type: ENTITY_TYPE.TABLE,
|
||||
label: 'routines',
|
||||
metadata: {
|
||||
schema: 'public',
|
||||
name: 'routines',
|
||||
tableId: 1,
|
||||
},
|
||||
})
|
||||
|
||||
expect(store.recentItems).toHaveLength(1)
|
||||
expect(store.recentItems[0].label).toBe('routines')
|
||||
expect(store.recentItems[0].metadata?.name).toBe('routines')
|
||||
})
|
||||
|
||||
it('keeps recent items aligned when an open tab label changes', () => {
|
||||
const store = createTabsState('default')
|
||||
|
||||
store.addTab({
|
||||
id: 'r-1',
|
||||
type: ENTITY_TYPE.TABLE,
|
||||
label: 'tasks',
|
||||
metadata: {
|
||||
schema: 'public',
|
||||
name: 'tasks',
|
||||
tableId: 1,
|
||||
},
|
||||
isPreview: false,
|
||||
})
|
||||
|
||||
store.updateTab('r-1', { label: 'routines' })
|
||||
|
||||
expect(store.tabsMap['r-1'].label).toBe('routines')
|
||||
expect(store.recentItems[0].label).toBe('routines')
|
||||
expect(store.recentItems[0].metadata?.name).toBe('routines')
|
||||
})
|
||||
})
|
||||
@@ -110,7 +110,21 @@ function getSavedTabs(ref: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function createTabsState(projectRef: string) {
|
||||
const getRecentItemLabel = (tab: Pick<Tab, 'label' | 'metadata'>) =>
|
||||
tab.label || tab.metadata?.name || 'Untitled'
|
||||
|
||||
const syncRecentItemWithTab = (item: RecentItem, tab: Pick<Tab, 'label' | 'metadata'>) => {
|
||||
const nextLabel = getRecentItemLabel(tab)
|
||||
|
||||
item.label = nextLabel
|
||||
item.metadata = {
|
||||
...item.metadata,
|
||||
...tab.metadata,
|
||||
name: nextLabel,
|
||||
}
|
||||
}
|
||||
|
||||
export function createTabsState(projectRef: string) {
|
||||
const recentItems = getSavedRecentItems(projectRef)
|
||||
const { openTabs, activeTab, tabsMap, previewTabId } = getSavedTabs(projectRef)
|
||||
|
||||
@@ -125,6 +139,7 @@ function createTabsState(projectRef: string) {
|
||||
if (existingItem) {
|
||||
// If it exists, update its timestamp
|
||||
existingItem.timestamp = Date.now()
|
||||
syncRecentItemWithTab(existingItem, tab)
|
||||
return // Exit the function
|
||||
}
|
||||
|
||||
@@ -132,7 +147,7 @@ function createTabsState(projectRef: string) {
|
||||
const recentItem: RecentItem = {
|
||||
id: tab.id, // Set the ID
|
||||
type: tab.type, // Set the type
|
||||
label: tab.label || 'Untitled', // Set the label or default to 'Untitled'
|
||||
label: getRecentItemLabel(tab), // Set the label or default to 'Untitled'
|
||||
timestamp: Date.now(), // Set the current timestamp
|
||||
metadata: tab.metadata, // Set the metadata
|
||||
}
|
||||
@@ -211,6 +226,8 @@ function createTabsState(projectRef: string) {
|
||||
if (!!store.tabsMap[id]) {
|
||||
if ('label' in updates) {
|
||||
store.tabsMap[id].label = updates.label
|
||||
const recentItem = store.recentItems.find((item) => item.id === id)
|
||||
if (recentItem) syncRecentItemWithTab(recentItem, store.tabsMap[id])
|
||||
}
|
||||
if ('scrollTop' in updates && store.tabsMap[id].metadata) {
|
||||
store.tabsMap[id].metadata.scrollTop = updates.scrollTop
|
||||
|
||||
Reference in new issue
Block a user