mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-08-10 08:43:34 +08:00
✨ feat(settings): 支持自定义并持久化日志目录
- 将日志目录配置整合到数据目录设置,支持选择、打开、恢复默认与保存 - 持久化日志目录并保留环境变量优先级,目录调整后重启生效 - 通过跨进程锁和原子写入保护数据目录与日志目录配置 - 移除重复标题并互斥目录修改操作,补齐六语言文案 - 补充桌面接口、浏览器模拟及并发回归测试
This commit is contained in:
@@ -90,6 +90,53 @@ describe('settings center layout', () => {
|
||||
expect(appSource).toContain("t('app.proxy.test.target_placeholder')");
|
||||
});
|
||||
|
||||
it('keeps log directory controls inside the data-root detail page', () => {
|
||||
const embeddedDataRootStart = appSource.indexOf("if (activeSettingsCenterPane.key === 'data-root')");
|
||||
const embeddedDataRootEnd = appSource.indexOf(
|
||||
"if (activeSettingsCenterPane.key === 'security-update')",
|
||||
embeddedDataRootStart,
|
||||
);
|
||||
const embeddedDataRootSource = appSource.slice(embeddedDataRootStart, embeddedDataRootEnd);
|
||||
const standaloneDataRootStart = appSource.indexOf('{isDataRootModalOpen && (');
|
||||
const standaloneDataRootEnd = appSource.indexOf(
|
||||
'<ConnectionPackagePasswordModal',
|
||||
standaloneDataRootStart,
|
||||
);
|
||||
const standaloneDataRootSource = appSource.slice(standaloneDataRootStart, standaloneDataRootEnd);
|
||||
const logDirectoryRendererStart = appSource.indexOf('const renderLogDirectorySettings = () => {');
|
||||
const logDirectoryRendererEnd = appSource.indexOf('\n const {', logDirectoryRendererStart);
|
||||
const logDirectoryRendererSource = appSource.slice(logDirectoryRendererStart, logDirectoryRendererEnd);
|
||||
|
||||
expect(embeddedDataRootStart).toBeGreaterThan(-1);
|
||||
expect(embeddedDataRootEnd).toBeGreaterThan(embeddedDataRootStart);
|
||||
expect(standaloneDataRootStart).toBeGreaterThan(-1);
|
||||
expect(standaloneDataRootEnd).toBeGreaterThan(standaloneDataRootStart);
|
||||
expect(appSource).toContain('ApplyLogDirectory');
|
||||
expect(appSource).toContain('OpenLogDirectory');
|
||||
expect(appSource).toContain('SelectLogDirectory');
|
||||
expect(appSource).toContain("const [selectedLogDirectoryPath, setSelectedLogDirectoryPath] = useState('');");
|
||||
expect(appSource).toContain('const directorySettingsApplying = dataRootApplying || logDirectoryApplying;');
|
||||
expect(appSource).toContain('const handleSelectLogDirectory = useCallback(async () => {');
|
||||
expect(appSource).toContain('const handleApplyLogDirectory = useCallback(async (useDefaultPath = false) => {');
|
||||
expect(appSource).toContain('const handleOpenLogDirectory = useCallback(async () => {');
|
||||
expect(appSource).toContain('const renderLogDirectorySettings = () => {');
|
||||
expect(appSource).toContain('data-log-directory-settings="true"');
|
||||
expect(appSource).toContain("dataRootInfo?.logDirectorySource === 'environment'");
|
||||
expect(appSource).toContain('dataRootInfo?.logDirectoryRestartRequired === true');
|
||||
expect(appSource).toContain("t('app.data_root.log_directory.environment_hint')");
|
||||
expect(appSource).toContain("t('app.data_root.log_directory.pending_restart')");
|
||||
expect(appSource).toContain("t('app.data_root.log_directory.restart_hint')");
|
||||
expect(logDirectoryRendererSource).not.toContain("t('app.data_root.log_directory.target_directory')");
|
||||
expect(logDirectoryRendererSource.match(/disabled={!editable \|\| directorySettingsApplying}/g)).toHaveLength(3);
|
||||
expect(embeddedDataRootSource.match(/disabled={directorySettingsApplying}/g)).toHaveLength(4);
|
||||
expect(standaloneDataRootSource.match(/disabled={directorySettingsApplying}/g)).toHaveLength(4);
|
||||
expect(embeddedDataRootSource).toContain('{renderLogDirectorySettings()}');
|
||||
expect(standaloneDataRootSource).toContain('{renderLogDirectorySettings()}');
|
||||
expect(appSource).not.toContain("| 'log-directory'");
|
||||
expect(appSource).not.toContain("key: 'log-directory'");
|
||||
expect(appSource).not.toContain("handleOpenToolCenterPane('config', 'log-directory')");
|
||||
});
|
||||
|
||||
it('adds close and back-to-settings actions to settings center detail panes', () => {
|
||||
expect(appSource).toContain('const handleBackFromSettingsCenterPane = useCallback(() => {');
|
||||
expect(appSource).toContain('const handleCancelSettingsCenterPane = useCallback(() => {');
|
||||
|
||||
@@ -219,7 +219,7 @@ import { useAppLogPanelResize } from './hooks/useAppLogPanelResize';
|
||||
import { useAppSidebarResize } from './hooks/useAppSidebarResize';
|
||||
import { useAppUtilityStyles } from './hooks/useAppUtilityStyles';
|
||||
import { useWorkbenchTabs } from './hooks/useWorkbenchTabs';
|
||||
import { ApplyDataRootDirectory, CancelApplicationQuit, ForceQuitApplication, GetDataRootDirectoryInfo, GetSavedConnections, ListInstalledFontFamilies, OpenDataRootDirectory, SelectDataRootDirectory, SetApplicationBrandIcon, SetMacNativeWindowControls, SetWindowTranslucency } from '../wailsjs/go/app/App';
|
||||
import { ApplyDataRootDirectory, ApplyLogDirectory, CancelApplicationQuit, ForceQuitApplication, GetDataRootDirectoryInfo, GetSavedConnections, ListInstalledFontFamilies, OpenDataRootDirectory, OpenLogDirectory, SelectDataRootDirectory, SelectLogDirectory, SetApplicationBrandIcon, SetMacNativeWindowControls, SetWindowTranslucency } from '../wailsjs/go/app/App';
|
||||
import { getAntdLocale } from './i18n/frameworkLocale';
|
||||
import { useI18n } from './i18n/provider';
|
||||
import './App.css';
|
||||
@@ -3069,8 +3069,11 @@ function App() {
|
||||
const [isDataRootModalOpen, setIsDataRootModalOpen] = useState(false);
|
||||
const [dataRootInfo, setDataRootInfo] = useState<any>(null);
|
||||
const [selectedDataRootPath, setSelectedDataRootPath] = useState('');
|
||||
const [selectedLogDirectoryPath, setSelectedLogDirectoryPath] = useState('');
|
||||
const [dataRootLoading, setDataRootLoading] = useState(false);
|
||||
const [dataRootApplying, setDataRootApplying] = useState(false);
|
||||
const [logDirectoryApplying, setLogDirectoryApplying] = useState(false);
|
||||
const directorySettingsApplying = dataRootApplying || logDirectoryApplying;
|
||||
|
||||
const aiEntryPlacement = resolveAIEntryPlacement();
|
||||
const legacyAiEdgeHandleAttachment = resolveLegacyAIEdgeHandleAttachment(aiPanelVisible);
|
||||
@@ -3471,6 +3474,7 @@ function App() {
|
||||
const data = (res?.data || {}) as any;
|
||||
setDataRootInfo(data);
|
||||
setSelectedDataRootPath(String(data.path || ''));
|
||||
setSelectedLogDirectoryPath(String(data.logDirectory || data.defaultLogDirectory || ''));
|
||||
} catch (error) {
|
||||
const errMsg = error instanceof Error ? error.message : String(error || t('common.unknown'));
|
||||
void message.error(t('app.data_root.message.load_failed_with_error', { error: errMsg }));
|
||||
@@ -3539,6 +3543,138 @@ function App() {
|
||||
}
|
||||
}, [t]);
|
||||
|
||||
const handleSelectLogDirectory = useCallback(async () => {
|
||||
try {
|
||||
const res = await SelectLogDirectory(
|
||||
selectedLogDirectoryPath || dataRootInfo?.logDirectory || dataRootInfo?.defaultLogDirectory || '',
|
||||
);
|
||||
if (!res?.success) {
|
||||
if (String(res?.message || '') !== '已取消') {
|
||||
throw new Error(res?.message || t('common.unknown'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const data = (res?.data || {}) as any;
|
||||
setSelectedLogDirectoryPath(String(data.directory || ''));
|
||||
} catch (error) {
|
||||
const errMsg = error instanceof Error ? error.message : String(error || t('common.unknown'));
|
||||
void message.error(t('app.data_root.log_directory.message.select_failed_with_error', { error: errMsg }));
|
||||
}
|
||||
}, [dataRootInfo?.defaultLogDirectory, dataRootInfo?.logDirectory, selectedLogDirectoryPath, t]);
|
||||
|
||||
const handleApplyLogDirectory = useCallback(async (useDefaultPath = false) => {
|
||||
const nextPath = useDefaultPath
|
||||
? String(dataRootInfo?.defaultLogDirectory || '')
|
||||
: String(selectedLogDirectoryPath || '').trim();
|
||||
if (!nextPath) {
|
||||
void message.warning(t('app.data_root.log_directory.message.select_valid_first'));
|
||||
return;
|
||||
}
|
||||
setLogDirectoryApplying(true);
|
||||
try {
|
||||
const res = await ApplyLogDirectory(nextPath);
|
||||
if (!res?.success) {
|
||||
throw new Error(res?.message || t('common.unknown'));
|
||||
}
|
||||
const data = (res?.data || {}) as any;
|
||||
setDataRootInfo(data);
|
||||
setSelectedLogDirectoryPath(String(data.logDirectory || data.defaultLogDirectory || nextPath));
|
||||
void message.success(res?.message || t('app.data_root.log_directory.message.updated'));
|
||||
} catch (error) {
|
||||
const errMsg = error instanceof Error ? error.message : String(error || t('common.unknown'));
|
||||
void message.error(t('app.data_root.log_directory.message.apply_failed_with_error', { error: errMsg }));
|
||||
} finally {
|
||||
setLogDirectoryApplying(false);
|
||||
}
|
||||
}, [dataRootInfo?.defaultLogDirectory, selectedLogDirectoryPath, t]);
|
||||
|
||||
const handleOpenLogDirectory = useCallback(async () => {
|
||||
try {
|
||||
const res = await OpenLogDirectory();
|
||||
if (!res?.success) {
|
||||
throw new Error(res?.message || t('common.unknown'));
|
||||
}
|
||||
} catch (error) {
|
||||
const errMsg = error instanceof Error ? error.message : String(error || t('common.unknown'));
|
||||
void message.error(t('app.data_root.log_directory.message.open_failed_with_error', { error: errMsg }));
|
||||
}
|
||||
}, [t]);
|
||||
|
||||
const renderLogDirectorySettings = () => {
|
||||
const editable = dataRootInfo?.logDirectoryEditable !== false;
|
||||
const managedByEnvironment = dataRootInfo?.logDirectorySource === 'environment';
|
||||
const restartRequired = dataRootInfo?.logDirectoryRestartRequired === true;
|
||||
return (
|
||||
<div style={utilityPanelStyle} data-log-directory-settings="true">
|
||||
<div style={{ fontWeight: 600 }}>{t('app.data_root.log_directory.title')}</div>
|
||||
<div style={{ ...utilityMutedTextStyle, marginTop: 4 }}>
|
||||
{t('app.data_root.log_directory.description')}
|
||||
</div>
|
||||
<div style={{ display: 'grid', gap: 10, marginTop: 14 }}>
|
||||
<Input
|
||||
readOnly
|
||||
disabled={!editable}
|
||||
value={selectedLogDirectoryPath}
|
||||
placeholder={t('app.data_root.log_directory.placeholder')}
|
||||
aria-label={t('app.data_root.log_directory.title')}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
|
||||
<Button
|
||||
icon={<FolderOpenOutlined />}
|
||||
disabled={!editable || directorySettingsApplying}
|
||||
onClick={() => void handleSelectLogDirectory()}
|
||||
>
|
||||
{t('app.data_root.action.select')}
|
||||
</Button>
|
||||
<Button onClick={() => void handleOpenLogDirectory()}>
|
||||
{t('app.data_root.action.open_current')}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!editable || directorySettingsApplying}
|
||||
loading={logDirectoryApplying}
|
||||
onClick={() => void handleApplyLogDirectory(true)}
|
||||
>
|
||||
{t('app.data_root.action.restore_default_directory')}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={!editable || directorySettingsApplying}
|
||||
loading={logDirectoryApplying}
|
||||
onClick={() => void handleApplyLogDirectory(false)}
|
||||
>
|
||||
{t('common.save')}
|
||||
</Button>
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 12 }}>
|
||||
<div>
|
||||
<div style={{ marginBottom: 6, fontWeight: 500 }}>
|
||||
{t('app.data_root.log_directory.current_file')}
|
||||
</div>
|
||||
<div style={{ ...utilityMutedTextStyle, overflowWrap: 'anywhere' }}>
|
||||
{dataRootInfo?.logFilePath || '-'}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ marginBottom: 6, fontWeight: 500 }}>
|
||||
{t('app.data_root.log_directory.default_directory')}
|
||||
</div>
|
||||
<div style={{ ...utilityMutedTextStyle, overflowWrap: 'anywhere' }}>
|
||||
{dataRootInfo?.defaultLogDirectory || '-'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{managedByEnvironment ? (
|
||||
<Alert type="warning" showIcon message={t('app.data_root.log_directory.environment_hint')} />
|
||||
) : restartRequired ? (
|
||||
<Alert type="info" showIcon message={t('app.data_root.log_directory.pending_restart')} />
|
||||
) : (
|
||||
<div style={utilityMutedTextStyle}>{t('app.data_root.log_directory.restart_hint')}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const {
|
||||
handleCloseLogPanel: handleCloseAppLogPanel,
|
||||
@@ -7877,13 +8013,21 @@ function App() {
|
||||
placeholder={t('app.data_root.placeholder.select_new_directory')}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
|
||||
<Button icon={<FolderOpenOutlined />} onClick={() => void handleSelectDataRoot()}>
|
||||
<Button
|
||||
icon={<FolderOpenOutlined />}
|
||||
disabled={directorySettingsApplying}
|
||||
onClick={() => void handleSelectDataRoot()}
|
||||
>
|
||||
{t('app.data_root.action.select')}
|
||||
</Button>
|
||||
<Button onClick={() => void handleOpenDataRoot()}>
|
||||
{t('app.data_root.action.open_current')}
|
||||
</Button>
|
||||
<Button loading={dataRootApplying} onClick={() => void handleApplyDataRoot(false, true)}>
|
||||
<Button
|
||||
disabled={directorySettingsApplying}
|
||||
loading={dataRootApplying}
|
||||
onClick={() => void handleApplyDataRoot(false, true)}
|
||||
>
|
||||
{t('app.data_root.action.restore_default_directory')}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -7892,10 +8036,19 @@ function App() {
|
||||
<div style={utilityPanelStyle}>
|
||||
<div style={{ marginBottom: 10, fontWeight: 600 }}>{t('app.data_root.apply_method')}</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
|
||||
<Button loading={dataRootApplying} onClick={() => void handleApplyDataRoot(false)}>
|
||||
<Button
|
||||
disabled={directorySettingsApplying}
|
||||
loading={dataRootApplying}
|
||||
onClick={() => void handleApplyDataRoot(false)}
|
||||
>
|
||||
{t('app.data_root.action.switch_only')}
|
||||
</Button>
|
||||
<Button type="primary" loading={dataRootApplying} onClick={() => void handleApplyDataRoot(true)}>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={directorySettingsApplying}
|
||||
loading={dataRootApplying}
|
||||
onClick={() => void handleApplyDataRoot(true)}
|
||||
>
|
||||
{t('app.data_root.action.migrate_and_switch')}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -7903,6 +8056,7 @@ function App() {
|
||||
{t('app.data_root.restart_hint')}
|
||||
</div>
|
||||
</div>
|
||||
{renderLogDirectorySettings()}
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
@@ -8352,13 +8506,21 @@ function App() {
|
||||
placeholder={t('app.data_root.placeholder.select_new_directory')}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
|
||||
<Button icon={<FolderOpenOutlined />} onClick={() => void handleSelectDataRoot()}>
|
||||
<Button
|
||||
icon={<FolderOpenOutlined />}
|
||||
disabled={directorySettingsApplying}
|
||||
onClick={() => void handleSelectDataRoot()}
|
||||
>
|
||||
{t('app.data_root.action.select')}
|
||||
</Button>
|
||||
<Button onClick={() => void handleOpenDataRoot()}>
|
||||
{t('app.data_root.action.open_current')}
|
||||
</Button>
|
||||
<Button loading={dataRootApplying} onClick={() => void handleApplyDataRoot(false, true)}>
|
||||
<Button
|
||||
disabled={directorySettingsApplying}
|
||||
loading={dataRootApplying}
|
||||
onClick={() => void handleApplyDataRoot(false, true)}
|
||||
>
|
||||
{t('app.data_root.action.restore_default_directory')}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -8367,10 +8529,19 @@ function App() {
|
||||
<div style={utilityPanelStyle}>
|
||||
<div style={{ marginBottom: 10, fontWeight: 600 }}>{t('app.data_root.apply_method')}</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
|
||||
<Button loading={dataRootApplying} onClick={() => void handleApplyDataRoot(false)}>
|
||||
<Button
|
||||
disabled={directorySettingsApplying}
|
||||
loading={dataRootApplying}
|
||||
onClick={() => void handleApplyDataRoot(false)}
|
||||
>
|
||||
{t('app.data_root.action.switch_only')}
|
||||
</Button>
|
||||
<Button type="primary" loading={dataRootApplying} onClick={() => void handleApplyDataRoot(true)}>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={directorySettingsApplying}
|
||||
loading={dataRootApplying}
|
||||
onClick={() => void handleApplyDataRoot(true)}
|
||||
>
|
||||
{t('app.data_root.action.migrate_and_switch')}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -8378,6 +8549,7 @@ function App() {
|
||||
{t('app.data_root.restart_hint')}
|
||||
</div>
|
||||
</div>
|
||||
{renderLogDirectorySettings()}
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
|
||||
@@ -167,6 +167,47 @@ describe("i18n catalog", () => {
|
||||
expect(catalogs["zh-CN"][devHintKey]).toBe("接收最新的开发版本");
|
||||
});
|
||||
|
||||
it("keeps data-root log directory copy complete across all catalogs", () => {
|
||||
const logDirectoryKeys = [
|
||||
"app.data_root.log_directory.backend.dialog.select_directory",
|
||||
"app.data_root.log_directory.backend.error.desktop_only",
|
||||
"app.data_root.log_directory.backend.error.directory_unavailable",
|
||||
"app.data_root.log_directory.backend.error.environment_managed",
|
||||
"app.data_root.log_directory.backend.error.open_directory_failed",
|
||||
"app.data_root.log_directory.backend.error.open_directory_unsupported",
|
||||
"app.data_root.log_directory.backend.error.save_failed",
|
||||
"app.data_root.log_directory.backend.message.opened",
|
||||
"app.data_root.log_directory.backend.message.unchanged",
|
||||
"app.data_root.log_directory.backend.message.updated_restart",
|
||||
"app.data_root.log_directory.current_file",
|
||||
"app.data_root.log_directory.default_directory",
|
||||
"app.data_root.log_directory.description",
|
||||
"app.data_root.log_directory.environment_hint",
|
||||
"app.data_root.log_directory.message.apply_failed_with_error",
|
||||
"app.data_root.log_directory.message.open_failed_with_error",
|
||||
"app.data_root.log_directory.message.select_failed_with_error",
|
||||
"app.data_root.log_directory.message.select_valid_first",
|
||||
"app.data_root.log_directory.message.updated",
|
||||
"app.data_root.log_directory.pending_restart",
|
||||
"app.data_root.log_directory.placeholder",
|
||||
"app.data_root.log_directory.restart_hint",
|
||||
"app.data_root.log_directory.title",
|
||||
] as const;
|
||||
const base = catalogs["en-US"];
|
||||
|
||||
for (const language of SUPPORTED_LANGUAGES) {
|
||||
for (const key of logDirectoryKeys) {
|
||||
expect(catalogs[language]).toHaveProperty(key);
|
||||
expect(catalogs[language][key]).toBeTruthy();
|
||||
expect(getPlaceholders(catalogs[language][key])).toEqual(getPlaceholders(base[key]));
|
||||
}
|
||||
}
|
||||
|
||||
expect(catalogs["zh-CN"]["app.data_root.log_directory.title"]).toBe("日志目录");
|
||||
expect(catalogs["zh-CN"]["app.data_root.log_directory.environment_hint"]).toContain("GONAVI_LOG_DIR");
|
||||
expect(catalogs["en-US"]["app.data_root.log_directory.restart_hint"]).toContain("gonavi.log");
|
||||
});
|
||||
|
||||
it("includes App shell keys required by every supported language", () => {
|
||||
const appShellKeys = [
|
||||
"app.tools.title",
|
||||
|
||||
@@ -75,6 +75,7 @@ const importMain = async () => {
|
||||
ImportConnectionsPayload: (raw: string, password?: string) => Promise<unknown>;
|
||||
ExportConnectionsPackage: (options?: { includeSecrets?: boolean; filePassword?: string }) => Promise<{ success: boolean; message?: string }>;
|
||||
ApplyDataRootDirectory: (path: string) => Promise<{ success: boolean; message?: string; data?: { path?: string } }>;
|
||||
ApplyLogDirectory: (path: string) => Promise<{ success: boolean; message?: string; data?: { logDirectory?: string; logDirectoryRestartRequired?: boolean } }>;
|
||||
SaveQuery: (input: { id?: string; name?: string; sql?: string }) => Promise<{ name: string; sql: string }>;
|
||||
CheckForUpdates: () => Promise<{ success: boolean; data?: Record<string, unknown> }>;
|
||||
CheckForUpdatesSilently: () => Promise<{ success: boolean; data?: Record<string, unknown> }>;
|
||||
@@ -241,6 +242,25 @@ describe('main browser mock', () => {
|
||||
expect(source).not.toContain("'数据目录已更新'");
|
||||
});
|
||||
|
||||
it('keeps browser mock log directory state available for the data-root page', async () => {
|
||||
vi.stubGlobal('navigator', {
|
||||
languages: ['en-US'],
|
||||
language: 'en-US',
|
||||
});
|
||||
|
||||
const app = await importMain();
|
||||
const { t } = await import('./i18n');
|
||||
|
||||
await expect(app!.ApplyLogDirectory('C:/mock/custom-logs')).resolves.toEqual(expect.objectContaining({
|
||||
success: true,
|
||||
message: t('app.data_root.log_directory.message.updated'),
|
||||
data: expect.objectContaining({
|
||||
logDirectory: 'C:/mock/custom-logs',
|
||||
logDirectoryRestartRequired: true,
|
||||
}),
|
||||
}));
|
||||
});
|
||||
|
||||
it('localizes browser mock MCP server test messages', async () => {
|
||||
vi.stubGlobal('navigator', {
|
||||
languages: ['en-US'],
|
||||
|
||||
@@ -142,6 +142,13 @@ if (
|
||||
driverPath: 'C:/mock/.gonavi/drivers',
|
||||
isDefaultPath: true,
|
||||
bootstrapPath: 'C:/mock/.gonavi/storage_root.json',
|
||||
logDirectory: 'C:/Users/mock/.GoNavi/Logs',
|
||||
activeLogDirectory: 'C:/Users/mock/.GoNavi/Logs',
|
||||
logFilePath: 'C:/Users/mock/.GoNavi/Logs/gonavi.log',
|
||||
defaultLogDirectory: 'C:/Users/mock/.GoNavi/Logs',
|
||||
logDirectorySource: 'default',
|
||||
logDirectoryEditable: true,
|
||||
logDirectoryRestartRequired: false,
|
||||
};
|
||||
|
||||
const upsertMockConnection = (view: any) => {
|
||||
@@ -543,6 +550,7 @@ if (
|
||||
OpenDownloadedUpdateDirectory: async () => ({ success: false }),
|
||||
OpenDriverDownloadDirectory: async (path: string) => ({ success: true, data: { path } }),
|
||||
OpenDataRootDirectory: async () => ({ success: true }),
|
||||
OpenLogDirectory: async () => ({ success: true }),
|
||||
SelectSQLDirectory: async (currentPath: string) => ({ success: false, message: currentPath ? '已取消' : '已取消' }),
|
||||
ListSQLDirectory: async () => ({ success: true, data: [] }),
|
||||
ReadSQLFile: async () => ({ success: false, message: '已取消' }),
|
||||
@@ -648,6 +656,24 @@ if (
|
||||
};
|
||||
return { success: true, message: t('app.data_root.message.updated'), data: cloneBrowserMockValue(mockDataRootInfo) };
|
||||
},
|
||||
SelectLogDirectory: async (currentPath: string) => ({
|
||||
success: true,
|
||||
data: { directory: currentPath || mockDataRootInfo.defaultLogDirectory },
|
||||
}),
|
||||
ApplyLogDirectory: async (path: string) => {
|
||||
const nextPath = String(path || mockDataRootInfo.defaultLogDirectory);
|
||||
mockDataRootInfo = {
|
||||
...mockDataRootInfo,
|
||||
logDirectory: nextPath,
|
||||
logDirectorySource: nextPath === mockDataRootInfo.defaultLogDirectory ? 'default' : 'custom',
|
||||
logDirectoryRestartRequired: nextPath !== mockDataRootInfo.activeLogDirectory,
|
||||
};
|
||||
return {
|
||||
success: true,
|
||||
message: t('app.data_root.log_directory.message.updated'),
|
||||
data: cloneBrowserMockValue(mockDataRootInfo),
|
||||
};
|
||||
},
|
||||
}
|
||||
},
|
||||
aiservice: {
|
||||
|
||||
6
frontend/wailsjs/go/app/App.d.ts
vendored
6
frontend/wailsjs/go/app/App.d.ts
vendored
@@ -12,6 +12,8 @@ export function ApplyChanges(arg1:connection.ConnectionConfig,arg2:string,arg3:s
|
||||
|
||||
export function ApplyDataRootDirectory(arg1:string,arg2:boolean):Promise<connection.QueryResult>;
|
||||
|
||||
export function ApplyLogDirectory(arg1:string):Promise<connection.QueryResult>;
|
||||
|
||||
export function BuildSQLAuditExport(arg1:sqlaudit.Filter,arg2:string):Promise<connection.QueryResult>;
|
||||
|
||||
export function CancelApplicationQuit():Promise<connection.QueryResult>;
|
||||
@@ -282,6 +284,8 @@ export function OpenDownloadedUpdateDirectory():Promise<connection.QueryResult>;
|
||||
|
||||
export function OpenDriverDownloadDirectory(arg1:string):Promise<connection.QueryResult>;
|
||||
|
||||
export function OpenLogDirectory():Promise<connection.QueryResult>;
|
||||
|
||||
export function OpenSQLFile():Promise<connection.QueryResult>;
|
||||
|
||||
export function PreviewChanges(arg1:connection.ConnectionConfig,arg2:string,arg3:string,arg4:connection.ChangeSet):Promise<connection.QueryResult>;
|
||||
@@ -406,6 +410,8 @@ export function SelectDriverPackageDirectory(arg1:string):Promise<connection.Que
|
||||
|
||||
export function SelectDriverPackageFile(arg1:string):Promise<connection.QueryResult>;
|
||||
|
||||
export function SelectLogDirectory(arg1:string):Promise<connection.QueryResult>;
|
||||
|
||||
export function SelectSQLDirectory(arg1:string):Promise<connection.QueryResult>;
|
||||
|
||||
export function SelectSQLFileForExecution():Promise<connection.QueryResult>;
|
||||
|
||||
@@ -10,6 +10,10 @@ export function ApplyDataRootDirectory(arg1, arg2) {
|
||||
return window['go']['app']['App']['ApplyDataRootDirectory'](arg1, arg2);
|
||||
}
|
||||
|
||||
export function ApplyLogDirectory(arg1) {
|
||||
return window['go']['app']['App']['ApplyLogDirectory'](arg1);
|
||||
}
|
||||
|
||||
export function BuildSQLAuditExport(arg1, arg2) {
|
||||
return window['go']['app']['App']['BuildSQLAuditExport'](arg1, arg2);
|
||||
}
|
||||
@@ -550,6 +554,10 @@ export function OpenDriverDownloadDirectory(arg1) {
|
||||
return window['go']['app']['App']['OpenDriverDownloadDirectory'](arg1);
|
||||
}
|
||||
|
||||
export function OpenLogDirectory() {
|
||||
return window['go']['app']['App']['OpenLogDirectory']();
|
||||
}
|
||||
|
||||
export function OpenSQLFile() {
|
||||
return window['go']['app']['App']['OpenSQLFile']();
|
||||
}
|
||||
@@ -798,6 +806,10 @@ export function SelectDriverPackageFile(arg1) {
|
||||
return window['go']['app']['App']['SelectDriverPackageFile'](arg1);
|
||||
}
|
||||
|
||||
export function SelectLogDirectory(arg1) {
|
||||
return window['go']['app']['App']['SelectLogDirectory'](arg1);
|
||||
}
|
||||
|
||||
export function SelectSQLDirectory(arg1) {
|
||||
return window['go']['app']['App']['SelectSQLDirectory'](arg1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user