From de3e4c638030546cca2af2a8a5b2a66a3f52d756 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Mon, 25 Nov 2024 12:27:54 +0800 Subject: [PATCH] update ID handling --- .../TableEditorLayout/EntityListItem.tsx | 28 +++++++++++++++++-- .../pages/project/[ref]/editor/[id].tsx | 5 ++-- .../[ref]/explorer/schema/[schema].tsx | 4 +-- apps/studio/pages/project/[ref]/sql/[id].tsx | 4 +-- apps/studio/state/tabs.ts | 28 +++++++++++++++++++ .../ui/src/components/TreeView/TreeView.tsx | 4 +++ 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx index c0c06b8dd14..3c8589e588b 100644 --- a/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx +++ b/apps/studio/components/layouts/TableEditorLayout/EntityListItem.tsx @@ -49,7 +49,7 @@ import { TreeViewItemVariant, } from 'ui' import { useProjectContext } from '../ProjectLayout/ProjectContext' -import { getTabsStore } from 'state/tabs' +import { getTabsStore, createTabId, makeTabPermanent } from 'state/tabs' import { useSnapshot } from 'valtio' export interface EntityListItemProps { @@ -70,6 +70,13 @@ const EntityListItem: ItemRenderer = ({ const snap = useTableEditorStateSnapshot() const { selectedSchema } = useQuerySchemaState() + const tabId = createTabId('table', { + schema: selectedSchema, + name: entity.name, + }) + + const tabStore = getTabsStore(projectRef) + const isPreview = tabStore.previewTabId === tabId const isActive = _isActive ?? Number(id) === entity.id const { data: lints = [] } = useProjectLintsQuery({ @@ -283,10 +290,25 @@ const EntityListItem: ItemRenderer = ({ href={`/project/${projectRef}/editor/${entity.id}?schema=${selectedSchema}`} role="button" aria-label={`View ${entity.name}`} - className={cn(TreeViewItemVariant({ isSelected: isActive, isOpened }), 'px-4')} + className={cn( + TreeViewItemVariant({ + isSelected: isActive && !isPreview, + isOpened: isOpened && !isPreview, + isPreview, + }), + 'px-4' + )} + onDoubleClick={(e) => { + e.preventDefault() + const tabId = createTabId('table', { + schema: selectedSchema, + name: entity.name, + }) + makeTabPermanent(projectRef, tabId) + }} > <> - {isActive &&
} + {!isPreview && isActive &&
} {entity.type === ENTITY_TYPE.TABLE ? ( diff --git a/apps/studio/pages/project/[ref]/editor/[id].tsx b/apps/studio/pages/project/[ref]/editor/[id].tsx index 6287ce7adf7..8d8c0f1d88f 100644 --- a/apps/studio/pages/project/[ref]/editor/[id].tsx +++ b/apps/studio/pages/project/[ref]/editor/[id].tsx @@ -2,7 +2,6 @@ import { useParams } from 'common/hooks' import { TableGridEditor } from 'components/interfaces/TableGridEditor' import DeleteConfirmationDialogs from 'components/interfaces/TableGridEditor/DeleteConfirmationDialogs' import { EditorBaseLayout } from 'components/layouts/editors/editor-base-layout' -import { HandleEditorLayouts } from 'components/layouts/editors/handle-editor-layouts' import { ProjectContextFromParamsProvider, useProjectContext, @@ -13,7 +12,7 @@ import { useTableEditorQuery } from 'data/table-editor/table-editor-query' import { useTheme } from 'next-themes' import { useRouter } from 'next/router' import { useEffect } from 'react' -import { addTab, getTabsStore } from 'state/tabs' +import { addTab, createTabId, getTabsStore } from 'state/tabs' import type { NextPageWithLayout } from 'types' const TableEditorPage: NextPageWithLayout = () => { @@ -38,7 +37,7 @@ const TableEditorPage: NextPageWithLayout = () => { */ useEffect(() => { if (selectedTable && projectRef) { - const tabId = `table-${selectedTable.schema}-${selectedTable.name}` + const tabId = createTabId('table', { schema: selectedTable.schema, name: selectedTable.name }) if (!store.tabsMap[tabId]) { addTab(projectRef, { diff --git a/apps/studio/pages/project/[ref]/explorer/schema/[schema].tsx b/apps/studio/pages/project/[ref]/explorer/schema/[schema].tsx index 37461fd6167..c1e1fa6c22c 100644 --- a/apps/studio/pages/project/[ref]/explorer/schema/[schema].tsx +++ b/apps/studio/pages/project/[ref]/explorer/schema/[schema].tsx @@ -5,7 +5,7 @@ import { ProjectContextFromParamsProvider } from 'components/layouts/ProjectLayo import { useRouter } from 'next/router' import { useEffect } from 'react' import { ReactFlowProvider } from 'reactflow' -import { addTab, getTabsStore } from 'state/tabs' +import { addTab, createTabId, getTabsStore } from 'state/tabs' import type { NextPageWithLayout } from 'types' const SchemasPage: NextPageWithLayout = () => { @@ -16,7 +16,7 @@ const SchemasPage: NextPageWithLayout = () => { useEffect(() => { if (schema) { - const tabId = `schema-${schema}` + const tabId = createTabId('schema', { schema }) if (!store.tabsMap[tabId]) { addTab('explorer', { diff --git a/apps/studio/pages/project/[ref]/sql/[id].tsx b/apps/studio/pages/project/[ref]/sql/[id].tsx index e28ce3c5cf7..4159cda09e4 100644 --- a/apps/studio/pages/project/[ref]/sql/[id].tsx +++ b/apps/studio/pages/project/[ref]/sql/[id].tsx @@ -22,7 +22,7 @@ import { useRouter } from 'next/router' import { useEffect, useRef } from 'react' import { useAppStateSnapshot } from 'state/app-state' import { useSnippets, useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2' -import { addTab } from 'state/tabs' +import { addTab, createTabId } from 'state/tabs' import type { NextPageWithLayout } from 'types' const SqlEditor: NextPageWithLayout = () => { @@ -173,7 +173,7 @@ const SqlEditor: NextPageWithLayout = () => { useEffect(() => { if (!router.isReady || !id || id === 'new') return - const tabId = `sql-${id}` + const tabId = createTabId('sql', { id }) const snippet = snippets.find((s) => s.id === id) addTab(ref, { diff --git a/apps/studio/state/tabs.ts b/apps/studio/state/tabs.ts index 50439f58e9a..e99ed5cf7ff 100644 --- a/apps/studio/state/tabs.ts +++ b/apps/studio/state/tabs.ts @@ -290,3 +290,31 @@ export const handleTabDragEnd = ( // Handle navigation handleTabNavigation(ref, tabId, router) } +type CreateTabIdParams = { + table: { + schema: string + name: string + } + sql: { + id: string + } + schema: { + schema: string + } + view: never + function: never + new: never +} + +export function createTabId(type: T, params: CreateTabIdParams[T]): string { + switch (type) { + case 'table': + return `table-${(params as CreateTabIdParams['table']).schema}-${(params as CreateTabIdParams['table']).name}` + case 'sql': + return `sql-${(params as CreateTabIdParams['sql']).id}` + case 'schema': + return `schema-${(params as CreateTabIdParams['schema']).schema}` + default: + return '' + } +} diff --git a/packages/ui/src/components/TreeView/TreeView.tsx b/packages/ui/src/components/TreeView/TreeView.tsx index de89b7cdf32..15bf0d427ce 100644 --- a/packages/ui/src/components/TreeView/TreeView.tsx +++ b/packages/ui/src/components/TreeView/TreeView.tsx @@ -24,6 +24,10 @@ export const TreeViewItemVariant = cva( true: 'bg-control', false: '', }, + isPreview: { + true: 'bg-control', + false: '', + }, }, } )