mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-28 17:31:32 +08:00
🐛 fix(query-editor): 优化事务下拉显示与浮层交互
- 自动提交延迟选项改为多语言完整文案,避免短标签语义不清 - 收窄并校准 V2 工具栏事务下拉宽度,兼顾不截断与紧凑布局 - 事务模式 Select 展开时自动隐藏 DBeaver 参考 Tooltip,避免浮层互相遮挡 - 补充事务设置行为测试和布局守护测试
This commit is contained in:
@@ -7227,8 +7227,9 @@ describe('QueryEditor external SQL save', () => {
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.mode.auto');
|
||||
expect(transactionSettingsSource).not.toContain("label: '手动提交'");
|
||||
expect(transactionSettingsSource).not.toContain("label: '自动提交'");
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate');
|
||||
expect(transactionSettingsSource).toContain("label: '3s'");
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate_commit');
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.delay.seconds_commit');
|
||||
expect(transactionSettingsSource).not.toContain("label: '3s'");
|
||||
expect(source).toContain('QueryEditorTransactionToolbar');
|
||||
expect(transactionToolbarSource).toContain("className={isV2Ui ? 'gn-v2-query-transaction-toolbar' : undefined}");
|
||||
expect(transactionToolbarSource).toContain(": null;");
|
||||
@@ -7255,8 +7256,8 @@ describe('QueryEditor external SQL save', () => {
|
||||
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-selects');
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-actions');
|
||||
expect(css).toContain('width: 74px !important;');
|
||||
expect(css).toContain('width: 62px !important;');
|
||||
expect(css).toContain('width: 78px !important;');
|
||||
expect(css).toContain('width: 104px !important;');
|
||||
expect(css).toContain('flex: 0 0 auto !important;');
|
||||
expect(css).toContain('justify-content: flex-start;');
|
||||
expect(css).toContain('height: 32px !important;');
|
||||
|
||||
@@ -2553,8 +2553,9 @@ describe('QueryEditor external SQL save', () => {
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.mode.auto');
|
||||
expect(transactionSettingsSource).not.toContain("label: '手动提交'");
|
||||
expect(transactionSettingsSource).not.toContain("label: '自动提交'");
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate');
|
||||
expect(transactionSettingsSource).toContain("label: '3s'");
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate_commit');
|
||||
expect(transactionSettingsSource).toContain('query_editor.transaction.delay.seconds_commit');
|
||||
expect(transactionSettingsSource).not.toContain("label: '3s'");
|
||||
expect(source).toContain('QueryEditorTransactionToolbar');
|
||||
expect(transactionToolbarSource).toContain("className={isV2Ui ? 'gn-v2-query-transaction-toolbar' : undefined}");
|
||||
expect(transactionToolbarSource).toContain(": null;");
|
||||
@@ -2581,8 +2582,8 @@ describe('QueryEditor external SQL save', () => {
|
||||
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-selects');
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-actions');
|
||||
expect(css).toContain('width: 74px !important;');
|
||||
expect(css).toContain('width: 62px !important;');
|
||||
expect(css).toContain('width: 78px !important;');
|
||||
expect(css).toContain('width: 104px !important;');
|
||||
expect(css).toContain('flex: 0 0 auto !important;');
|
||||
expect(css).toContain('justify-content: flex-start;');
|
||||
expect(css).toContain('height: 32px !important;');
|
||||
|
||||
@@ -62,4 +62,21 @@ describe('QueryEditorToolbar layout', () => {
|
||||
expect(commitHoverCss).toContain('box-shadow:');
|
||||
expect(commitKbdHoverCss).toContain('background:');
|
||||
});
|
||||
|
||||
it('keeps transaction selects wide enough for localized auto-commit labels', () => {
|
||||
const css = readV2ThemeCss();
|
||||
const transactionModeCss = css.slice(
|
||||
css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-mode-select {'),
|
||||
css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-delay-select {'),
|
||||
);
|
||||
const transactionDelayCss = css.slice(
|
||||
css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-delay-select {'),
|
||||
css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar .ant-select-selector {'),
|
||||
);
|
||||
|
||||
expect(transactionModeCss).toContain('width: 78px !important;');
|
||||
expect(transactionModeCss).toContain('flex: 0 0 78px !important;');
|
||||
expect(transactionDelayCss).toContain('width: 104px !important;');
|
||||
expect(transactionDelayCss).toContain('flex: 0 0 104px !important;');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,6 +20,8 @@ const toolbarLegacyLiterals = [
|
||||
|
||||
const requiredKeys = [
|
||||
'query_editor.transaction.delay.immediate',
|
||||
'query_editor.transaction.delay.immediate_commit',
|
||||
'query_editor.transaction.delay.seconds_commit',
|
||||
'query_editor.transaction.mode.tooltip',
|
||||
'query_editor.transaction.mode.manual',
|
||||
'query_editor.transaction.mode.auto',
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import React from 'react';
|
||||
import { act, create, type ReactTestRenderer } from 'react-test-renderer';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import QueryEditorTransactionSettings from './QueryEditorTransactionSettings';
|
||||
|
||||
const antdState = vi.hoisted(() => ({
|
||||
selectProps: [] as any[],
|
||||
tooltipProps: [] as any[],
|
||||
}));
|
||||
|
||||
vi.mock('antd', () => ({
|
||||
Select: (props: any) => {
|
||||
antdState.selectProps.push(props);
|
||||
return <button type="button">{props.value}</button>;
|
||||
},
|
||||
Tooltip: (props: any) => {
|
||||
antdState.tooltipProps.push(props);
|
||||
return <div>{props.children}</div>;
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../i18n/provider', () => ({
|
||||
useOptionalI18n: () => ({
|
||||
t: (key: string, params?: Record<string, unknown>) => params?.seconds ? `${params.seconds}s后提交` : key,
|
||||
}),
|
||||
}));
|
||||
|
||||
const latestSelectProps = () => antdState.selectProps[antdState.selectProps.length - 1];
|
||||
const latestTooltipProps = () => antdState.tooltipProps[antdState.tooltipProps.length - 1];
|
||||
|
||||
describe('QueryEditorTransactionSettings', () => {
|
||||
let renderer: ReactTestRenderer | null = null;
|
||||
|
||||
beforeEach(() => {
|
||||
antdState.selectProps = [];
|
||||
antdState.tooltipProps = [];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
renderer?.unmount();
|
||||
renderer = null;
|
||||
});
|
||||
|
||||
it('hides the DBeaver reference tooltip while the transaction mode select is open', () => {
|
||||
act(() => {
|
||||
renderer = create(
|
||||
<QueryEditorTransactionSettings
|
||||
isV2Ui
|
||||
commitMode="manual"
|
||||
autoCommitDelayMs={0}
|
||||
onCommitModeChange={vi.fn()}
|
||||
onAutoCommitDelayMsChange={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
act(() => {
|
||||
latestTooltipProps().onOpenChange(true);
|
||||
});
|
||||
expect(latestTooltipProps().open).toBe(true);
|
||||
|
||||
act(() => {
|
||||
latestSelectProps().onOpenChange(true);
|
||||
});
|
||||
expect(latestTooltipProps().open).toBe(false);
|
||||
|
||||
act(() => {
|
||||
latestSelectProps().onOpenChange(false);
|
||||
latestTooltipProps().onOpenChange(true);
|
||||
});
|
||||
expect(latestTooltipProps().open).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -8,18 +8,14 @@ export type SqlEditorCommitMode = 'manual' | 'auto';
|
||||
|
||||
type SqlEditorAutoCommitDelayOption = {
|
||||
value: number;
|
||||
label: string;
|
||||
} | {
|
||||
value: number;
|
||||
labelKey: string;
|
||||
};
|
||||
|
||||
export const SQL_EDITOR_AUTO_COMMIT_DELAY_OPTIONS: SqlEditorAutoCommitDelayOption[] = [
|
||||
{ value: 0, labelKey: 'query_editor.transaction.delay.immediate' },
|
||||
{ value: 3000, label: '3s' },
|
||||
{ value: 5000, label: '5s' },
|
||||
{ value: 10000, label: '10s' },
|
||||
{ value: 30000, label: '30s' },
|
||||
{ value: 0 },
|
||||
{ value: 3000 },
|
||||
{ value: 5000 },
|
||||
{ value: 10000 },
|
||||
{ value: 30000 },
|
||||
];
|
||||
|
||||
type QueryEditorTransactionSettingsProps = {
|
||||
@@ -39,18 +35,36 @@ const QueryEditorTransactionSettings: React.FC<QueryEditorTransactionSettingsPro
|
||||
}) => {
|
||||
const i18n = useOptionalI18n();
|
||||
const t = i18n?.t ?? defaultTranslate;
|
||||
const [isModeSelectOpen, setIsModeSelectOpen] = React.useState(false);
|
||||
const [isModeTooltipOpen, setIsModeTooltipOpen] = React.useState(false);
|
||||
const autoCommitDelayOptions = SQL_EDITOR_AUTO_COMMIT_DELAY_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: 'labelKey' in option ? t(option.labelKey) : option.label,
|
||||
label: option.value === 0
|
||||
? t('query_editor.transaction.delay.immediate_commit')
|
||||
: t('query_editor.transaction.delay.seconds_commit', { seconds: Math.round(option.value / 1000) }),
|
||||
}));
|
||||
const handleModeSelectOpenChange = (open: boolean) => {
|
||||
setIsModeSelectOpen(open);
|
||||
if (open) {
|
||||
setIsModeTooltipOpen(false);
|
||||
}
|
||||
};
|
||||
const handleModeTooltipOpenChange = (open: boolean) => {
|
||||
setIsModeTooltipOpen(open);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={t('query_editor.transaction.mode.tooltip')}>
|
||||
<Tooltip
|
||||
title={t('query_editor.transaction.mode.tooltip')}
|
||||
open={isModeTooltipOpen && !isModeSelectOpen}
|
||||
onOpenChange={handleModeTooltipOpenChange}
|
||||
>
|
||||
<Select
|
||||
className={isV2Ui ? 'gn-v2-query-toolbar-select gn-v2-query-toolbar-transaction-mode-select' : undefined}
|
||||
style={isV2Ui ? undefined : { width: 78 }}
|
||||
value={commitMode}
|
||||
onOpenChange={handleModeSelectOpenChange}
|
||||
onChange={(mode) => onCommitModeChange(mode === 'auto' ? 'auto' : 'manual')}
|
||||
options={[
|
||||
{ label: t('query_editor.transaction.mode.manual'), value: 'manual' },
|
||||
|
||||
@@ -154,13 +154,13 @@ body[data-ui-version="v2"] .gn-v2-query-toolbar-max-rows-select {
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-mode-select {
|
||||
width: 74px !important;
|
||||
flex: 0 0 74px !important;
|
||||
width: 78px !important;
|
||||
flex: 0 0 78px !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-delay-select {
|
||||
width: 62px !important;
|
||||
flex: 0 0 62px !important;
|
||||
width: 104px !important;
|
||||
flex: 0 0 104px !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar .ant-select-selector {
|
||||
|
||||
@@ -6249,6 +6249,8 @@
|
||||
"query_editor.transaction.action.commit_with_count": "Commit ({{count}})",
|
||||
"query_editor.transaction.action.rollback": "Rollback",
|
||||
"query_editor.transaction.delay.immediate": "Sofort",
|
||||
"query_editor.transaction.delay.immediate_commit": "Sofort committen",
|
||||
"query_editor.transaction.delay.seconds_commit": "Commit in {{seconds}}s",
|
||||
"query_editor.transaction.message.pending_managed_transaction": "Im SQL-Editor ist bereits eine nicht festgeschriebene Transaktion offen. Führen Sie zuerst Commit oder Rollback aus, bevor Sie eine weitere DML-Anweisung starten.",
|
||||
"query_editor.transaction.mode.auto": "Automatisch",
|
||||
"query_editor.transaction.mode.manual": "Manuell",
|
||||
|
||||
@@ -6249,6 +6249,8 @@
|
||||
"query_editor.transaction.action.commit_with_count": "Commit ({{count}})",
|
||||
"query_editor.transaction.action.rollback": "Rollback",
|
||||
"query_editor.transaction.delay.immediate": "Immediately",
|
||||
"query_editor.transaction.delay.immediate_commit": "Commit now",
|
||||
"query_editor.transaction.delay.seconds_commit": "Commit in {{seconds}}s",
|
||||
"query_editor.transaction.message.pending_managed_transaction": "The SQL editor already has a pending transaction. Commit or roll it back before running another DML statement.",
|
||||
"query_editor.transaction.mode.auto": "Auto",
|
||||
"query_editor.transaction.mode.manual": "Manual",
|
||||
|
||||
@@ -6249,6 +6249,8 @@
|
||||
"query_editor.transaction.action.commit_with_count": "コミット ({{count}})",
|
||||
"query_editor.transaction.action.rollback": "ロールバック",
|
||||
"query_editor.transaction.delay.immediate": "即時",
|
||||
"query_editor.transaction.delay.immediate_commit": "即時コミット",
|
||||
"query_editor.transaction.delay.seconds_commit": "{{seconds}}s 後にコミット",
|
||||
"query_editor.transaction.message.pending_managed_transaction": "SQL エディターには未コミットのトランザクションがあります。新しい DML 文を実行する前にコミットまたはロールバックしてください。",
|
||||
"query_editor.transaction.mode.auto": "自動",
|
||||
"query_editor.transaction.mode.manual": "手動",
|
||||
|
||||
@@ -6249,6 +6249,8 @@
|
||||
"query_editor.transaction.action.commit_with_count": "Commit ({{count}})",
|
||||
"query_editor.transaction.action.rollback": "Rollback",
|
||||
"query_editor.transaction.delay.immediate": "Сразу",
|
||||
"query_editor.transaction.delay.immediate_commit": "Commit сразу",
|
||||
"query_editor.transaction.delay.seconds_commit": "Commit через {{seconds}}s",
|
||||
"query_editor.transaction.message.pending_managed_transaction": "В SQL-редакторе уже есть незавершённая транзакция. Перед выполнением нового DML-оператора выполните commit или rollback.",
|
||||
"query_editor.transaction.mode.auto": "Авто",
|
||||
"query_editor.transaction.mode.manual": "Вручную",
|
||||
|
||||
@@ -6249,6 +6249,8 @@
|
||||
"query_editor.transaction.action.commit_with_count": "提交 ({{count}})",
|
||||
"query_editor.transaction.action.rollback": "回滚",
|
||||
"query_editor.transaction.delay.immediate": "立即",
|
||||
"query_editor.transaction.delay.immediate_commit": "立即提交",
|
||||
"query_editor.transaction.delay.seconds_commit": "{{seconds}}s后提交",
|
||||
"query_editor.transaction.message.pending_managed_transaction": "当前 SQL 编辑器已有未提交事务,请先提交或回滚后再执行新的增删改语句。",
|
||||
"query_editor.transaction.mode.auto": "自动",
|
||||
"query_editor.transaction.mode.manual": "手动",
|
||||
|
||||
@@ -6249,6 +6249,8 @@
|
||||
"query_editor.transaction.action.commit_with_count": "提交 ({{count}})",
|
||||
"query_editor.transaction.action.rollback": "回滾",
|
||||
"query_editor.transaction.delay.immediate": "立即",
|
||||
"query_editor.transaction.delay.immediate_commit": "立即提交",
|
||||
"query_editor.transaction.delay.seconds_commit": "{{seconds}}s後提交",
|
||||
"query_editor.transaction.message.pending_managed_transaction": "目前 SQL 編輯器已有未提交交易,請先提交或回滾後再執行新的新增、更新或刪除語句。",
|
||||
"query_editor.transaction.mode.auto": "自動",
|
||||
"query_editor.transaction.mode.manual": "手動",
|
||||
|
||||
Reference in New Issue
Block a user