Skip to content

Commit 1f00f67

Browse files
committed
fix dazong issue
1 parent 0ab4ccd commit 1f00f67

10 files changed

Lines changed: 185 additions & 7 deletions

File tree

webapp/packages/core-blocks/src/useErrorDetails.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ interface IErrorDetailsHook {
2525
isOpen: boolean;
2626
open: () => void;
2727
refresh?: () => void;
28+
errorCode?: string;
2829
}
2930

3031
type HookType =
@@ -55,6 +56,7 @@ export function useErrorDetails(error: IErrorDetailsHook['error']): HookType {
5556
const name = typeof error === 'string' ? translate('core_blocks_exception_message_error_message') : error?.name;
5657
const message = typeof error === 'string' ? error : error?.message;
5758
const executionFailedMessage = (error as any)?.execution_failed_message as string;
59+
const errorCode = (error as any)?.errorCode as string;
5860

5961
return {
6062
name,
@@ -66,5 +68,6 @@ export function useErrorDetails(error: IErrorDetailsHook['error']): HookType {
6668
open,
6769
refresh: loadingError?.refresh,
6870
executionFailedMessage,
71+
errorCode,
6972
};
7073
}

webapp/packages/plugin-data-viewer/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@cloudbeaver/plugin-navigation-tabs": "workspace:*",
4646
"@cloudbeaver/plugin-object-viewer": "workspace:*",
4747
"@cloudbeaver/plugin-sql-editor": "workspace:*",
48+
"@cloudbeaver/plugin-sql-editor-navigation-tab": "workspace:*",
4849
"@dbeaver/js-helpers": "workspace:^",
4950
"@dbeaver/result-set-api": "workspace:^",
5051
"lz-string": "1.5.0",
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.container {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 16px;
5+
}
6+
7+
.message {
8+
color: var(--theme-text-on-surface);
9+
line-height: 1.5;
10+
}
11+
12+
.queryInfo {
13+
display: flex;
14+
flex-direction: column;
15+
gap: 8px;
16+
padding: 12px;
17+
background-color: var(--theme-background-secondary);
18+
border-radius: 4px;
19+
border: 1px solid var(--theme-divider);
20+
}
21+
22+
.queryLabel {
23+
font-weight: 500;
24+
color: var(--theme-text-on-surface);
25+
font-size: 14px;
26+
}
27+
28+
.queryPreview {
29+
font-family: monospace;
30+
font-size: 13px;
31+
color: var(--theme-text-on-surface-secondary);
32+
word-break: break-all;
33+
white-space: pre-wrap;
34+
max-height: 120px;
35+
overflow-y: auto;
36+
}
37+
38+
.footer {
39+
display: flex;
40+
align-items: center;
41+
gap: 12px;
42+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
Button,
3+
Fill,
4+
Translate,
5+
CommonDialogBody,
6+
CommonDialogHeader,
7+
CommonDialogWrapper,
8+
s,
9+
CommonDialogFooter,
10+
useS,
11+
} from '@cloudbeaver/core-blocks';
12+
import style from './SqlEditorSessionClosedDialog.module.css';
13+
14+
import type { DialogComponent } from '@cloudbeaver/core-dialogs';
15+
16+
export interface SqlEditorSessionClosedDialogPayload {
17+
query?: string;
18+
}
19+
20+
export const SqlEditorSessionClosedDialog: DialogComponent<SqlEditorSessionClosedDialogPayload, boolean> = function SqlSessionClosedDialog({
21+
payload,
22+
resolveDialog,
23+
rejectDialog,
24+
className,
25+
}) {
26+
const styles = useS(style);
27+
28+
return (
29+
<CommonDialogWrapper size="medium" className={className} fixedWidth>
30+
<CommonDialogHeader title="plugin_data_viewer_sql_session_closed_title" icon="/icons/info_icon.svg" onReject={rejectDialog} />
31+
<CommonDialogBody>
32+
<div className={s(styles, { container: true })}>
33+
<div className={s(styles, { message: true })}>
34+
<Translate token="plugin_data_viewer_sql_session_closed_message" />
35+
</div>
36+
{payload.query && (
37+
<div className={s(styles, { queryInfo: true })}>
38+
<div className={s(styles, { queryLabel: true })}>
39+
<Translate token="plugin_data_viewer_sql_session_closed_query_label" />
40+
</div>
41+
<div className={s(styles, { queryPreview: true })} title={payload.query}>
42+
{payload.query.length > 100 ? `${payload.query.substring(0, 100)}...` : payload.query}
43+
</div>
44+
</div>
45+
)}
46+
</div>
47+
</CommonDialogBody>
48+
<CommonDialogFooter className={s(styles, { footer: true })}>
49+
<Button type="button" variant="secondary" onClick={rejectDialog}>
50+
<Translate token="ui_processing_cancel" />
51+
</Button>
52+
<Fill />
53+
<Button type="button" onClick={() => resolveDialog(true)}>
54+
<Translate token="plugin_data_viewer_sql_session_closed_open_editor" />
55+
</Button>
56+
</CommonDialogFooter>
57+
</CommonDialogWrapper>
58+
);
59+
};

webapp/packages/plugin-data-viewer/src/TableViewer/TableError.tsx

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88
import { observable } from 'mobx';
99
import { observer } from 'mobx-react-lite';
10-
import { useEffect } from 'react';
10+
import { useCallback, useEffect } from 'react';
1111
import { compressToEncodedURIComponent } from 'lz-string';
1212

1313
import { Button, IconOrImage, Placeholder, s, useErrorDetails, useObservableRef, useS, useStateDelay, useTranslate } from '@cloudbeaver/core-blocks';
@@ -20,7 +20,11 @@ import { DataViewerService } from '../DataViewerService.js';
2020
import styles from './TableError.module.css';
2121
import { ConnectionSchemaManagerService } from '@cloudbeaver/plugin-datasource-context-switch';
2222
import { NavigationTabsService } from '@cloudbeaver/plugin-navigation-tabs';
23-
import { SqlDataSourceService } from '@cloudbeaver/plugin-sql-editor';
23+
import { ConnectionInfoResource, createConnectionParam } from '@cloudbeaver/core-connections';
24+
import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs';
25+
import { LocalStorageSqlDataSource, SqlDataSourceService } from '@cloudbeaver/plugin-sql-editor';
26+
import { isSQLEditorTab, SqlEditorNavigatorService } from '@cloudbeaver/plugin-sql-editor-navigation-tab';
27+
import { SqlEditorSessionClosedDialog } from './SqlEditorSessionClosedDialog.js';
2428

2529
interface Props {
2630
model: IDatabaseDataModel;
@@ -41,6 +45,9 @@ export const TableError = observer<Props>(function TableError({ model, loading,
4145
const connectionSchemaManagerService = useService(ConnectionSchemaManagerService);
4246
const sqlDataSourceService = useService(SqlDataSourceService);
4347
const navigationTabsService = useService(NavigationTabsService);
48+
const commonDialogService = useService(CommonDialogService);
49+
const sqlEditorNavigatorService = useService(SqlEditorNavigatorService);
50+
const connectionInfo = useService(ConnectionInfoResource);
4451

4552
const style = useS(styles);
4653
const dataViewerService = useService(DataViewerService);
@@ -113,6 +120,48 @@ export const TableError = observer<Props>(function TableError({ model, loading,
113120
}
114121
}, [errorInfo, model.source.error]);
115122

123+
const handleReopenEditor = useCallback(async () => {
124+
const contextId = navigationTabsService.getView()?.context.id ?? '';
125+
const dataSource = sqlDataSourceService.get(contextId);
126+
127+
if (dataSource) {
128+
const query = dataSource.script || '';
129+
const shouldReopen = await commonDialogService.open(SqlEditorSessionClosedDialog, { query });
130+
if (shouldReopen === true || shouldReopen === DialogueStateResult.Resolved) {
131+
const relatedTab = navigationTabsService.findTab(isSQLEditorTab(tab => tab.id === contextId));
132+
if (relatedTab) {
133+
await navigationTabsService.closeTab(relatedTab.id, true);
134+
135+
const executionContext = dataSource?.executionContext;
136+
137+
if (executionContext) {
138+
const connection = executionContext
139+
? connectionInfo.get(createConnectionParam(executionContext.projectId, executionContext.connectionId))
140+
: undefined;
141+
142+
await sqlEditorNavigatorService.openNewEditor({
143+
dataSourceKey: LocalStorageSqlDataSource.key,
144+
connectionKey: connection && createConnectionParam(connection),
145+
query: query,
146+
});
147+
}
148+
}
149+
}
150+
}
151+
}, [navigationTabsService, sqlDataSourceService, commonDialogService, connectionInfo, sqlEditorNavigatorService]);
152+
153+
useEffect(() => {
154+
const SQL_CONTEXT_ERROR_CODE = '508';
155+
if (errorInfo.error !== model.source.error) {
156+
errorInfo.error = model.source.error || null;
157+
errorInfo.display = !!model.source.error;
158+
}
159+
const isSqlContextError = error.errorCode === SQL_CONTEXT_ERROR_CODE || /SQL context .* not found/i.test(error.message || '');
160+
if (isSqlContextError) {
161+
handleReopenEditor();
162+
}
163+
}, [error.message, handleReopenEditor, model.source.error, errorInfo]);
164+
116165
return (
117166
<div
118167
role="status"

webapp/packages/plugin-data-viewer/src/locales/en.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,11 @@ export default [
6363
['settings_data_editor_fetch_default_description', 'Default number of rows to fetch'],
6464
['plugin_data_viewer_no_available_presentation', 'No available presentation'],
6565
['plugin_data_viewer_result_set_save_success', 'Saved successfully'],
66+
['plugin_data_viewer_sql_session_closed_title', 'SQL Execution Session Closed'],
67+
[
68+
'plugin_data_viewer_sql_session_closed_message',
69+
'The current SQL execution session has been closed, possibly due to connection timeout or manual disconnection. You can reopen the SQL editor and retain the current query statement.',
70+
],
71+
['plugin_data_viewer_sql_session_closed_query_label', 'Current Query:'],
72+
['plugin_data_viewer_sql_session_closed_open_editor', 'Reopen Editor'],
6673
];

webapp/packages/plugin-data-viewer/tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@
9090
},
9191
{
9292
"path": "../plugin-sql-editor"
93+
},
94+
{
95+
"path": "../plugin-sql-editor-navigation-tab"
9396
}
9497
],
9598
"include": [

webapp/packages/plugin-session-expiration/src/SessionExpireDialog/SessionExpiredDialog.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,20 @@ import {
1717
useS,
1818
useTranslate,
1919
} from '@cloudbeaver/core-blocks';
20-
import { useService } from '@cloudbeaver/core-di';
2120
import type { DialogComponent } from '@cloudbeaver/core-dialogs';
22-
import { RouterService } from '@cloudbeaver/core-routing';
2321
import { ServerNodeChangedDialogStyles } from '@cloudbeaver/plugin-root';
2422

2523
export const SessionExpiredDialog: DialogComponent<null, null> = observer(function SessionExpiredDialog({ rejectDialog }) {
2624
const styles = useS(ServerNodeChangedDialogStyles);
27-
const routerService = useService(RouterService);
25+
// const routerService = useService(RouterService);
2826
const translate = useTranslate();
2927
function reload() {
30-
routerService.reload();
28+
const currentSearch = window.location.search;
29+
30+
document.cookie = 'cb-session-id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
31+
localStorage.removeItem('TOKEN');
32+
const DMS_REDIRECT_KEY_PARAMS_NAME = 'target';
33+
window.location.href = `/login?${DMS_REDIRECT_KEY_PARAMS_NAME}=${encodeURIComponent('/project/700300/cloud-beaver' + currentSearch)}`;
3134
}
3235

3336
return (

webapp/packages/plugin-session-expiration/src/SessionExpireDialog/SessionExpiredDialogBootstrap.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ export class SessionExpiredDialogBootstrap extends Bootstrap {
2929
this.sessionExpireService.onSessionExpire.addPostHandler(this.handleSessionExpired.bind(this));
3030
}
3131

32+
private reload() {
33+
const currentSearch = window.location.search;
34+
35+
localStorage.removeItem('TOKEN');
36+
// 删除 名为cb-session-id 的 cookie
37+
document.cookie = 'cb-session-id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
38+
const DMS_REDIRECT_KEY_PARAMS_NAME = 'target';
39+
window.location.href = `/login?${DMS_REDIRECT_KEY_PARAMS_NAME}=${encodeURIComponent('/project/700300/cloud-beaver' + currentSearch)}`;
40+
}
41+
3242
private async handleSessionExpired(): Promise<void> {
3343
const state = await this.commonDialogService.open(SessionExpiredDialog, null);
3444

@@ -37,7 +47,7 @@ export class SessionExpiredDialogBootstrap extends Bootstrap {
3747
() => ActionSnackbar,
3848
{
3949
actionText: 'ui_processing_reload',
40-
onAction: () => this.routerService.reload(),
50+
onAction: () => this.reload(),
4151
},
4252
{ title: 'app_root_session_expired_title', persistent: true, type: ENotificationType.Error },
4353
);

webapp/yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2908,6 +2908,7 @@ __metadata:
29082908
"@cloudbeaver/plugin-navigation-tabs": "workspace:*"
29092909
"@cloudbeaver/plugin-object-viewer": "workspace:*"
29102910
"@cloudbeaver/plugin-sql-editor": "workspace:*"
2911+
"@cloudbeaver/plugin-sql-editor-navigation-tab": "workspace:*"
29112912
"@cloudbeaver/tsconfig": "workspace:*"
29122913
"@dbeaver/cli": "workspace:*"
29132914
"@dbeaver/js-helpers": "workspace:^"

0 commit comments

Comments
 (0)