diff --git a/frontend/src/App.tool-center.test.ts b/frontend/src/App.tool-center.test.ts index 17e9af5..114710f 100644 --- a/frontend/src/App.tool-center.test.ts +++ b/frontend/src/App.tool-center.test.ts @@ -117,22 +117,37 @@ describe('tool center menu entries', () => { expect(appSource).toContain('const handleOpenToolsModal = useCallback('); expect(appSource).toContain('const handleOpenSettingsModal = useCallback('); expect(appSource).toContain('const handleToggleLogPanel = useCallback('); + expect(appSource).toContain('new CustomEvent'); + expect(appSource).toContain("'gonavi:show-sql-execution-log'"); + expect(appSource).toContain("detail: { mode: 'open' }"); + expect(appSource).toContain('toggleAppLogPanel();'); expect(appSource).toContain('const handleFocusSidebarSearch = useCallback('); expect(appSource).toContain('const antdTheme = useMemo(() => ({'); expect(appSource).toContain('theme={antdTheme}'); - expect(appSource).toContain('const sqlLogCount = useStore(state => state.sqlLogs.length);'); expect(appSource).toContain('onOpenTools={handleOpenToolsModal}'); expect(appSource).toContain('onOpenSettings={handleOpenSettingsModal}'); expect(appSource).toContain('onToggleLogPanel={handleToggleLogPanel}'); expect(appSource).toContain('onFocusCommandSearch={handleFocusSidebarSearch}'); - expect(appSource).toContain('sqlLogCount={sqlLogCount}'); expect(appSource).not.toContain('onOpenTools={() => setIsToolsModalOpen(true)}'); expect(appSource).not.toContain('onOpenSettings={() => setIsSettingsModalOpen(true)}'); expect(appSource).not.toContain('onToggleLogPanel={() => setIsLogPanelOpen((prev) => !prev)}'); + expect(appSource).not.toContain('sqlLogCount={sqlLogCount}'); expect(appSource).not.toContain('theme={{'); expect(appSource).not.toContain('const sqlLogs = useStore(state => state.sqlLogs);'); }); + it('renders the shared SQL log panel only for legacy layouts', () => { + const logPanelIndex = appSource.indexOf(' { const siderIndex = appSource.indexOf("className={isV2Ui ? 'gn-v2-app-sider' : undefined}"); const legacyGuardIndex = appSource.indexOf('{!isV2Ui && (', siderIndex); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8e98f9f..52d17a8 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -391,7 +391,6 @@ function App() { const aiPanelVisible = useStore(state => state.aiPanelVisible); const toggleAIPanel = useStore(state => state.toggleAIPanel); const setAIPanelVisible = useStore(state => state.setAIPanelVisible); - const sqlLogCount = useStore(state => state.sqlLogs.length); const globalProxyInvalidHintShownRef = React.useRef(false); const windowDiagSequenceRef = React.useRef(0); const windowDiagLastSignatureRef = React.useRef(''); @@ -2139,23 +2138,23 @@ function App() { const { - handleCloseLogPanel: handleCloseLegacyLogPanel, + handleCloseLogPanel: handleCloseAppLogPanel, handleLogResizeStart, - handleToggleLogPanel: toggleLegacyLogPanel, + handleToggleLogPanel: toggleAppLogPanel, isLogPanelOpen, logGhostRef, logPanelHeight, } = useAppLogPanelResize(); const handleToggleLogPanel = useCallback(() => { if (isV2Ui) { - window.dispatchEvent(new CustomEvent('gonavi:show-sql-execution-log')); + window.dispatchEvent(new CustomEvent('gonavi:show-sql-execution-log', { detail: { mode: 'open' } })); return; } - toggleLegacyLogPanel(); - }, [isV2Ui, toggleLegacyLogPanel]); + toggleAppLogPanel(); + }, [isV2Ui, toggleAppLogPanel]); const handleCloseLogPanel = useCallback(() => { - handleCloseLegacyLogPanel(); - }, [handleCloseLegacyLogPanel]); + handleCloseAppLogPanel(); + }, [handleCloseAppLogPanel]); const handleCreateConnection = useCallback(() => { setSecurityUpdateRepairSource(null); @@ -2944,7 +2943,6 @@ function App() { onOpenSettings={handleOpenSettingsModal} onToggleAI={toggleAIPanel} onToggleLogPanel={handleToggleLogPanel} - sqlLogCount={sqlLogCount} uiVersion={appearance.uiVersion} onFocusCommandSearch={handleFocusSidebarSearch} /> diff --git a/frontend/src/components/DataGrid.layout.test.tsx b/frontend/src/components/DataGrid.layout.test.tsx index 816aa19..ef45525 100644 --- a/frontend/src/components/DataGrid.layout.test.tsx +++ b/frontend/src/components/DataGrid.layout.test.tsx @@ -34,6 +34,12 @@ const readDataGridSource = () => [ './DataGridCore.tsx', './DataGridShell.tsx', ].map((file) => readFileSync(new URL(file, import.meta.url), 'utf8')).join('\n'); +const readDataViewerSource = (): string => + readFileSync(new URL('./DataViewer.tsx', import.meta.url), 'utf8'); +const readDataGridSecondaryActionsSource = (): string => + readFileSync(new URL('./DataGridSecondaryActions.tsx', import.meta.url), 'utf8'); +const readDataGridShellSource = (): string => + readFileSync(new URL('./DataGridShell.tsx', import.meta.url), 'utf8'); const mockStoreState = vi.hoisted(() => ({ languagePreference: 'system' as LanguagePreference, @@ -172,6 +178,7 @@ describe('DataGrid layout', () => { expect(markup).toContain('data-grid-column-quick-find-action="true"'); expect(markup).toContain('字段显示'); expect(markup).toContain('跳列'); + expect(markup).toContain('日志'); expect(markup).toContain(zhObjectDesignLabel); expect(markup).toContain('data-grid-page-find="true"'); expect(markup).toContain('data-grid-page-find-prev="true"'); @@ -190,6 +197,27 @@ describe('DataGrid layout', () => { expect(markup).toContain('当前页查找...'); }); + it('opens the embedded SQL log view from the shared V2 SQL log event in table data tabs', () => { + const source = readDataGridSource(); + const dataViewerSource = readDataViewerSource(); + const secondaryActionsSource = readDataGridSecondaryActionsSource(); + const shellSource = readDataGridShellSource(); + + expect(dataViewerSource).toContain('isActive={isActive}'); + expect(dataViewerSource).toContain('enableSqlLogEvent'); + expect(source).toContain("isActive = true"); + expect(source).toContain("enableSqlLogEvent = false"); + expect(source).toContain("'gonavi:show-sql-execution-log'"); + expect(source).toContain("if (!enableSqlLogEvent || !isV2Ui || !isActive) return;"); + expect(source).toContain("handleViewModeChange('sqlLog');"); + expect(source).toContain("'sqlLog'"); + expect(shellSource).toContain('import LogPanel from'); + expect(shellSource).toContain("viewMode === 'sqlLog'"); + expect(shellSource).toContain(''); + expect(secondaryActionsSource).toContain("key: 'sqlLog'"); + expect(secondaryActionsSource).toContain("translate('log_panel.short_title')"); + }); + it('localizes DataGrid error boundary, column drag affordances, and legacy row context menu labels through i18n keys', () => { const source = readDataGridSource(); const expectedKeys = [ diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index ad43fe6..4a8e44d 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -286,7 +286,7 @@ const DataGrid: React.FC = ({ resultExportAllSql, onReload, onSort, onPageChange, pagination, onRequestTotalCount, onCancelTotalCount, sortInfoExternal, showFilter, onToggleFilter, exportSqlWithFilter, onApplyFilter, appliedFilterConditions, quickWhereCondition, onApplyQuickWhereCondition, - scrollSnapshot, onScrollSnapshotChange, toolbarExtraActions, showRowNumberColumn = false + scrollSnapshot, onScrollSnapshotChange, toolbarExtraActions, showRowNumberColumn = false, isActive = true, enableSqlLogEvent = false }) => { const connections = useStore(state => state.connections); const addTab = useStore(state => state.addTab); @@ -1351,13 +1351,23 @@ const DataGrid: React.FC = ({ if (String(detail.tableName || '') !== String(tableName || '')) return; const nextMode = String(detail.viewMode || '').trim(); if (!nextMode) return; - if (!['table', 'json', 'text', 'fields', 'ddl', 'er'].includes(nextMode)) return; + if (!['table', 'json', 'text', 'fields', 'ddl', 'er', 'sqlLog'].includes(nextMode)) return; handleViewModeChange(nextMode as GridViewMode); }; window.addEventListener('gonavi:data-grid:set-view-mode', handleExternalViewModeChange as EventListener); return () => window.removeEventListener('gonavi:data-grid:set-view-mode', handleExternalViewModeChange as EventListener); - }, [canOpenObjectDesigner, connectionId, dbName, handleViewModeChange, tableName]); + }, [connectionId, dbName, handleViewModeChange, tableName]); + + useEffect(() => { + if (!enableSqlLogEvent || !isV2Ui || !isActive) return; + const handleOpenSqlExecutionLog = () => { + handleViewModeChange('sqlLog'); + }; + + window.addEventListener('gonavi:show-sql-execution-log', handleOpenSqlExecutionLog as EventListener); + return () => window.removeEventListener('gonavi:show-sql-execution-log', handleOpenSqlExecutionLog as EventListener); + }, [enableSqlLogEvent, handleViewModeChange, isActive, isV2Ui]); useEffect(() => { if (!isTableSurfaceActive || !isV2Ui || !cellContextMenu.visible) return; diff --git a/frontend/src/components/DataGridCore.tsx b/frontend/src/components/DataGridCore.tsx index b341b23..fbb999e 100644 --- a/frontend/src/components/DataGridCore.tsx +++ b/frontend/src/components/DataGridCore.tsx @@ -1334,6 +1334,8 @@ interface DataGridProps { scrollSnapshot?: { top: number; left: number }; onScrollSnapshotChange?: (snapshot: { top: number; left: number }) => void; toolbarExtraActions?: React.ReactNode; + isActive?: boolean; + enableSqlLogEvent?: boolean; } type GridFilterCondition = FilterCondition & { @@ -1344,7 +1346,7 @@ type GridFilterCondition = FilterCondition & { value2?: string; }; -type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er'; +type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er' | 'sqlLog'; type DdlViewLayoutMode = 'bottom' | 'side'; type DataGridExportScope = 'selected' | 'page' | 'all' | 'filteredAll'; type VirtualEditingCellState = { diff --git a/frontend/src/components/DataGridResultViewSwitcher.tsx b/frontend/src/components/DataGridResultViewSwitcher.tsx index 8a66a16..6ced1d6 100644 --- a/frontend/src/components/DataGridResultViewSwitcher.tsx +++ b/frontend/src/components/DataGridResultViewSwitcher.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { Segmented } from 'antd'; import { t as defaultTranslate, type I18nParams } from '../i18n'; -type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er'; +type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er' | 'sqlLog'; export type DataGridResultViewTranslate = (key: string, params?: I18nParams) => string; diff --git a/frontend/src/components/DataGridSecondaryActions.tsx b/frontend/src/components/DataGridSecondaryActions.tsx index 3eb7d98..aae0a77 100644 --- a/frontend/src/components/DataGridSecondaryActions.tsx +++ b/frontend/src/components/DataGridSecondaryActions.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Button, Popover } from 'antd'; import { AimOutlined, + BugOutlined, ConsoleSqlOutlined, EditOutlined, FileTextOutlined, @@ -10,7 +11,7 @@ import { } from '@ant-design/icons'; import { t as defaultTranslate, type I18nParams } from '../i18n'; -type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er'; +type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er' | 'sqlLog'; export type DataGridSecondaryActionsTranslate = (key: string, params?: I18nParams) => string; @@ -69,6 +70,7 @@ const DataGridSecondaryActions: React.FC = ({ { key: 'fields', label: fieldsActionLabel, icon: fieldsActionIcon }, { key: 'ddl', label: translate('data_grid.secondary.view_ddl'), icon: , disabled: !canViewDdl }, { key: 'er', label: translate('data_grid.secondary.er_diagram'), icon: }, + { key: 'sqlLog', label: translate('log_panel.short_title'), icon: }, ]; return ( diff --git a/frontend/src/components/DataGridShell.tsx b/frontend/src/components/DataGridShell.tsx index bdecebc..abdfbd6 100644 --- a/frontend/src/components/DataGridShell.tsx +++ b/frontend/src/components/DataGridShell.tsx @@ -9,6 +9,7 @@ import DataGridModals from './DataGridModals'; import DataGridPreviewPanel from './DataGridPreviewPanel'; import DataGridSecondaryActions from './DataGridSecondaryActions'; import DataGridToolbarFrame from './DataGridToolbarFrame'; +import LogPanel from './LogPanel'; import { DataGridJsonView, DataGridTextView } from './DataGridRecordViews'; import { DataGridV2DdlSideWorkspace, DataGridV2DdlView } from './DataGridV2DdlWorkspace'; import { DataGridV2ErView, DataGridV2FieldsView } from './DataGridV2MetadataViews'; @@ -789,6 +790,8 @@ const renderDataTableView = () => ( onOpenTable={onOpenErTable} translate={translateDataGrid} /> + ) : isV2Ui && viewMode === 'sqlLog' ? ( + ) : viewMode === 'json' ? ( = React.memo(({ exportSqlWithFilter={exportSqlWithFilter || undefined} scrollSnapshot={scrollSnapshotRef.current} onScrollSnapshotChange={handleTableScrollSnapshotChange} + isActive={isActive} + enableSqlLogEvent /> ); diff --git a/frontend/src/components/QueryEditor.external-sql-save.test.tsx b/frontend/src/components/QueryEditor.external-sql-save.test.tsx index 06cd937..fb9e08e 100644 --- a/frontend/src/components/QueryEditor.external-sql-save.test.tsx +++ b/frontend/src/components/QueryEditor.external-sql-save.test.tsx @@ -989,7 +989,7 @@ describe('QueryEditor external SQL save', () => { renderer.unmount(); }); - it('opens the embedded sql execution log tab from the shared log toggle event in v2', async () => { + it('opens the embedded sql execution log tab from the shared log event in v2', async () => { storeState.appearance.uiVersion = 'v2'; storeState.sqlLogs = [{ id: 'log-1', @@ -1043,6 +1043,54 @@ describe('QueryEditor external SQL save', () => { renderer.unmount(); }); + it('keeps the embedded sql execution log tab open for explicit open events in v2', async () => { + storeState.appearance.uiVersion = 'v2'; + storeState.sqlLogs = [{ + id: 'log-1', + timestamp: Date.now(), + sql: 'select 1', + status: 'success', + duration: 12, + }]; + + const windowListeners: Record void)[]> = {}; + vi.stubGlobal('window', { + addEventListener: vi.fn((type: string, listener: (event?: any) => void) => { + windowListeners[type] ||= []; + windowListeners[type].push(listener); + }), + removeEventListener: vi.fn(), + dispatchEvent: vi.fn(), + requestAnimationFrame: vi.fn((callback: FrameRequestCallback) => { + callback(0); + return 1; + }), + cancelAnimationFrame: vi.fn(), + innerHeight: 900, + }); + + let renderer!: ReactTestRenderer; + await act(async () => { + renderer = create(); + }); + + const openEvent = new CustomEvent('gonavi:show-sql-execution-log', { detail: { mode: 'open' } }); + await act(async () => { + windowListeners['gonavi:show-sql-execution-log']?.forEach((listener) => listener(openEvent)); + }); + expect(textContent(renderer.toJSON())).toContain('SQL 执行日志'); + + await act(async () => { + windowListeners['gonavi:show-sql-execution-log']?.forEach((listener) => listener(openEvent)); + }); + expect(textContent(renderer.toJSON())).toContain('SQL 执行日志'); + expect(storeState.updateQueryTabDraft).toHaveBeenLastCalledWith('tab-1', { + resultPanelVisible: true, + }); + + renderer.unmount(); + }); + it('shows execution failures inside the embedded sql log tab in v2', async () => { storeState.appearance.uiVersion = 'v2'; backendApp.DBQueryMulti.mockResolvedValueOnce({ diff --git a/frontend/src/components/QueryEditor.results-and-drop.test.tsx b/frontend/src/components/QueryEditor.results-and-drop.test.tsx index 3a1e9ef..abe4293 100644 --- a/frontend/src/components/QueryEditor.results-and-drop.test.tsx +++ b/frontend/src/components/QueryEditor.results-and-drop.test.tsx @@ -15,6 +15,7 @@ import QueryEditor, { resolveQueryEditorNavigationDecorations, resolveQueryEditorNavigationTarget, } from './QueryEditor'; +import QueryEditorResultsPanel from './QueryEditorResultsPanel'; const storeState = vi.hoisted(() => ({ connections: [ @@ -2645,20 +2646,59 @@ describe('QueryEditor external SQL save', () => { expect(source).toContain("if (isEditableElement(event.target) && !inEditorPane) {"); }); - it('embeds the sql execution log as a result tab instead of a standalone workspace panel in v2', () => { + it('keeps the embedded sql execution log limited to v2 query editor result tabs', () => { const panelSource = readFileSync(new URL('./QueryEditorResultsPanel.tsx', import.meta.url), 'utf8'); const editorSource = readFileSync(new URL('./QueryEditor.tsx', import.meta.url), 'utf8'); expect(panelSource).toContain('QUERY_EDITOR_SQL_LOG_TAB_KEY'); + expect(panelSource).toContain('const shouldShowSqlLogTab = isV2Ui && (sqlLogCount > 0 || activeResultKey === QUERY_EDITOR_SQL_LOG_TAB_KEY);'); expect(panelSource).toContain(' { + const renderResultsPanel = (isV2Ui: boolean) => create( + , + ); + + const legacyRenderer = renderResultsPanel(false); + expect(legacyRenderer.root.findAll((node) => node.props?.['data-log-panel'] === 'true')).toHaveLength(0); + expect(legacyRenderer.root.findAll((node) => node.props?.['data-tab-key'] === '__gonavi_sql_execution_log__')).toHaveLength(0); + legacyRenderer.unmount(); + + const v2Renderer = renderResultsPanel(true); + expect(v2Renderer.root.findAll((node) => node.props?.['data-log-panel'] === 'true')).toHaveLength(1); + expect(v2Renderer.root.findAll((node) => node.props?.['data-tab-key'] === '__gonavi_sql_execution_log__')).toHaveLength(1); + v2Renderer.unmount(); + }); + it('keeps the v2 query editor toolbar grouped and compact', () => { const source = readFileSync(new URL('./QueryEditor.tsx', import.meta.url), 'utf8'); const toolbarSource = readFileSync(new URL('./QueryEditorToolbar.tsx', import.meta.url), 'utf8'); diff --git a/frontend/src/components/QueryEditor.tsx b/frontend/src/components/QueryEditor.tsx index 0cb70fb..dd8c54f 100644 --- a/frontend/src/components/QueryEditor.tsx +++ b/frontend/src/components/QueryEditor.tsx @@ -385,11 +385,11 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc return nextVisible; }); }, [tab.id, updateQueryTabDraft]); - const handleShowSqlExecutionLog = useCallback(() => { + const handleShowSqlExecutionLog = useCallback((mode: 'open' | 'toggle' = 'toggle') => { if (!isActive) { return; } - if (isResultPanelVisible && activeResultKey === QUERY_EDITOR_SQL_LOG_TAB_KEY) { + if (mode !== 'open' && isResultPanelVisible && activeResultKey === QUERY_EDITOR_SQL_LOG_TAB_KEY) { updateResultPanelVisibility(false); return; } @@ -4467,8 +4467,9 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc }, [isActive, handleQuickSave]); useEffect(() => { - const handleOpenSqlExecutionLog = () => { - handleShowSqlExecutionLog(); + const handleOpenSqlExecutionLog = (event: Event) => { + const mode = event instanceof CustomEvent && event.detail?.mode === 'open' ? 'open' : 'toggle'; + handleShowSqlExecutionLog(mode); }; window.addEventListener('gonavi:show-sql-execution-log', handleOpenSqlExecutionLog as EventListener); diff --git a/frontend/src/components/QueryEditorResultsPanel.tsx b/frontend/src/components/QueryEditorResultsPanel.tsx index f607526..02fd5aa 100644 --- a/frontend/src/components/QueryEditorResultsPanel.tsx +++ b/frontend/src/components/QueryEditorResultsPanel.tsx @@ -81,7 +81,7 @@ const QueryEditorResultsPanel: React.FC = ({ }) => { const i18n = useOptionalI18n(); const t = i18n?.t ?? defaultTranslate; - const shouldShowSqlLogTab = sqlLogCount > 0 || activeResultKey === QUERY_EDITOR_SQL_LOG_TAB_KEY; + const shouldShowSqlLogTab = isV2Ui && (sqlLogCount > 0 || activeResultKey === QUERY_EDITOR_SQL_LOG_TAB_KEY); const logTabCountLabel = sqlLogCount > 999 ? '999+' : String(sqlLogCount); const resolvedResultSetKey = activeResultKey && resultSets.some((rs) => rs.key === activeResultKey) ? activeResultKey diff --git a/frontend/src/components/Sidebar.locate-toolbar.test.tsx b/frontend/src/components/Sidebar.locate-toolbar.test.tsx index eaa2c1a..e386cb0 100644 --- a/frontend/src/components/Sidebar.locate-toolbar.test.tsx +++ b/frontend/src/components/Sidebar.locate-toolbar.test.tsx @@ -697,8 +697,8 @@ describe('Sidebar locate toolbar', () => { expect(source).not.toContain("justifyContent: 'space-between', borderTop: `1px solid ${darkMode ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.04)'}`, borderBottom: `1px solid ${darkMode ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.04)'}`, background: darkMode ? 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.015)' }}>"); }); - it('renders the v2 sidebar rail, command search hint, filter tabs and log footer', () => { - const markup = renderSidebarMarkup({ uiVersion: 'v2', sqlLogCount: 2341, onCreateConnection: mocks.noop }); + it('renders the v2 sidebar rail, command search hint, filter tabs and slow-query footer', () => { + const markup = renderSidebarMarkup({ uiVersion: 'v2', onCreateConnection: mocks.noop }); const source = readSidebarSource(); expect(markup).toContain('gn-v2-sidebar-redesign'); @@ -734,8 +734,10 @@ describe('Sidebar locate toolbar', () => { expect(source).toContain('onClick={() => setV2ExplorerFilter(item.key)}'); expect(source).toContain('treeData={isV2Ui ? v2VisibleTreeData : displayTreeData}'); expect(markup).toContain('gn-v2-sidebar-log-footer'); - expect(markup).toContain('SQL 执行日志'); - expect(markup).toContain('2,341'); + expect(markup).toContain('gn-v2-sidebar-slow-query-button'); + expect(markup).not.toContain('gn-v2-sidebar-log-button'); + expect(markup).not.toContain('SQL 执行日志'); + expect(markup).not.toContain('2,341'); expect(markup).not.toContain('gn-v2-rail-action-group'); expect(source).toContain('className="gn-v2-rail-primary-actions"'); expect(markup).toContain('data-sidebar-create-group-action="true"'); diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index 412111f..ef0c4d8 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -99,8 +99,7 @@ import { Tree, message, Dropdown, MenuProps, Input, Button, Form, Popover, Toolt AimOutlined, MoreOutlined, ToolOutlined, - SettingOutlined, - BarsOutlined + SettingOutlined } from '@ant-design/icons'; import { buildSidebarRootConnectionToken, @@ -369,7 +368,6 @@ const Sidebar: React.FC<{ onOpenSettings?: () => void; onToggleAI?: () => void; onToggleLogPanel?: () => void; - sqlLogCount?: number; uiVersion?: 'legacy' | 'v2'; onFocusCommandSearch?: () => void; }> = React.memo(({ @@ -379,7 +377,6 @@ const Sidebar: React.FC<{ onOpenSettings, onToggleAI, onToggleLogPanel, - sqlLogCount = 0, uiVersion, onFocusCommandSearch, }) => { @@ -2854,11 +2851,6 @@ const Sidebar: React.FC<{ {isV2Ui && (
- ; @@ -118,15 +118,19 @@ export const useDataGridDdlView = ({ }, [canViewDdl, currentConnConfig, dbName, dbType, isV2Ui, messageApi, tableName, translateMessage]); React.useEffect(() => { - if (isV2Ui || (viewMode !== 'fields' && viewMode !== 'ddl' && viewMode !== 'er')) return; + if (isV2Ui || (viewMode !== 'fields' && viewMode !== 'ddl' && viewMode !== 'er' && viewMode !== 'sqlLog')) return; setViewMode('table'); }, [isV2Ui, viewMode]); const handleViewModeChange = React.useCallback((nextMode: GridViewMode) => { - if ((nextMode === 'fields' || nextMode === 'ddl' || nextMode === 'er') && !isV2Ui) { + if ((nextMode === 'fields' || nextMode === 'ddl' || nextMode === 'er' || nextMode === 'sqlLog') && !isV2Ui) { setViewMode('table'); return; } + if (nextMode === 'sqlLog') { + setViewMode('sqlLog'); + return; + } if (nextMode === 'ddl') { void handleOpenTableDdl({ asView: true }); setViewMode('ddl'); diff --git a/frontend/src/v2-theme.css b/frontend/src/v2-theme.css index b1a2493..3c46753 100644 --- a/frontend/src/v2-theme.css +++ b/frontend/src/v2-theme.css @@ -2950,35 +2950,6 @@ body[data-ui-version="v2"] .gn-v2-sidebar-log-footer { gap: 8px; } -body[data-ui-version="v2"] .gn-v2-sidebar-log-button { - width: auto; - min-width: 0; - flex: 1 1 auto; - height: 28px; - border: 0; - border-radius: 8px; - background: transparent; - color: var(--gn-fg-2); - display: inline-flex; - align-items: center; - gap: 6px; - padding: 0 10px; - font-size: 12.5px; - font-weight: 400; -} - -body[data-ui-version="v2"] .gn-v2-sidebar-log-button:hover { - background: var(--gn-bg-hover); -} - -body[data-ui-version="v2"] .gn-v2-sidebar-log-button small { - margin-left: auto; - color: var(--gn-fg-4); - font-family: var(--gn-font-mono); - font-size: 10.5px; - font-weight: 400; -} - body[data-ui-version="v2"] .gn-v2-sidebar-slow-query-button { width: 28px; height: 28px;