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:
Alexey
2021-12-08 10:52:07 +03:00
committed by GitHub
6 changed files with 74 additions and 33 deletions
@@ -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 {