mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-08 22:12:29 +08:00
🐛 fix(query-editor): 统一对象查看与修改字号
- object-edit 查询态补齐与查看页一致的 Monaco 字号和行高配置 - 统一对象查看与修改的行号宽度,避免视觉尺寸不一致 - 补充 QueryEditor 与 DefinitionViewer Monaco 选项回归测试
This commit is contained in:
@@ -50,6 +50,9 @@ vi.mock('./MonacoEditor', () => ({
|
||||
data-editor="true"
|
||||
data-readonly={String(options?.readOnly)}
|
||||
data-sticky-scroll-enabled={String(options?.stickyScroll?.enabled)}
|
||||
data-font-size={String(options?.fontSize)}
|
||||
data-line-height={String(options?.lineHeight)}
|
||||
data-line-numbers-min-chars={String(options?.lineNumbersMinChars)}
|
||||
>
|
||||
{value}
|
||||
</pre>
|
||||
@@ -128,6 +131,9 @@ describe('Object definition viewers Monaco options', () => {
|
||||
|
||||
const editor = renderer.root.findByProps({ 'data-editor': 'true' });
|
||||
expect(editor.props['data-sticky-scroll-enabled']).toBe('false');
|
||||
expect(editor.props['data-font-size']).toBe('14');
|
||||
expect(editor.props['data-line-height']).toBe('24');
|
||||
expect(editor.props['data-line-numbers-min-chars']).toBe('4');
|
||||
});
|
||||
|
||||
it('disables sticky scroll for read-only trigger definitions', async () => {
|
||||
|
||||
@@ -151,6 +151,7 @@ const editorState = vi.hoisted(() => {
|
||||
decorationIds: [] as string[],
|
||||
contentHoverCalls: [] as any[],
|
||||
latestOnChange: null as null | ((value?: string) => void),
|
||||
latestOptions: null as any,
|
||||
};
|
||||
const offsetAt = (position: { lineNumber: number; column: number }) => {
|
||||
const text = state.value;
|
||||
@@ -295,10 +296,11 @@ vi.mock('../utils/autoFetchVisibility', () => ({
|
||||
}));
|
||||
|
||||
vi.mock('@monaco-editor/react', () => ({
|
||||
default: ({ defaultValue, onChange, onMount }: any) => {
|
||||
default: ({ defaultValue, onChange, onMount, options }: any) => {
|
||||
React.useEffect(() => {
|
||||
editorState.value = String(defaultValue || '');
|
||||
editorState.latestOnChange = onChange;
|
||||
editorState.latestOptions = options ?? null;
|
||||
onMount?.(editorState.editor, {
|
||||
editor: { setTheme: vi.fn() },
|
||||
KeyMod: { CtrlCmd: 2048, WinCtrl: 256, Alt: 512, Shift: 1024 },
|
||||
@@ -706,6 +708,7 @@ describe('QueryEditor external SQL save', () => {
|
||||
editorState.decorationIds = [];
|
||||
editorState.contentHoverCalls = [];
|
||||
editorState.latestOnChange = null;
|
||||
editorState.latestOptions = null;
|
||||
editorState.editor.getValue.mockClear();
|
||||
editorState.editor.getModel().getValue.mockClear();
|
||||
editorState.editor.getModel().getValueLength.mockClear();
|
||||
@@ -840,6 +843,48 @@ describe('QueryEditor external SQL save', () => {
|
||||
renderer?.unmount();
|
||||
});
|
||||
|
||||
it('disables sticky scroll for object-edit query tabs', async () => {
|
||||
storeState.connections[0].config.type = 'oracle';
|
||||
storeState.connections[0].config.database = 'ORCLPDB1';
|
||||
const plsql = [
|
||||
'CREATE OR REPLACE PROCEDURE cproc_demo AS',
|
||||
'BEGIN',
|
||||
' NULL;',
|
||||
'END cproc_demo;',
|
||||
'/;',
|
||||
].join('\n');
|
||||
|
||||
let renderer!: ReactTestRenderer;
|
||||
await act(async () => {
|
||||
renderer = create(<QueryEditor tab={createTab({ dbName: 'ORCLPDB1', query: plsql, queryMode: 'object-edit' })} />);
|
||||
});
|
||||
|
||||
expect(editorState.latestOptions?.stickyScroll?.enabled).toBe(false);
|
||||
expect(editorState.latestOptions?.fontSize).toBe(14);
|
||||
expect(editorState.latestOptions?.lineHeight).toBe(24);
|
||||
expect(editorState.latestOptions?.lineNumbersMinChars).toBe(4);
|
||||
expect(editorState.editor.updateOptions).toHaveBeenCalledWith(expect.objectContaining({
|
||||
fontSize: 14,
|
||||
lineHeight: 24,
|
||||
lineNumbersMinChars: 4,
|
||||
stickyScroll: { enabled: false },
|
||||
}));
|
||||
renderer?.unmount();
|
||||
});
|
||||
|
||||
it('keeps standard query tabs on the default sticky scroll behavior', async () => {
|
||||
let renderer!: ReactTestRenderer;
|
||||
await act(async () => {
|
||||
renderer = create(<QueryEditor tab={createTab()} />);
|
||||
});
|
||||
|
||||
expect(editorState.latestOptions?.stickyScroll).toBeUndefined();
|
||||
expect(editorState.latestOptions?.fontSize).toBeUndefined();
|
||||
expect(editorState.latestOptions?.lineHeight).toBeUndefined();
|
||||
expect(editorState.editor.updateOptions.mock.calls[0]?.[0]?.stickyScroll).toBeUndefined();
|
||||
renderer?.unmount();
|
||||
});
|
||||
|
||||
it('runs the preceding Oracle procedure when the cursor is on the SQLPlus slash delimiter', async () => {
|
||||
storeState.connections[0].config.type = 'oracle';
|
||||
storeState.connections[0].config.database = 'ORCLPDB1';
|
||||
|
||||
@@ -154,6 +154,29 @@ const QUERY_EDITOR_MONACO_FIND_OPTIONS = {
|
||||
} as const;
|
||||
const QUERY_EDITOR_NATIVE_SELECT_CURRENT_LINE_EVENT = 'gonavi:native-select-current-line';
|
||||
|
||||
const buildQueryEditorMonacoOptions = (isObjectEditQueryTab: boolean) => ({
|
||||
minimap: { enabled: false },
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
find: QUERY_EDITOR_MONACO_FIND_OPTIONS,
|
||||
hover: {
|
||||
enabled: true,
|
||||
delay: QUERY_EDITOR_HOVER_DELAY_MS,
|
||||
above: false,
|
||||
},
|
||||
scrollBeyondLastLine: false,
|
||||
quickSuggestions: { other: true, comments: false, strings: false },
|
||||
suggestOnTriggerCharacters: true,
|
||||
...(isObjectEditQueryTab
|
||||
? {
|
||||
fontSize: 14,
|
||||
lineHeight: 24,
|
||||
lineNumbersMinChars: 4,
|
||||
stickyScroll: { enabled: false },
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
|
||||
const QUERY_EDITOR_SQL_PROMPT_PLACEHOLDER = '{SQL}';
|
||||
|
||||
const escapeQueryEditorObjectEditSqlLiteral = (value: unknown): string => (
|
||||
@@ -815,6 +838,10 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc
|
||||
));
|
||||
const isExternalSQLFileTab = Boolean(String(tab.filePath || '').trim());
|
||||
const isObjectEditQueryTab = tab.type === 'query' && tab.queryMode === 'object-edit';
|
||||
const queryEditorMonacoOptions = useMemo(
|
||||
() => buildQueryEditorMonacoOptions(isObjectEditQueryTab),
|
||||
[isObjectEditQueryTab],
|
||||
);
|
||||
|
||||
type ResultSet = QueryEditorResultSet;
|
||||
|
||||
@@ -2616,15 +2643,7 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc
|
||||
}
|
||||
lastEditorCursorPositionRef.current = normalizeEditorPosition(editor.getPosition?.());
|
||||
|
||||
editor.updateOptions?.({
|
||||
fixedOverflowWidgets: true,
|
||||
find: QUERY_EDITOR_MONACO_FIND_OPTIONS,
|
||||
hover: {
|
||||
enabled: true,
|
||||
delay: QUERY_EDITOR_HOVER_DELAY_MS,
|
||||
above: false,
|
||||
},
|
||||
});
|
||||
editor.updateOptions?.(buildQueryEditorMonacoOptions(isObjectEditQueryTab));
|
||||
|
||||
const applyNavigationHoverStateAtPosition = (targetPosition: { lineNumber: number; column: number } | null) => {
|
||||
if (!ctrlMetaPressedRef.current) {
|
||||
@@ -6258,20 +6277,7 @@ const QueryEditor: React.FC<{ tab: TabData; isActive?: boolean }> = ({ tab, isAc
|
||||
syncQueryDraft(nextValue);
|
||||
}}
|
||||
onMount={handleEditorDidMount}
|
||||
options={{
|
||||
minimap: { enabled: false },
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
find: QUERY_EDITOR_MONACO_FIND_OPTIONS,
|
||||
hover: {
|
||||
enabled: true,
|
||||
delay: QUERY_EDITOR_HOVER_DELAY_MS,
|
||||
above: false,
|
||||
},
|
||||
scrollBeyondLastLine: false,
|
||||
quickSuggestions: { other: true, comments: false, strings: false },
|
||||
suggestOnTriggerCharacters: true,
|
||||
}}
|
||||
options={queryEditorMonacoOptions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user