mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #580 from dbeaver/feat/sql-editor-result-set-tabs
feat(plugin-sql-editor): CB-1284 close tabs on executing new query
This commit is contained in:
@@ -19,4 +19,5 @@ export default [
|
||||
['sql_editor_download_script_tooltip', 'Download sql script'],
|
||||
['sql_editor_upload_script_unsaved_changes_dialog_message', 'Your current script will be overwritten by the uploaded script. Do you want to save it first?'],
|
||||
['sql_editor_upload_script_max_size_title', 'File size exceeds max size'],
|
||||
['sql_editor_close_result_tabs_dialog_title', 'Confirm closing tabs'],
|
||||
];
|
||||
|
||||
@@ -15,4 +15,5 @@ export default [
|
||||
['sql_execution_plan_properties_panel_value', 'Valore'],
|
||||
['sql_execution_plan_properties_panel_general', 'Generale'],
|
||||
['sql_execution_plan_properties_panel_details', 'Dettagli'],
|
||||
['sql_editor_close_result_tabs_dialog_title', 'Confirm closing tabs'],
|
||||
];
|
||||
|
||||
@@ -19,4 +19,5 @@ export default [
|
||||
['sql_editor_download_script_tooltip', 'Скачать sql скрипт'],
|
||||
['sql_editor_upload_script_unsaved_changes_dialog_message', 'Текущий скрипт будет перезаписан загруженным. Сохранить текущий?'],
|
||||
['sql_editor_upload_script_max_size_title', 'Размер файла превышает максимально допустимый'],
|
||||
['sql_editor_close_result_tabs_dialog_title', 'Подтвердить закрытие вкладок'],
|
||||
];
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
export default [
|
||||
['sql_editor_menu', 'SQL编辑器'],
|
||||
['sql_editor_placeholder', '使用Ctrl + Enter执行查询以查看结果'],
|
||||
['sql_editor_execution_plan_button_tooltip', '解释执行计划(Shift + Ctrl + E)'],
|
||||
['sql_editor_sql_execution_button_tooltip', '执行SQL语句(Ctrl + Enter)'],
|
||||
['sql_editor_sql_execution_new_tab_button_tooltip', '在新选项卡中执行SQL语句(Ctrl + \\)(Shift + Ctrl + Enter)'],
|
||||
['sql_editor_sql_execution_script_button_tooltip', '执行SQL脚本(Alt + X)'],
|
||||
['sql_editor_sql_format_button_tooltip', '格式化SQL脚本(Shift + Ctrl + F)'],
|
||||
['sql_editor_sql_statistics_unavailable', '统计不可用'],
|
||||
['sql_editor_sql_execution_queries', '查询:'],
|
||||
['sql_editor_sql_execution_executing', '执行...'],
|
||||
['sql_execution_plan_placeholder', '执行计划为空'],
|
||||
['sql_execution_plan_properties_panel_placeholder', '没有要显示的项目'],
|
||||
['sql_execution_plan_properties_panel_name', '名称'],
|
||||
['sql_execution_plan_properties_panel_value', '值'],
|
||||
['sql_execution_plan_properties_panel_general', '一般'],
|
||||
['sql_execution_plan_properties_panel_details', '详情'],
|
||||
['sql_editor_upload_script_tooltip', '上传SQL脚本'],
|
||||
['sql_editor_download_script_tooltip', '下载SQL脚本'],
|
||||
['sql_editor_upload_script_unsaved_changes_dialog_message', '您当前的脚本将被上传的脚本覆盖。要先保存吗?'],
|
||||
['sql_editor_upload_script_max_size_title', '文件大小超过最大大小'],
|
||||
];
|
||||
['sql_editor_menu', 'SQL编辑器'],
|
||||
['sql_editor_placeholder', '使用Ctrl + Enter执行查询以查看结果'],
|
||||
['sql_editor_execution_plan_button_tooltip', '解释执行计划(Shift + Ctrl + E)'],
|
||||
['sql_editor_sql_execution_button_tooltip', '执行SQL语句(Ctrl + Enter)'],
|
||||
['sql_editor_sql_execution_new_tab_button_tooltip', '在新选项卡中执行SQL语句(Ctrl + \\)(Shift + Ctrl + Enter)'],
|
||||
['sql_editor_sql_execution_script_button_tooltip', '执行SQL脚本(Alt + X)'],
|
||||
['sql_editor_sql_format_button_tooltip', '格式化SQL脚本(Shift + Ctrl + F)'],
|
||||
['sql_editor_sql_statistics_unavailable', '统计不可用'],
|
||||
['sql_editor_sql_execution_queries', '查询:'],
|
||||
['sql_editor_sql_execution_executing', '执行...'],
|
||||
['sql_execution_plan_placeholder', '执行计划为空'],
|
||||
['sql_execution_plan_properties_panel_placeholder', '没有要显示的项目'],
|
||||
['sql_execution_plan_properties_panel_name', '名称'],
|
||||
['sql_execution_plan_properties_panel_value', '值'],
|
||||
['sql_execution_plan_properties_panel_general', '一般'],
|
||||
['sql_execution_plan_properties_panel_details', '详情'],
|
||||
['sql_editor_upload_script_tooltip', '上传SQL脚本'],
|
||||
['sql_editor_download_script_tooltip', '下载SQL脚本'],
|
||||
['sql_editor_upload_script_unsaved_changes_dialog_message', '您当前的脚本将被上传的脚本覆盖。要先保存吗?'],
|
||||
['sql_editor_upload_script_max_size_title', '文件大小超过最大大小'],
|
||||
['sql_editor_close_result_tabs_dialog_title', 'Confirm closing tabs'],
|
||||
];
|
||||
|
||||
@@ -20,6 +20,7 @@ import type { IControlledCodeMirror } from 'react-codemirror2';
|
||||
|
||||
import { ConnectionExecutionContextService } from '@cloudbeaver/core-connections';
|
||||
import { IDestructibleController, IInitializableController, injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService, ConfirmationDialog, DialogueStateResult } from '@cloudbeaver/core-dialogs';
|
||||
import type { SqlDialectInfo } from '@cloudbeaver/core-sdk';
|
||||
import { throttleAsync } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -29,6 +30,7 @@ import { SqlEditorService } from '../SqlEditorService';
|
||||
import { ISQLScriptSegment, SQLParser } from '../SQLParser';
|
||||
import { SqlExecutionPlanService } from '../SqlResultTabs/ExecutionPlan/SqlExecutionPlanService';
|
||||
import { SqlQueryService } from '../SqlResultTabs/SqlQueryService';
|
||||
import { SqlResultTabsService } from '../SqlResultTabs/SqlResultTabsService';
|
||||
|
||||
const closeCharacters = /[\s()[\]{};:>,=\\*]/;
|
||||
|
||||
@@ -113,11 +115,13 @@ export class SqlEditorController implements IInitializableController, IDestructi
|
||||
private reactionDisposer: IReactionDisposer | null;
|
||||
|
||||
constructor(
|
||||
private connectionExecutionContextService: ConnectionExecutionContextService,
|
||||
private sqlQueryService: SqlQueryService,
|
||||
private sqlDialectInfoService: SqlDialectInfoService,
|
||||
private sqlEditorService: SqlEditorService,
|
||||
private sqlExecutionPlanService: SqlExecutionPlanService,
|
||||
private readonly connectionExecutionContextService: ConnectionExecutionContextService,
|
||||
private readonly sqlQueryService: SqlQueryService,
|
||||
private readonly sqlDialectInfoService: SqlDialectInfoService,
|
||||
private readonly sqlEditorService: SqlEditorService,
|
||||
private readonly sqlExecutionPlanService: SqlExecutionPlanService,
|
||||
private readonly sqlResultTabsService: SqlResultTabsService,
|
||||
private readonly commonDialogService: CommonDialogService
|
||||
) {
|
||||
this.parser = new SQLParser();
|
||||
this.getHandleAutocomplete = this.getHandleAutocomplete.bind(this);
|
||||
@@ -228,6 +232,21 @@ export class SqlEditorController implements IInitializableController, IDestructi
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.state.tabs.length) {
|
||||
const result = await this.commonDialogService.open(ConfirmationDialog, {
|
||||
title: 'sql_editor_close_result_tabs_dialog_title',
|
||||
message: `Do you want to close ${this.state.tabs.length} tabs before executing script?`,
|
||||
confirmActionText: 'ui_yes',
|
||||
extraStatus: 'no',
|
||||
});
|
||||
|
||||
if (result === DialogueStateResult.Resolved) {
|
||||
this.sqlResultTabsService.removeResultTabs(this.state);
|
||||
} else if (result === DialogueStateResult.Rejected) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.beforeExecute();
|
||||
try {
|
||||
this.executingScript = true;
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { action, makeObservable } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
|
||||
import type { ISqlEditorTabState } from '../ISqlEditorTabState';
|
||||
import type { ISqlEditorTabState, ISqlEditorResultTab } from '../ISqlEditorTabState';
|
||||
import { SqlExecutionPlanService } from './ExecutionPlan/SqlExecutionPlanService';
|
||||
import { SqlQueryResultService } from './SqlQueryResultService';
|
||||
import { SqlQueryService } from './SqlQueryService';
|
||||
@@ -19,7 +21,11 @@ export class SqlResultTabsService {
|
||||
private sqlQueryService: SqlQueryService,
|
||||
private sqlQueryResultService: SqlQueryResultService,
|
||||
private sqlExecutionPlanService: SqlExecutionPlanService,
|
||||
) { }
|
||||
) {
|
||||
makeObservable(this, {
|
||||
removeResultTabs: action,
|
||||
});
|
||||
}
|
||||
|
||||
selectResultTab(state: ISqlEditorTabState, resultId: string): void {
|
||||
state.currentTabId = resultId;
|
||||
@@ -29,14 +35,26 @@ export class SqlResultTabsService {
|
||||
const tab = state.tabs.find(tab => tab.id === tabId);
|
||||
|
||||
if (tab) {
|
||||
state.tabs.splice(state.tabs.indexOf(tab), 1);
|
||||
this.removeTab(state, tab);
|
||||
} else {
|
||||
console.warn(`Unable to remove tab. Tab with id="${tabId}" was not found`);
|
||||
}
|
||||
}
|
||||
|
||||
this.sqlQueryService.removeStatisticsTab(state, tabId);
|
||||
this.sqlQueryResultService.removeResultTab(state, tabId);
|
||||
this.sqlExecutionPlanService.removeExecutionPlanTab(state, tabId);
|
||||
removeResultTabs(state: ISqlEditorTabState): void {
|
||||
for (const tab of state.tabs.slice()) {
|
||||
this.removeTab(state, tab);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.currentTabId === tabId) {
|
||||
private removeTab(state: ISqlEditorTabState, tab: ISqlEditorResultTab) {
|
||||
state.tabs.splice(state.tabs.indexOf(tab), 1);
|
||||
|
||||
this.sqlQueryService.removeStatisticsTab(state, tab.id);
|
||||
this.sqlQueryResultService.removeResultTab(state, tab.id);
|
||||
this.sqlExecutionPlanService.removeExecutionPlanTab(state, tab.id);
|
||||
|
||||
if (state.currentTabId === tab.id) {
|
||||
if (state.tabs.length > 0) {
|
||||
state.currentTabId = state.tabs[0].id;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user