From ce30de20b6bba6d0335f85e42ee9e0238758cdc8 Mon Sep 17 00:00:00 2001 From: Syngnat Date: Thu, 25 Jun 2026 21:36:14 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(data-grid):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20DDL=20=E8=A7=86=E5=9B=BE=E5=B8=B8=E9=A9=BB=E4=B8=8E?= =?UTF-8?q?=E4=BE=A7=E6=A0=8F=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 记忆 DDL 底部/侧栏布局并支持切表常驻刷新 修复侧栏关闭、拖拽预览和首次加载布局抖动 优化 DDL 行号 gutter,并保留文本选择时的横向视角 --- frontend/src/components/DataGrid.tsx | 37 ++- frontend/src/components/DataGridShell.tsx | 3 + .../src/components/DataGridV2DdlWorkspace.tsx | 89 ++++++- frontend/src/components/useDataGridDdlView.ts | 226 ++++++++++++++++-- frontend/src/v2-theme.css | 31 ++- 5 files changed, 356 insertions(+), 30 deletions(-) diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index 4a8e44d..298c303 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -1322,6 +1322,7 @@ const DataGrid: React.FC = ({ handleViewModeChange, handleDdlSidebarResizeStart, resetDdlViewState, + closeDdlView, } = useDataGridDdlView({ canViewDdl, currentConnConfig, @@ -1329,6 +1330,7 @@ const DataGrid: React.FC = ({ dbType, tableName, isV2Ui, + isActive, cellEditMode, selectedRowKeys, mergedDisplayDataRef, @@ -1833,8 +1835,19 @@ const DataGrid: React.FC = ({ }, [displayData, modifiedRows, deletedRowKeys]); mergedDisplayDataRef.current = mergedDisplayData; + const dataSourceContextKey = useMemo( + () => `${connectionId || ''}\u0001${dbName || ''}\u0001${tableName || ''}`, + [connectionId, dbName, tableName], + ); + const previousDataSourceContextKeyRef = useRef(null); + // Reset local state when data source likely changes (e.g. tableName change) useEffect(() => { + const previousContextKey = previousDataSourceContextKeyRef.current; + const contextChanged = previousContextKey !== dataSourceContextKey; + previousDataSourceContextKeyRef.current = dataSourceContextKey; + if (!contextChanged) return; + setAddedRows([]); setModifiedRows({}); setDeletedRowKeys(new Set()); @@ -1843,11 +1856,30 @@ const DataGrid: React.FC = ({ setCopiedCellPatch(null); setCopiedRowsForPaste([]); closeRowEditor(); - resetDdlViewState(); + const shouldKeepOpenV2DdlView = previousContextKey !== null + && isV2Ui + && viewMode === 'ddl' + && canViewDdl + && !!currentConnConfig + && !!tableName; + if (!shouldKeepOpenV2DdlView && previousContextKey !== null) { + resetDdlViewState(); + } closeVirtualInlineEditor(); closeCellEditor(); formRef.current.resetFields(); - }, [tableName, dbName, connectionId, closeRowEditor, resetDdlViewState, closeVirtualInlineEditor, closeCellEditor]); // Reset on context change + }, [ + canViewDdl, + closeCellEditor, + closeRowEditor, + closeVirtualInlineEditor, + currentConnConfig, + dataSourceContextKey, + isV2Ui, + resetDdlViewState, + tableName, + viewMode, + ]); // Reset on context change useEffect(() => { const next = new Map(); @@ -4260,6 +4292,7 @@ const DataGrid: React.FC = ({ handleCopyUpdate, handleDataPanelFormatJson, handleDataPanelSave, + closeDdlView, handleDdlSidebarResizeStart, handleDeleteSelected, handleDragEnd, diff --git a/frontend/src/components/DataGridShell.tsx b/frontend/src/components/DataGridShell.tsx index abdfbd6..2e57c2f 100644 --- a/frontend/src/components/DataGridShell.tsx +++ b/frontend/src/components/DataGridShell.tsx @@ -83,6 +83,7 @@ const DataGridShell: React.FC = (props) => { closeBatchEditModal, closeCellEditMode, closeCellEditor, + closeDdlView, closeJsonEditor, closeRowEditor, closestCenter, @@ -755,6 +756,7 @@ const renderDataTableView = () => ( ddlText={ddlText} darkMode={darkMode} onDdlViewLayoutChange={setDdlViewLayout} + onClose={closeDdlView} onReload={() => { void handleOpenTableDdl({ asView: true }); }} @@ -773,6 +775,7 @@ const renderDataTableView = () => ( ddlText={ddlText} darkMode={darkMode} onDdlViewLayoutChange={setDdlViewLayout} + onClose={closeDdlView} onReload={() => { void handleOpenTableDdl({ asView: true }); }} diff --git a/frontend/src/components/DataGridV2DdlWorkspace.tsx b/frontend/src/components/DataGridV2DdlWorkspace.tsx index 2c37657..6122cd9 100644 --- a/frontend/src/components/DataGridV2DdlWorkspace.tsx +++ b/frontend/src/components/DataGridV2DdlWorkspace.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button, Segmented } from 'antd'; import { CopyOutlined } from '@ant-design/icons'; -import Editor from './MonacoEditor'; +import Editor, { type OnMount } from './MonacoEditor'; import { t as defaultTranslate, type I18nParams } from '../i18n'; type DdlViewLayoutMode = 'bottom' | 'side'; @@ -16,10 +16,82 @@ export interface DataGridV2DdlViewProps { ddlText: string; darkMode: boolean; onDdlViewLayoutChange: (layout: DdlViewLayoutMode) => void; + onClose?: () => void; onReload: () => void; onCopy: () => void; } +const handleReadOnlyDdlEditorMount: OnMount = (editor, monaco) => { + const contentMouseTargetTypes = new Set([ + monaco.editor.MouseTargetType.CONTENT_TEXT, + monaco.editor.MouseTargetType.CONTENT_EMPTY, + ]); + let pendingContentInteraction: + | { x: number; y: number; scrollLeft: number } + | null = null; + + const getMousePoint = (event: any) => ({ + x: Number.isFinite(Number(event?.posx)) ? Number(event.posx) : Number(event?.browserEvent?.clientX ?? 0), + y: Number.isFinite(Number(event?.posy)) ? Number(event.posy) : Number(event?.browserEvent?.clientY ?? 0), + }); + + const restoreScrollLeft = (scrollLeft: number) => { + const apply = () => { + if (typeof editor.getScrollLeft === 'function' && editor.getScrollLeft() === scrollLeft) return; + editor.setScrollLeft?.(scrollLeft); + }; + apply(); + if (typeof requestAnimationFrame === 'function') { + requestAnimationFrame(() => { + apply(); + requestAnimationFrame(apply); + }); + } + }; + + editor.onDidScrollChange?.((event: any) => { + if (!pendingContentInteraction) return; + if (event?.scrollLeftChanged === false) return; + restoreScrollLeft(pendingContentInteraction.scrollLeft); + }); + + editor.onMouseDown((event: any) => { + pendingContentInteraction = null; + if (!contentMouseTargetTypes.has(event.target?.type)) return; + const mouseEvent = event.event; + if (mouseEvent?.browserEvent && mouseEvent.browserEvent.button !== 0) return; + if (mouseEvent?.leftButton === false) return; + const point = getMousePoint(mouseEvent); + pendingContentInteraction = { + ...point, + scrollLeft: typeof editor.getScrollLeft === 'function' ? editor.getScrollLeft() : 0, + }; + }); + + editor.onMouseUp((event: any) => { + const interaction = pendingContentInteraction; + if (!interaction) return; + const point = getMousePoint(event.event); + const moved = Math.abs(point.x - interaction.x) > 3 || Math.abs(point.y - interaction.y) > 3; + restoreScrollLeft(interaction.scrollLeft); + if (!moved) { + pendingContentInteraction = null; + return; + } + if (typeof requestAnimationFrame === 'function') { + requestAnimationFrame(() => { + requestAnimationFrame(() => { + if (pendingContentInteraction === interaction) { + pendingContentInteraction = null; + } + }); + }); + return; + } + pendingContentInteraction = null; + }); +}; + export const DataGridV2DdlView: React.FC = ({ layout, translate = defaultTranslate, @@ -29,16 +101,17 @@ export const DataGridV2DdlView: React.FC = ({ ddlText, darkMode, onDdlViewLayoutChange, + onClose, onReload, onCopy, }) => (
-
+
DDL {tableName ? `DDL - ${tableName}` : 'DDL'}
-
+
= ({ {translate('data_grid.ddl.copy')} {layout === 'side' && ( - )} @@ -68,13 +141,21 @@ export const DataGridV2DdlView: React.FC = ({ language="sql" theme={darkMode ? 'transparent-dark' : 'transparent-light'} value={ddlLoading ? translate('data_grid.ddl.loading') : ddlText} + onMount={handleReadOnlyDdlEditorMount} options={{ readOnly: true, + domReadOnly: true, minimap: { enabled: false }, scrollBeyondLastLine: false, wordWrap: 'off', tabSize: 2, automaticLayout: true, + mouseStyle: 'default', + renderLineHighlight: 'none', + glyphMargin: false, + folding: false, + lineDecorationsWidth: 8, + lineNumbersMinChars: 2, }} />
diff --git a/frontend/src/components/useDataGridDdlView.ts b/frontend/src/components/useDataGridDdlView.ts index 7065e69..5364ba1 100644 --- a/frontend/src/components/useDataGridDdlView.ts +++ b/frontend/src/components/useDataGridDdlView.ts @@ -7,6 +7,70 @@ import { formatDdlForDisplay } from '../utils/ddlFormat'; type GridViewMode = 'table' | 'json' | 'text' | 'fields' | 'ddl' | 'er' | 'sqlLog'; type DdlViewLayoutMode = 'bottom' | 'side'; type TranslateParams = Record; +const DDL_VIEW_LAYOUT_STORAGE_KEY = 'gonavi.dataGrid.ddlViewLayout'; +let sharedDdlViewOpen = false; +let sharedDdlViewLayout: DdlViewLayoutMode | null = null; +const ddlViewLayoutListeners = new Set<(layout: DdlViewLayoutMode) => void>(); + +const sanitizeDdlViewLayout = (value: unknown): DdlViewLayoutMode => ( + value === 'side' ? 'side' : 'bottom' +); + +const readPersistedDdlViewLayout = (): DdlViewLayoutMode => { + try { + const storage = typeof window !== 'undefined' ? window.localStorage : undefined; + return sanitizeDdlViewLayout(storage?.getItem(DDL_VIEW_LAYOUT_STORAGE_KEY)); + } catch { + return 'bottom'; + } +}; + +const persistDdlViewLayout = (layout: DdlViewLayoutMode) => { + try { + if (typeof window !== 'undefined') { + window.localStorage?.setItem(DDL_VIEW_LAYOUT_STORAGE_KEY, layout); + } + } catch { + // Ignore storage failures in restricted runtimes. + } +}; + +const readSharedDdlViewLayout = (): DdlViewLayoutMode => { + if (!sharedDdlViewLayout) { + sharedDdlViewLayout = readPersistedDdlViewLayout(); + } + return sharedDdlViewLayout; +}; + +const setSharedDdlViewLayout = (layout: DdlViewLayoutMode) => { + sharedDdlViewLayout = layout; + persistDdlViewLayout(layout); + ddlViewLayoutListeners.forEach((listener) => listener(layout)); +}; + +const setSharedDdlViewOpen = (open: boolean) => { + sharedDdlViewOpen = open; +}; + +const shouldRestoreSharedDdlView = () => sharedDdlViewOpen; + +export const resetDataGridDdlViewSharedStateForTests = () => { + sharedDdlViewOpen = false; + sharedDdlViewLayout = null; + ddlViewLayoutListeners.clear(); +}; + +const buildDdlContextKey = (currentConnConfig: unknown, dbName?: string, tableName?: string) => { + const config = (currentConnConfig || {}) as Record; + return [ + String(config.type || ''), + String(config.host || ''), + String(config.port || ''), + String(config.database || ''), + dbName || '', + tableName || '', + ].join('\u0001'); +}; interface UseDataGridDdlViewParams { canViewDdl: boolean; @@ -14,6 +78,7 @@ interface UseDataGridDdlViewParams { dbName?: string; tableName?: string; isV2Ui: boolean; + isActive?: boolean; cellEditMode: boolean; selectedRowKeys: React.Key[]; mergedDisplayDataRef: React.MutableRefObject; @@ -44,6 +109,7 @@ export interface UseDataGridDdlViewResult { handleViewModeChange: (nextMode: GridViewMode) => void; handleDdlSidebarResizeStart: (event: React.MouseEvent) => void; resetDdlViewState: () => void; + closeDdlView: () => void; } export const useDataGridDdlView = ({ @@ -52,6 +118,7 @@ export const useDataGridDdlView = ({ dbName, tableName, isV2Ui, + isActive = true, cellEditMode, selectedRowKeys, mergedDisplayDataRef, @@ -62,28 +129,71 @@ export const useDataGridDdlView = ({ dbType, translate, }: UseDataGridDdlViewParams): UseDataGridDdlViewResult => { - const [viewMode, setViewMode] = React.useState('table'); + const canRestoreSharedDdlView = isV2Ui && canViewDdl && !!currentConnConfig && !!tableName && shouldRestoreSharedDdlView(); + const shouldStartWithSharedDdlView = isActive && canRestoreSharedDdlView; + const [viewMode, setViewMode] = React.useState(() => (shouldStartWithSharedDdlView ? 'ddl' : 'table')); const [ddlModalOpen, setDdlModalOpen] = React.useState(false); - const [ddlLoading, setDdlLoading] = React.useState(false); + const [ddlLoading, setDdlLoading] = React.useState(shouldStartWithSharedDdlView); const [ddlText, setDdlText] = React.useState(''); - const [ddlViewLayout, setDdlViewLayout] = React.useState('bottom'); + const [ddlViewLayoutState, setDdlViewLayoutState] = React.useState(readSharedDdlViewLayout); const [ddlSidebarWidth, setDdlSidebarWidth] = React.useState(420); const [ddlSidebarResizePreviewX, setDdlSidebarResizePreviewX] = React.useState(null); const ddlSidebarResizeRef = React.useRef<{ startX: number; startWidth: number; previewWidth: number; + previewX: number | null; + previewElement?: HTMLElement | null; + previewFrame?: number | null; moveHandler?: (event: MouseEvent) => void; upHandler?: () => void; } | null>(null); const ddlRequestSeqRef = React.useRef(0); + const ddlRequestedContextKeyRef = React.useRef(null); + const ddlContextKey = React.useMemo( + () => buildDdlContextKey(currentConnConfig, dbName, tableName), + [currentConnConfig, dbName, tableName], + ); - const isTableSurfaceActive = viewMode === 'table' || (isV2Ui && viewMode === 'ddl' && ddlViewLayout === 'side'); + const ddlViewLayout = ddlViewLayoutState; + const resolvedViewMode: GridViewMode = isActive + && canRestoreSharedDdlView + && (viewMode === 'table' || viewMode === 'ddl') + ? 'ddl' + : viewMode; + const isDdlContextPending = resolvedViewMode === 'ddl' + && isActive + && canRestoreSharedDdlView + && ddlRequestedContextKeyRef.current !== ddlContextKey; + const resolvedDdlLoading = ddlLoading || isDdlContextPending; + const resolvedDdlText = isDdlContextPending ? '' : ddlText; + const isTableSurfaceActive = resolvedViewMode === 'table' || (isV2Ui && resolvedViewMode === 'ddl' && ddlViewLayout === 'side'); const translateMessage = React.useCallback((key: string, params?: TranslateParams) => { return translate ? translate(key, params) : catalogTranslate('zh-CN', key, params); }, [translate]); + const setDdlViewLayout: React.Dispatch> = React.useCallback((nextLayout) => { + const currentLayout = readSharedDdlViewLayout(); + const resolvedLayout = sanitizeDdlViewLayout( + typeof nextLayout === 'function' ? nextLayout(currentLayout) : nextLayout, + ); + setSharedDdlViewLayout(resolvedLayout); + }, []); + + React.useEffect(() => { + const handleSharedDdlViewLayoutChange = (nextLayout: DdlViewLayoutMode) => { + setDdlViewLayoutState((currentLayout) => ( + currentLayout === nextLayout ? currentLayout : nextLayout + )); + }; + ddlViewLayoutListeners.add(handleSharedDdlViewLayoutChange); + handleSharedDdlViewLayoutChange(readSharedDdlViewLayout()); + return () => { + ddlViewLayoutListeners.delete(handleSharedDdlViewLayoutChange); + }; + }, []); + const handleOpenTableDdl = React.useCallback(async (options?: { asView?: boolean }) => { if (!canViewDdl || !currentConnConfig || !tableName) { messageApi.error(translateMessage('data_grid.message.ddl_missing_context')); @@ -91,7 +201,9 @@ export const useDataGridDdlView = ({ } const asView = options?.asView === true && isV2Ui; const requestSeq = ++ddlRequestSeqRef.current; + ddlRequestedContextKeyRef.current = ddlContextKey; if (asView) { + setSharedDdlViewOpen(true); setViewMode('ddl'); setDdlModalOpen(false); } else { @@ -115,27 +227,51 @@ export const useDataGridDdlView = ({ setDdlLoading(false); } } - }, [canViewDdl, currentConnConfig, dbName, dbType, isV2Ui, messageApi, tableName, translateMessage]); + }, [canViewDdl, currentConnConfig, dbName, dbType, ddlContextKey, isV2Ui, messageApi, tableName, translateMessage]); React.useEffect(() => { if (isV2Ui || (viewMode !== 'fields' && viewMode !== 'ddl' && viewMode !== 'er' && viewMode !== 'sqlLog')) return; setViewMode('table'); }, [isV2Ui, viewMode]); + const closeDdlView = React.useCallback(() => { + setSharedDdlViewOpen(false); + ddlRequestedContextKeyRef.current = null; + ddlRequestSeqRef.current += 1; + setViewMode('table'); + setDdlModalOpen(false); + setDdlLoading(false); + setDdlText(''); + setDdlSidebarResizePreviewX(null); + }, []); + + React.useEffect(() => { + if (!isActive || !isV2Ui || !shouldRestoreSharedDdlView()) return; + if (!canViewDdl || !currentConnConfig || !tableName) return; + if (ddlRequestedContextKeyRef.current === ddlContextKey) return; + void handleOpenTableDdl({ asView: true }); + }, [canViewDdl, currentConnConfig, ddlContextKey, handleOpenTableDdl, isActive, isV2Ui, tableName]); + const handleViewModeChange = React.useCallback((nextMode: GridViewMode) => { if ((nextMode === 'fields' || nextMode === 'ddl' || nextMode === 'er' || nextMode === 'sqlLog') && !isV2Ui) { + setSharedDdlViewOpen(false); setViewMode('table'); return; } if (nextMode === 'sqlLog') { + setSharedDdlViewOpen(false); setViewMode('sqlLog'); return; } if (nextMode === 'ddl') { + if (isV2Ui && resolvedViewMode === 'ddl') { + closeDdlView(); + return; + } void handleOpenTableDdl({ asView: true }); - setViewMode('ddl'); return; } + setSharedDdlViewOpen(false); if (nextMode === 'json' && cellEditMode) { closeCellEditModeRef.current(); } @@ -151,22 +287,69 @@ export const useDataGridDdlView = ({ } setViewMode(nextMode); - }, [cellEditMode, closeCellEditModeRef, handleOpenTableDdl, isV2Ui, mergedDisplayDataRef, rowKeyStr, selectedRowKeys, setTextRecordIndex]); + }, [cellEditMode, closeCellEditModeRef, closeDdlView, handleOpenTableDdl, isV2Ui, mergedDisplayDataRef, resolvedViewMode, rowKeyStr, selectedRowKeys, setTextRecordIndex]); const handleDdlSidebarResizeStart = React.useCallback((event: React.MouseEvent) => { event.preventDefault(); event.stopPropagation(); const startX = event.clientX; const startWidth = ddlSidebarWidth; + const resizerElement = event.currentTarget; + const workspaceElement = resizerElement.parentElement; + const previewElement = workspaceElement?.querySelector?.('[data-grid-ddl-resize-preview="true"]') as HTMLElement | null | undefined; + const workspaceWidth = workspaceElement?.getBoundingClientRect?.().width; + const resizerWidth = resizerElement.getBoundingClientRect?.().width || 8; + const resolvePreviewX = (width: number, fallbackX: number) => ( + typeof workspaceWidth === 'number' && workspaceWidth > 0 + ? Math.max(0, workspaceWidth - width - resizerWidth / 2) + : fallbackX + ); + const applyPreviewElementPosition = (x: number | null) => { + if (!previewElement) return; + if (x === null) { + previewElement.style.opacity = '0'; + previewElement.style.transform = 'translate3d(0, 0, 0)'; + return; + } + previewElement.style.opacity = '1'; + previewElement.style.transform = `translateX(${x}px)`; + }; + const schedulePreviewElementPosition = (x: number) => { + const state = ddlSidebarResizeRef.current; + if (!state?.previewElement) return false; + state.previewX = x; + if (state.previewFrame !== null && state.previewFrame !== undefined) return true; + const run = () => { + const current = ddlSidebarResizeRef.current; + if (!current?.previewElement) return; + current.previewFrame = null; + applyPreviewElementPosition(current.previewX); + }; + if (typeof requestAnimationFrame === 'function') { + state.previewFrame = requestAnimationFrame(run); + } else { + run(); + } + return true; + }; + const startPreviewX = resolvePreviewX(startWidth, startX); const moveHandler = (moveEvent: MouseEvent) => { const nextWidth = Math.max(320, Math.min(760, startWidth + (startX - moveEvent.clientX))); if (ddlSidebarResizeRef.current) { ddlSidebarResizeRef.current.previewWidth = nextWidth; } - setDdlSidebarResizePreviewX(moveEvent.clientX); + const nextPreviewX = resolvePreviewX(nextWidth, moveEvent.clientX); + if (!schedulePreviewElementPosition(nextPreviewX)) { + setDdlSidebarResizePreviewX(nextPreviewX); + } }; const upHandler = () => { - const nextWidth = ddlSidebarResizeRef.current?.previewWidth ?? startWidth; + const resizeState = ddlSidebarResizeRef.current; + const nextWidth = resizeState?.previewWidth ?? startWidth; + if (resizeState?.previewFrame !== null && resizeState?.previewFrame !== undefined && typeof cancelAnimationFrame === 'function') { + cancelAnimationFrame(resizeState.previewFrame); + } + applyPreviewElementPosition(null); setDdlSidebarWidth(nextWidth); setDdlSidebarResizePreviewX(null); document.removeEventListener('mousemove', moveHandler); @@ -174,27 +357,41 @@ export const useDataGridDdlView = ({ ddlSidebarResizeRef.current = null; }; - ddlSidebarResizeRef.current = { startX, startWidth, previewWidth: startWidth, moveHandler, upHandler }; + ddlSidebarResizeRef.current = { + startX, + startWidth, + previewWidth: startWidth, + previewX: startPreviewX, + previewElement, + previewFrame: null, + moveHandler, + upHandler, + }; + if (previewElement) { + applyPreviewElementPosition(startPreviewX); + } else { + setDdlSidebarResizePreviewX(startPreviewX); + } document.addEventListener('mousemove', moveHandler); document.addEventListener('mouseup', upHandler); }, [ddlSidebarWidth]); const resetDdlViewState = React.useCallback(() => { + ddlRequestedContextKeyRef.current = null; ddlRequestSeqRef.current += 1; setDdlModalOpen(false); setDdlLoading(false); setDdlText(''); - setDdlViewLayout('bottom'); setDdlSidebarResizePreviewX(null); }, []); return { - viewMode, + viewMode: resolvedViewMode, setViewMode, ddlModalOpen, setDdlModalOpen, - ddlLoading, - ddlText, + ddlLoading: resolvedDdlLoading, + ddlText: resolvedDdlText, ddlViewLayout, setDdlViewLayout, ddlSidebarWidth, @@ -205,5 +402,6 @@ export const useDataGridDdlView = ({ handleViewModeChange, handleDdlSidebarResizeStart, resetDdlViewState, + closeDdlView, }; }; diff --git a/frontend/src/v2-theme.css b/frontend/src/v2-theme.css index 28cd4ef..9633269 100644 --- a/frontend/src/v2-theme.css +++ b/frontend/src/v2-theme.css @@ -819,24 +819,35 @@ body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side { } body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-alt-toolbar { - min-height: 52px; - align-items: flex-start; - padding: 8px 10px; + min-height: 46px; + align-items: center; + gap: 8px; + padding: 7px 10px; } -body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-alt-toolbar > div:first-child { - flex: 1 1 auto; +body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-ddl-title { + flex: 1 1 72px; + overflow: hidden; } -body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-alt-toolbar > div:last-child { +body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-ddl-actions { justify-content: flex-end; - flex: 0 1 auto; - flex-wrap: wrap; - gap: 6px; + flex: 0 0 auto; + flex-wrap: nowrap; + gap: 4px; + white-space: nowrap; +} + +body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-ddl-actions .ant-btn-sm { + padding-inline: 7px; +} + +body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-ddl-actions .ant-segmented-small .ant-segmented-item-label { + padding-inline: 8px; } body[data-ui-version="v2"] .gn-v2-data-grid-ddl-view.is-side .gn-v2-data-grid-alt-toolbar strong { - max-width: 210px; + max-width: 150px; } body[data-ui-version="v2"] .gn-v2-data-grid-ddl-code {