From ab813e21aba794ea1e3a5f01b87d6fc5a6ad86ea Mon Sep 17 00:00:00 2001 From: Sychev Andrey <44414066+SychevAndrey@users.noreply.github.com> Date: Wed, 10 Sep 2025 15:04:03 +0200 Subject: [PATCH] dbeaver/pro#5129 cb 6095 sql editor buttons shortcut labels are hardcoded (#3696) * dbeaver/pro#5129 feat: use action item bindings API to get binding label removes hardcoded shortcuts adds formatting for shortcuts, uses OS-specific shortcuts * dbeaver/pro#5129 feat: add example of manual using getBindingLabel function * dbeaver/pro#5129 feat: use menu api for sql editor actions * dbeaver/pro#5129 fix: lint async * dbeaver/pro#5129 fix: remove wrong action icons move private methods to the end of files * dbeaver/pro#5129 refactor: use context via useDataContextLink hook * dbeaver/pro#5129 refactor: DRY ACTIONS * dbeaver/pro#5129 fix: DRY ACTIONS * dbeaver/pro#5129 fix: action titles * dbeaver/pro#5129 fix: DI after devel merge * dbeaver/pro#5129 bonus: fix text content in dropdowns --------- Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com> Co-authored-by: Alexey Potsetsuev --- .../core-blocks/src/FormControls/Combobox.css | 2 +- .../src/ContextMenu/MenuActionElement.tsx | 15 +- .../src/ContextMenu/MenuBar/MenuBar.tsx | 7 +- .../src/Action/Actions/ACTION_COLLAPSE_ALL.ts | 4 +- .../KeyBinding/Bindings/KEY_BINDING_ADD.ts | 13 ++ .../Bindings/KEY_BINDING_DUPLICATE.ts | 13 ++ .../src/Action/KeyBinding/getBindingLabel.ts | 65 +++++++-- webapp/packages/core-view/src/index.ts | 2 + .../DataGridContextMenuCellEditingService.ts | 33 +++-- .../TableFooterMenu/TableFooterMenuService.ts | 129 ++++++++++-------- .../ElementsTreeToolsMenuService.ts | 23 +--- .../src/ACTION_LINK_OBJECT.ts | 2 +- .../src/ObjectViewerNavTreeLinkMenuService.ts | 21 +-- .../src/locales/en.ts | 2 +- .../src/locales/fr.ts | 2 +- .../src/locales/it.ts | 2 +- .../src/locales/ru.ts | 2 +- .../src/locales/vi.ts | 2 +- .../src/locales/zh.ts | 2 +- .../plugin-sql-editor/src/MenuBootstrap.ts | 47 +++++-- .../src/SqlEditor/SQLEditorActions.tsx | 67 +++------ .../src/actions/ACTION_SQL_EDITOR_EXECUTE.ts | 3 +- .../actions/ACTION_SQL_EDITOR_EXECUTE_NEW.ts | 3 +- .../ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN.ts | 3 +- .../plugin-sql-editor/src/locales/en.ts | 12 +- .../plugin-sql-editor/src/locales/fr.ts | 14 +- .../plugin-sql-editor/src/locales/it.ts | 12 +- .../plugin-sql-editor/src/locales/ru.ts | 12 +- .../plugin-sql-editor/src/locales/vi.ts | 12 +- .../plugin-sql-editor/src/locales/zh.ts | 12 +- 30 files changed, 306 insertions(+), 232 deletions(-) create mode 100644 webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_ADD.ts create mode 100644 webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_DUPLICATE.ts diff --git a/webapp/packages/core-blocks/src/FormControls/Combobox.css b/webapp/packages/core-blocks/src/FormControls/Combobox.css index 77b1457ba6..b8228597df 100644 --- a/webapp/packages/core-blocks/src/FormControls/Combobox.css +++ b/webapp/packages/core-blocks/src/FormControls/Combobox.css @@ -29,6 +29,6 @@ padding-inline: calc(var(--tw-spacing) * 3); padding-block: calc(var(--tw-spacing) * 2); gap: calc(var(--tw-spacing) * 2); - line-height: 1; + line-height: 1.25; } } diff --git a/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx b/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx index 21c1b260f7..ddb44067db 100644 --- a/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx +++ b/webapp/packages/core-ui/src/ContextMenu/MenuActionElement.tsx @@ -47,12 +47,7 @@ export const MenuActionElement = observer(function Menu focusable onClick={handleClick} > - } - tooltip={actionInfo.tooltip} - loading={loading} - /> + } tooltip={actionInfo.tooltip} loading={loading} /> ); } @@ -72,7 +67,13 @@ export const MenuActionElement = observer(function Menu focusable onClick={handleClick} > - } tooltip={actionInfo.tooltip} loading={loading} /> + } + tooltip={actionInfo.tooltip} + loading={loading} + /> ); } diff --git a/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBar.tsx b/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBar.tsx index c067e7161e..7fa8691458 100644 --- a/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBar.tsx +++ b/webapp/packages/core-ui/src/ContextMenu/MenuBar/MenuBar.tsx @@ -21,11 +21,13 @@ import { useListKeyboardNavigation, useMergeRefs, useS, + useTranslate, } from '@cloudbeaver/core-blocks'; import { type IDataContext, useDataContextLink } from '@cloudbeaver/core-data-context'; import { DATA_CONTEXT_MENU_NESTED, DATA_CONTEXT_SUBMENU_ITEM, + getBindingLabel, type IMenuActionItem, type IMenuData, type IMenuInfo, @@ -146,11 +148,14 @@ export interface IMenuBarActionProps { export const MenuBarAction = registry( observer(function MenuBarAction({ item, parentMenuInfo, submenu, className }) { + const translate = useTranslate(); const actionInfo = item.action.actionInfo; const loading = item.action.isLoading(); /** @deprecated must be refactored (#1)*/ const displayLabel = item.action.isLabelVisible(); + const binding = item.action.binding ? getBindingLabel(item.action.binding.binding) : null; + const title = translate(actionInfo.tooltip ?? actionInfo.label); function handleClick() { item.events?.onSelect?.(); @@ -165,7 +170,7 @@ export const MenuBarAction = registry( label={actionInfo.label} displayLabel={displayLabel} icon={actionInfo.icon ?? parentMenuInfo?.icon} - title={actionInfo.tooltip ?? parentMenuInfo?.tooltip} + title={binding ? `${title} (${binding})` : title} disabled={item.disabled} loading={loading} submenu={submenu} diff --git a/webapp/packages/core-view/src/Action/Actions/ACTION_COLLAPSE_ALL.ts b/webapp/packages/core-view/src/Action/Actions/ACTION_COLLAPSE_ALL.ts index d8b1e5f4e0..58dd8d1610 100644 --- a/webapp/packages/core-view/src/Action/Actions/ACTION_COLLAPSE_ALL.ts +++ b/webapp/packages/core-view/src/Action/Actions/ACTION_COLLAPSE_ALL.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -8,6 +8,6 @@ import { createAction } from '../createAction.js'; export const ACTION_COLLAPSE_ALL = createAction('collapse-all', { - label: 'collapse-all', + label: 'app_navigationTree_action_collapse_all', icon: '/icons/collapse_sm.svg', }); diff --git a/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_ADD.ts b/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_ADD.ts new file mode 100644 index 0000000000..0a5f062ef9 --- /dev/null +++ b/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_ADD.ts @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2025 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { createKeyBinding } from '../createKeyBinding.js'; + +export const KEY_BINDING_ADD = createKeyBinding({ + id: 'add', + keys: ['alt+r'], +}); \ No newline at end of file diff --git a/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_DUPLICATE.ts b/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_DUPLICATE.ts new file mode 100644 index 0000000000..fc42bae435 --- /dev/null +++ b/webapp/packages/core-view/src/Action/KeyBinding/Bindings/KEY_BINDING_DUPLICATE.ts @@ -0,0 +1,13 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2025 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { createKeyBinding } from '../createKeyBinding.js'; + +export const KEY_BINDING_DUPLICATE = createKeyBinding({ + id: 'duplicate', + keys: ['alt+shift+r'], +}); \ No newline at end of file diff --git a/webapp/packages/core-view/src/Action/KeyBinding/getBindingLabel.ts b/webapp/packages/core-view/src/Action/KeyBinding/getBindingLabel.ts index 9028cc3193..64e8c9ec2f 100644 --- a/webapp/packages/core-view/src/Action/KeyBinding/getBindingLabel.ts +++ b/webapp/packages/core-view/src/Action/KeyBinding/getBindingLabel.ts @@ -1,18 +1,67 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import { getOSSpecificKeys } from './getCommonAndOSSpecificKeys.js'; +import { getOS, OperatingSystem } from '@cloudbeaver/core-utils'; +import { getCommonAndOSSpecificKeys } from './getCommonAndOSSpecificKeys.js'; import type { IKeyBinding } from './IKeyBinding.js'; -export function getBindingLabel(binding: IKeyBinding) { - let bindingLabel = getOSSpecificKeys(binding) ?? binding.keys; - if (Array.isArray(bindingLabel)) { - bindingLabel = bindingLabel[0]; - } +const FORMAT_SHORTCUT_KEYS_MAP: Record = { + comma: ',', + slash: '/', + backslash: '\\', + backspace: '⌫', + tab: 'tab', + clear: 'clear', + enter: '↵', + return: '↵', + escape: 'escape', + esc: 'escape', + space: '␣', + up: '↑', + down: '↓', + left: '←', + right: '→', + pageup: 'pageup', + pagedown: 'pagedown', + del: '⌦', + delete: '⌦', +}; +const SOURCE_DIVIDER_REGEXP = /\+/gi; +const APPLIED_DIVIDER = ' + '; - return bindingLabel?.replace(/\+/g, ' + ').replace(/\b\w/g, letter => letter.toUpperCase()); +function transformKeys(keyBinding: IKeyBinding): string[] { + return getCommonAndOSSpecificKeys(keyBinding).map(shortcut => + shortcut.split(SOURCE_DIVIDER_REGEXP).map(formatKeyToDisplayKey).join(APPLIED_DIVIDER).toLocaleUpperCase(), + ); +} + +function formatKeyToDisplayKey(code: string): string { + const lowerCaseCode = code.toLowerCase(); + const OS = getOS(); + + switch (lowerCaseCode) { + case 'mod': + if (OS === OperatingSystem.windowsOS || OS === OperatingSystem.linuxOS) { + return 'CTRL'; + } + if (OS === OperatingSystem.macOS) { + return 'CMD'; + } + return code; + case 'alt': + if (OS === OperatingSystem.macOS) { + return 'OPTION'; + } + return 'ALT'; + default: + return FORMAT_SHORTCUT_KEYS_MAP[lowerCaseCode] ?? code; + } +} + +export function getBindingLabel(binding: IKeyBinding): string | undefined { + return transformKeys(binding)[0]; } diff --git a/webapp/packages/core-view/src/index.ts b/webapp/packages/core-view/src/index.ts index d62072c7b8..d82e1c2163 100644 --- a/webapp/packages/core-view/src/index.ts +++ b/webapp/packages/core-view/src/index.ts @@ -37,6 +37,8 @@ export * from './Action/KeyBinding/Bindings/KEY_BINDING_OPEN_IN_TAB.js'; export * from './Action/KeyBinding/Bindings/KEY_BINDING_REDO.js'; export * from './Action/KeyBinding/Bindings/KEY_BINDING_UNDO.js'; export * from './Action/KeyBinding/Bindings/KEY_BINDING_SAVE.js'; +export * from './Action/KeyBinding/Bindings/KEY_BINDING_ADD.js'; +export * from './Action/KeyBinding/Bindings/KEY_BINDING_DUPLICATE.js'; export * from './Action/KeyBinding/KeyBindingService.js'; export * from './Action/KeyBinding/createKeyBinding.js'; export * from './Action/ActionService.js'; diff --git a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts index f7563b8297..5d9995faf0 100644 --- a/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts +++ b/webapp/packages/plugin-data-spreadsheet-new/src/DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.ts @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. */ import { injectable } from '@cloudbeaver/core-di'; -import { ACTION_EDIT, ActionService, MenuService } from '@cloudbeaver/core-view'; +import { ACTION_EDIT, ActionService, getBindingLabel, KEY_BINDING_ADD, KEY_BINDING_DUPLICATE, MenuService, type IAction } from '@cloudbeaver/core-view'; import { DATA_CONTEXT_DV_DDM, DATA_CONTEXT_DV_DDM_RESULT_INDEX, @@ -22,6 +22,8 @@ import { ResultSetSelectAction, ResultSetViewAction, } from '@cloudbeaver/plugin-data-viewer'; +import type { IDataContextProvider } from '@cloudbeaver/core-data-context'; +import { LocalizationService } from '@cloudbeaver/core-localization'; import { ACTION_DATA_GRID_EDITING_ADD_ROW } from '../Actions/Editing/ACTION_DATA_GRID_EDITING_ADD_ROW.js'; import { ACTION_DATA_GRID_EDITING_DELETE_ROW } from '../Actions/Editing/ACTION_DATA_GRID_EDITING_DELETE_ROW.js'; @@ -32,13 +34,16 @@ import { ACTION_DATA_GRID_EDITING_REVERT_SELECTED_ROW } from '../Actions/Editing import { ACTION_DATA_GRID_EDITING_SET_TO_NULL } from '../Actions/Editing/ACTION_DATA_GRID_EDITING_SET_TO_NULL.js'; import { MENU_DATA_GRID_EDITING } from './MENU_DATA_GRID_EDITING.js'; -@injectable(() => [ActionService, MenuService]) +@injectable(() => [ActionService, LocalizationService, MenuService]) export class DataGridContextMenuCellEditingService { constructor( private readonly actionService: ActionService, + private readonly localizationService: LocalizationService, private readonly menuService: MenuService, ) { } + + register(): void { this.menuService.addCreator({ root: true, @@ -140,13 +145,7 @@ export class DataGridContextMenuCellEditingService { ACTION_DATA_GRID_EDITING_REVERT_SELECTED_ROW, ].includes(action); }, - getActionInfo(context, action) { - if (action === ACTION_EDIT) { - return { ...action.info, label: 'data_grid_table_editing_open_inline_editor', icon: 'edit' }; - } - - return action.info; - }, + getActionInfo: this.getActionInfo.bind(this), handler(context, action) { const model = context.get(DATA_CONTEXT_DV_DDM)!; const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!; @@ -188,4 +187,20 @@ export class DataGridContextMenuCellEditingService { }, }); } + + private getActionInfo(context: IDataContextProvider, action: IAction) { + const t = this.localizationService.translate; + if (action === ACTION_DATA_GRID_EDITING_ADD_ROW) { + return { ...action.info, label: 'data_grid_table_editing_row_add', tooltip: t('data_grid_table_editing_row_add') + ' (' + getBindingLabel(KEY_BINDING_ADD) + ')' }; + } + if (action === ACTION_DATA_GRID_EDITING_DUPLICATE_ROW) { + return { ...action.info, label: 'data_grid_table_editing_row_add_copy', tooltip: t('data_grid_table_editing_row_add_copy') + ' (' + getBindingLabel(KEY_BINDING_DUPLICATE) + ')' }; + } + + if (action === ACTION_EDIT) { + return { ...action.info, label: t('data_grid_table_editing_open_inline_editor'), icon: 'edit' }; + } + + return action.info; + } } diff --git a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts index 35a9da483b..70118919f2 100644 --- a/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts +++ b/webapp/packages/plugin-data-viewer/src/TableViewer/TableFooter/TableFooterMenu/TableFooterMenuService.ts @@ -14,8 +14,14 @@ import { ACTION_REVERT, ACTION_SAVE, ActionService, + getBindingLabel, + KEY_BINDING_ADD, + KEY_BINDING_DUPLICATE, MenuService, + type IAction, } from '@cloudbeaver/core-view'; +import { LocalizationService } from '@cloudbeaver/core-localization'; +import type { IDataContextProvider } from '@cloudbeaver/core-data-context'; import { DatabaseEditAction } from '../../../DatabaseDataModel/Actions/DatabaseEditAction.js'; import { DatabaseSelectAction } from '../../../DatabaseDataModel/Actions/DatabaseSelectAction.js'; @@ -26,14 +32,15 @@ import { DATA_CONTEXT_DV_PRESENTATION, DataViewerPresentationType } from '../../ import type { IDatabaseDataModel } from '../../../DatabaseDataModel/IDatabaseDataModel.js'; import { DATA_VIEWER_DATA_MODEL_ACTIONS_MENU } from './DATA_VIEWER_DATA_MODEL_ACTIONS_MENU.js'; -@injectable(() => [ActionService, MenuService]) +@injectable(() => [ActionService, LocalizationService, MenuService]) export class TableFooterMenuService { constructor( private readonly actionService: ActionService, + private readonly localizationService: LocalizationService, private readonly menuService: MenuService, - ) {} + ) { } - register() { + register(): void { this.registerEditingActions(); } @@ -144,63 +151,69 @@ export class TableFooterMenuService { return false; }, - getActionInfo(context, action) { - switch (action) { - case ACTION_ADD: - return { ...action.info, label: '', icon: '/icons/data_add_sm.svg', tooltip: 'data_viewer_action_edit_add' }; - case ACTION_DUPLICATE: - return { ...action.info, label: '', icon: '/icons/data_add_copy_sm.svg', tooltip: 'data_viewer_action_edit_add_copy' }; - case ACTION_DELETE: - return { ...action.info, label: '', icon: '/icons/data_delete_sm.svg', tooltip: 'data_viewer_action_edit_delete' }; - case ACTION_REVERT: - return { ...action.info, label: '', icon: '/icons/data_revert_sm.svg', tooltip: 'data_viewer_action_edit_revert' }; - case ACTION_SAVE: - return { ...action.info, icon: 'table-save' }; - case ACTION_CANCEL: - return { ...action.info, icon: '/icons/data_revert_all_sm.svg', tooltip: 'data_viewer_value_revert_title' }; - } - - return action.info; - }, - handler: (context, action) => { - const model = context.get(DATA_CONTEXT_DV_DDM)!; - const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!; - const editor = model.source.getActionImplementation(resultIndex, DatabaseEditAction); - - if (!editor) { - return; - } - const select = model.source.getActionImplementation(resultIndex, DatabaseSelectAction); - const selectedElements = getActiveElements(model, resultIndex); - - switch (action) { - case ACTION_ADD: { - editor.add(select?.getFocusedElement()); - break; - } - case ACTION_DUPLICATE: { - editor.duplicate(...selectedElements); - break; - } - case ACTION_DELETE: { - editor.delete(...selectedElements); - break; - } - case ACTION_REVERT: { - editor.revert(...selectedElements); - break; - } - case ACTION_SAVE: - model.save().catch(() => {}); - break; - case ACTION_CANCEL: { - editor.clear(); - break; - } - } - }, + getActionInfo: this.tableFooterMenuGetActionInfo.bind(this), + handler: this.tableFooterMenuActionHandler.bind(this), }); } + + private tableFooterMenuActionHandler(context: IDataContextProvider, action: IAction) { + const model = context.get(DATA_CONTEXT_DV_DDM)!; + const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!; + const editor = model.source.getActionImplementation(resultIndex, DatabaseEditAction); + + if (!editor) { + return; + } + const select = model.source.getActionImplementation(resultIndex, DatabaseSelectAction); + const selectedElements = getActiveElements(model, resultIndex); + + switch (action) { + case ACTION_ADD: { + editor.add(select?.getFocusedElement()); + break; + } + case ACTION_DUPLICATE: { + editor.duplicate(...selectedElements); + break; + } + case ACTION_DELETE: { + editor.delete(...selectedElements); + break; + } + case ACTION_REVERT: { + editor.revert(...selectedElements); + break; + } + case ACTION_SAVE: + model.save().catch(() => { }); + break; + case ACTION_CANCEL: { + editor.clear(); + break; + } + } + + } + + private tableFooterMenuGetActionInfo(context: IDataContextProvider, action: IAction) { + const t = this.localizationService.translate; + switch (action) { + case ACTION_ADD: + return { ...action.info, label: '', icon: '/icons/data_add_sm.svg', tooltip: t('data_viewer_action_edit_add') + ' (' + getBindingLabel(KEY_BINDING_ADD) + ')' }; + case ACTION_DUPLICATE: + return { ...action.info, label: '', icon: '/icons/data_add_copy_sm.svg', tooltip: t('data_viewer_action_edit_add_copy') + ' (' + getBindingLabel(KEY_BINDING_DUPLICATE) + ')' }; + case ACTION_DELETE: + return { ...action.info, label: '', icon: '/icons/data_delete_sm.svg', tooltip: t('data_viewer_action_edit_delete') }; + case ACTION_REVERT: + return { ...action.info, label: '', icon: '/icons/data_revert_sm.svg', tooltip: t('data_viewer_action_edit_revert') }; + case ACTION_SAVE: + return { ...action.info, icon: 'table-save' }; + case ACTION_CANCEL: + return { ...action.info, icon: '/icons/data_revert_all_sm.svg', tooltip: t('data_viewer_value_revert_title') }; + } + + return action.info; + } } function getActiveElements(model: IDatabaseDataModel, resultIndex: number): unknown[] { diff --git a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/ElementsTreeToolsMenuService.ts b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/ElementsTreeToolsMenuService.ts index e317a92172..e743cfb3f2 100644 --- a/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/ElementsTreeToolsMenuService.ts +++ b/webapp/packages/plugin-navigation-tree/src/NavigationTree/ElementsTree/ElementsTreeTools/ElementsTreeToolsMenuService.ts @@ -8,12 +8,10 @@ import { UserDataService } from '@cloudbeaver/core-authentication'; import type { IDataContextProvider } from '@cloudbeaver/core-data-context'; import { injectable } from '@cloudbeaver/core-di'; -import { LocalizationService } from '@cloudbeaver/core-localization'; import { ACTION_COLLAPSE_ALL, ACTION_FILTER, ActionService, - getBindingLabel, type IAction, KeyBindingService, MenuService, @@ -27,15 +25,14 @@ import { createElementsTreeSettings, validateElementsTreeSettings } from './Navi import { DATA_CONTEXT_NAV_TREE_ROOT } from './NavigationTreeSettings/DATA_CONTEXT_NAV_TREE_ROOT.js'; import { KEY_BINDING_ENABLE_FILTER } from './NavigationTreeSettings/KEY_BINDING_ENABLE_FILTER.js'; -@injectable(() => [ActionService, KeyBindingService, UserDataService, MenuService, LocalizationService]) +@injectable(() => [ActionService, KeyBindingService, UserDataService, MenuService]) export class ElementsTreeToolsMenuService { constructor( private readonly actionService: ActionService, private readonly keyBindingService: KeyBindingService, private readonly userDataService: UserDataService, private readonly menuService: MenuService, - private readonly localizationService: LocalizationService, - ) {} + ) { } register() { this.actionService.addHandler({ @@ -53,20 +50,6 @@ export class ElementsTreeToolsMenuService { return false; }, - getActionInfo: (context, action) => { - switch (action) { - case ACTION_COLLAPSE_ALL: { - const bindingLabel = getBindingLabel(KEY_BINDING_COLLAPSE_ALL); - const tooltip = this.localizationService.translate('app_navigationTree_action_collapse_all') + (bindingLabel ? ` (${bindingLabel})` : ''); - return { - ...action.info, - tooltip, - }; - } - } - - return action.info; - }, handler: this.elementsTreeActionHandler.bind(this), }); @@ -135,7 +118,7 @@ export class ElementsTreeToolsMenuService { state.filter = !state.filter; } - private async elementsTreeActionHandler(contexts: IDataContextProvider, action: IAction) { + private elementsTreeActionHandler(contexts: IDataContextProvider, action: IAction) { const tree = contexts.get(DATA_CONTEXT_ELEMENTS_TREE); if (tree === undefined) { diff --git a/webapp/packages/plugin-object-viewer-nav-tree-link/src/ACTION_LINK_OBJECT.ts b/webapp/packages/plugin-object-viewer-nav-tree-link/src/ACTION_LINK_OBJECT.ts index ffe62794f1..04f52ab91c 100644 --- a/webapp/packages/plugin-object-viewer-nav-tree-link/src/ACTION_LINK_OBJECT.ts +++ b/webapp/packages/plugin-object-viewer-nav-tree-link/src/ACTION_LINK_OBJECT.ts @@ -8,6 +8,6 @@ import { createAction } from '@cloudbeaver/core-view'; export const ACTION_LINK_OBJECT = createAction('link-object', { - label: 'link-object', + label: 'app_navigationTree_action_link_with_editor', icon: '/icons/reveal_in_explorer_view_sm.svg', }); diff --git a/webapp/packages/plugin-object-viewer-nav-tree-link/src/ObjectViewerNavTreeLinkMenuService.ts b/webapp/packages/plugin-object-viewer-nav-tree-link/src/ObjectViewerNavTreeLinkMenuService.ts index c95cb28102..2606bb4038 100644 --- a/webapp/packages/plugin-object-viewer-nav-tree-link/src/ObjectViewerNavTreeLinkMenuService.ts +++ b/webapp/packages/plugin-object-viewer-nav-tree-link/src/ObjectViewerNavTreeLinkMenuService.ts @@ -8,14 +8,13 @@ import type { IDataContextProvider } from '@cloudbeaver/core-data-context'; import { NavigationTreeService, DATA_CONTEXT_ELEMENTS_TREE, MENU_ELEMENTS_TREE_TOOLS } from '@cloudbeaver/plugin-navigation-tree'; import { Bootstrap, injectable } from '@cloudbeaver/core-di'; -import { LocalizationService } from '@cloudbeaver/core-localization'; -import { ActionService, getBindingLabel, type IAction, KeyBindingService, MenuService } from '@cloudbeaver/core-view'; +import { ActionService, type IAction, KeyBindingService, MenuService } from '@cloudbeaver/core-view'; import { ConnectionSchemaManagerService } from '@cloudbeaver/plugin-datasource-context-switch'; import { ACTION_LINK_OBJECT } from './ACTION_LINK_OBJECT.js'; import { KEY_BINDING_LINK_OBJECT } from './KEY_BINDING_LINK_OBJECT.js'; -@injectable(() => [ActionService, KeyBindingService, NavigationTreeService, ConnectionSchemaManagerService, MenuService, LocalizationService]) +@injectable(() => [ActionService, KeyBindingService, NavigationTreeService, ConnectionSchemaManagerService, MenuService]) export class ObjectViewerNavTreeLinkMenuService extends Bootstrap { constructor( private readonly actionService: ActionService, @@ -23,7 +22,6 @@ export class ObjectViewerNavTreeLinkMenuService extends Bootstrap { private readonly navigationTreeService: NavigationTreeService, private readonly connectionSchemaManagerService: ConnectionSchemaManagerService, private readonly menuService: MenuService, - private readonly localizationService: LocalizationService, ) { super(); } @@ -35,21 +33,6 @@ export class ObjectViewerNavTreeLinkMenuService extends Bootstrap { id: 'object-viewer-nav-tree-link-handler', contexts: [DATA_CONTEXT_ELEMENTS_TREE], actions: [ACTION_LINK_OBJECT], - getActionInfo: (context, action) => { - switch (action) { - case ACTION_LINK_OBJECT: { - const bindingLabel = getBindingLabel(KEY_BINDING_LINK_OBJECT); - const tooltip = - this.localizationService.translate('app_navigationTree_action_link_with_editor') + (bindingLabel ? ` (${bindingLabel})` : ''); - return { - ...action.info, - tooltip, - }; - } - } - - return action.info; - }, isHidden: context => { const tree = context.get(DATA_CONTEXT_ELEMENTS_TREE)!; diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/en.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/en.ts index 6835ae8e09..f324c2c930 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/en.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/en.ts @@ -1,5 +1,5 @@ export default [ - ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Save as script (Shift + Ctrl + S)'], + ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Save as script'], ['plugin_sql_editor_navigation_tab_script_state_renaming', 'Renaming script...'], ['plugin_sql_editor_navigation_tab_script_state_reading', 'Reading script...'], ['plugin_sql_editor_navigation_tab_script_state_saving', 'Saving script...'], diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/fr.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/fr.ts index fd1dc67b5f..8fe06ed6a7 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/fr.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/fr.ts @@ -1,5 +1,5 @@ export default [ - ['plugin_sql_editor_navigation_tab_resource_save_title', 'Enregistrer comme script (Shift + Ctrl + S)'], + ['plugin_sql_editor_navigation_tab_resource_save_title', 'Enregistrer comme script'], ['plugin_sql_editor_navigation_tab_script_state_renaming', 'Renommer le script...'], ['plugin_sql_editor_navigation_tab_script_state_reading', 'Lecture du script...'], ['plugin_sql_editor_navigation_tab_script_state_saving', 'Enregistrement du script...'], diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/it.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/it.ts index 6835ae8e09..f324c2c930 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/it.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/it.ts @@ -1,5 +1,5 @@ export default [ - ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Save as script (Shift + Ctrl + S)'], + ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Save as script'], ['plugin_sql_editor_navigation_tab_script_state_renaming', 'Renaming script...'], ['plugin_sql_editor_navigation_tab_script_state_reading', 'Reading script...'], ['plugin_sql_editor_navigation_tab_script_state_saving', 'Saving script...'], diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/ru.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/ru.ts index 75155e4307..5527769668 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/ru.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/ru.ts @@ -1,5 +1,5 @@ export default [ - ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Сохранить как скрипт (Shift + Ctrl + S)'], + ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Сохранить как скрипт'], ['plugin_sql_editor_navigation_tab_script_state_renaming', 'Переименовывание скрипта...'], ['plugin_sql_editor_navigation_tab_script_state_reading', 'Чтение скрипта...'], ['plugin_sql_editor_navigation_tab_script_state_saving', 'Сохранение скрипта...'], diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/vi.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/vi.ts index 2559ab6575..51ee8e4c1e 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/vi.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/vi.ts @@ -1,5 +1,5 @@ export default [ - ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Lưu dưới dạng script (Shift + Ctrl + S)'], + ['plugin_sql_editor_navigation_tab_resource_save_script_title', 'Lưu dưới dạng script'], ['plugin_sql_editor_navigation_tab_script_state_renaming', 'Đang đổi tên script...'], ['plugin_sql_editor_navigation_tab_script_state_reading', 'Đang đọc script...'], ['plugin_sql_editor_navigation_tab_script_state_saving', 'Đang lưu script...'], diff --git a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/zh.ts b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/zh.ts index d1c4a654cc..50e1d6720f 100644 --- a/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/zh.ts +++ b/webapp/packages/plugin-sql-editor-navigation-tab-script/src/locales/zh.ts @@ -1,5 +1,5 @@ export default [ - ['plugin_sql_editor_navigation_tab_resource_save_script_title', '保存为脚本 (Shift + Ctrl + S)'], + ['plugin_sql_editor_navigation_tab_resource_save_script_title', '保存为脚本'], ['plugin_sql_editor_navigation_tab_script_state_renaming', '重命名脚本中...'], ['plugin_sql_editor_navigation_tab_script_state_reading', '读取脚本中...'], ['plugin_sql_editor_navigation_tab_script_state_saving', '保存脚本中...'], diff --git a/webapp/packages/plugin-sql-editor/src/MenuBootstrap.ts b/webapp/packages/plugin-sql-editor/src/MenuBootstrap.ts index 38b7fa4810..8db3a7f483 100644 --- a/webapp/packages/plugin-sql-editor/src/MenuBootstrap.ts +++ b/webapp/packages/plugin-sql-editor/src/MenuBootstrap.ts @@ -46,6 +46,7 @@ import { SqlDataSourceService } from './SqlDataSource/SqlDataSourceService.js'; import { DATA_CONTEXT_SQL_EDITOR_DATA } from './SqlEditor/DATA_CONTEXT_SQL_EDITOR_DATA.js'; import { SQL_EDITOR_TOOLS_MENU } from './SqlEditor/SQL_EDITOR_TOOLS_MENU.js'; import { SQL_EDITOR_TOOLS_MORE_MENU } from './SqlEditor/SQL_EDITOR_TOOLS_MORE_MENU.js'; +import { SQL_EDITOR_ACTIONS_MENU } from './SqlEditor/SQL_EDITOR_ACTIONS_MENU.js'; import { getSqlEditorName } from './getSqlEditorName.js'; import type { ISqlEditorTabState } from './ISqlEditorTabState.js'; import { SqlEditorSettingsService } from './SqlEditorSettingsService.js'; @@ -53,6 +54,12 @@ import { SqlEditorSettingsService } from './SqlEditorSettingsService.js'; const SYNC_DELAY = 5 * 60 * 1000; const ScriptImportDialog = importLazyComponent(() => import('./SqlEditor/ScriptImportDialog.js').then(m => m.ScriptImportDialog)); +const EXECUTIONS_ACTIONS = [ + ACTION_SQL_EDITOR_EXECUTE, + ACTION_SQL_EDITOR_EXECUTE_NEW, + ACTION_SQL_EDITOR_EXECUTE_SCRIPT, + ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN, +]; @injectable(() => [ MenuService, @@ -207,6 +214,15 @@ export class MenuBootstrap extends Bootstrap { getItems: (context, items) => [...items, ACTION_SAVE], }); + this.menuService.addCreator({ + menus: [SQL_EDITOR_ACTIONS_MENU], + contexts: [DATA_CONTEXT_SQL_EDITOR_DATA, DATA_CONTEXT_SQL_EDITOR_STATE], + getItems: (context, items) => [ + ...items, + ...EXECUTIONS_ACTIONS, + ], + }); + this.keyBindingService.addKeyBindingHandler({ id: 'sql-editor-save', binding: KEY_BINDING_SAVE, @@ -227,13 +243,10 @@ export class MenuBootstrap extends Bootstrap { this.actionService.addHandler({ id: 'sql-editor-actions', actions: [ - ACTION_SQL_EDITOR_EXECUTE, - ACTION_SQL_EDITOR_EXECUTE_NEW, - ACTION_SQL_EDITOR_EXECUTE_SCRIPT, + ...EXECUTIONS_ACTIONS, ACTION_SQL_EDITOR_FORMAT, ACTION_REDO, ACTION_UNDO, - ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN, ], contexts: [DATA_CONTEXT_SQL_EDITOR_DATA], isActionApplicable: (contexts, action): boolean => { @@ -245,12 +258,7 @@ export class MenuBootstrap extends Bootstrap { if ( !sqlEditorData.isExecutionAllowed && - [ - ACTION_SQL_EDITOR_EXECUTE, - ACTION_SQL_EDITOR_EXECUTE_NEW, - ACTION_SQL_EDITOR_EXECUTE_SCRIPT, - ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN, - ].includes(action) + EXECUTIONS_ACTIONS.includes(action) ) { return false; } @@ -259,6 +267,11 @@ export class MenuBootstrap extends Bootstrap { return !!sqlEditorData.dataSource?.hasFeature(ESqlDataSourceFeatures.script) && !sqlEditorData.activeSegmentMode.activeSegmentMode; } + if (action === ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN) { + return !!sqlEditorData.dataSource?.hasFeature(ESqlDataSourceFeatures.query) && + !!sqlEditorData.dialect?.supportsExplainExecutionPlan; + } + // TODO we have to add check for output action ? if ( !sqlEditorData.dataSource?.hasFeature(ESqlDataSourceFeatures.query) && @@ -271,6 +284,11 @@ export class MenuBootstrap extends Bootstrap { }, isDisabled: (context, action) => { const data = context.get(DATA_CONTEXT_SQL_EDITOR_DATA)!; + + if (EXECUTIONS_ACTIONS.includes(action)) { + return data.isDisabled || data.isScriptEmpty; + } + switch (action) { case ACTION_SQL_EDITOR_FORMAT: return data.isDisabled || data.isScriptEmpty || data.readonly; @@ -278,6 +296,15 @@ export class MenuBootstrap extends Bootstrap { return false; }, + getActionInfo: (context, action) => { + if (EXECUTIONS_ACTIONS.includes(action)) { + return { + ...action.info, + label: '', + }; + } + return action.info; + }, handler: this.sqlEditorActionHandler.bind(this), }); diff --git a/webapp/packages/plugin-sql-editor/src/SqlEditor/SQLEditorActions.tsx b/webapp/packages/plugin-sql-editor/src/SqlEditor/SQLEditorActions.tsx index d850bda01d..df5ed9bef4 100644 --- a/webapp/packages/plugin-sql-editor/src/SqlEditor/SQLEditorActions.tsx +++ b/webapp/packages/plugin-sql-editor/src/SqlEditor/SQLEditorActions.tsx @@ -7,14 +7,18 @@ */ import { observer } from 'mobx-react-lite'; -import { ActionIconButton, getComputed, preventFocusHandler, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import { preventFocusHandler, s, useS } from '@cloudbeaver/core-blocks'; +import { useDataContextLink } from '@cloudbeaver/core-data-context'; +import { useMenu } from '@cloudbeaver/core-view'; import type { ISqlEditorTabState } from '../ISqlEditorTabState.js'; -import { ESqlDataSourceFeatures } from '../SqlDataSource/ESqlDataSourceFeatures.js'; +import { DATA_CONTEXT_SQL_EDITOR_DATA } from './DATA_CONTEXT_SQL_EDITOR_DATA.js'; +import { DATA_CONTEXT_SQL_EDITOR_STATE } from '../DATA_CONTEXT_SQL_EDITOR_STATE.js'; import type { ISQLEditorData } from './ISQLEditorData.js'; import style from './SQLEditorActions.module.css'; import { SqlEditorActionsMenu } from './SqlEditorActionsMenu.js'; import { SqlEditorTools } from './SqlEditorTools.js'; +import { SQL_EDITOR_ACTIONS_MENU } from './SQL_EDITOR_ACTIONS_MENU.js'; interface Props { data: ISQLEditorData; @@ -22,58 +26,21 @@ interface Props { className?: string; } -export const SQLEditorActions = observer(function SQLEditorActions({ data, state }) { +export const SQLEditorActions = observer(function SQLEditorActions({ data, state, className }) { const styles = useS(style); - const translate = useTranslate(); - const isActiveSegmentMode = getComputed(() => data.activeSegmentMode.activeSegmentMode); - const disabled = getComputed(() => data.isScriptEmpty || data.isDisabled); - const isQuery = data.dataSource?.hasFeature(ESqlDataSourceFeatures.query); - const isExecutable = data.isExecutionAllowed; + const menu = useMenu({ menu: SQL_EDITOR_ACTIONS_MENU }); + + useDataContextLink(menu.context, (context, id) => { + context.set(DATA_CONTEXT_SQL_EDITOR_STATE, state, id); + }); + useDataContextLink(menu.context, (context, id) => { + context.set(DATA_CONTEXT_SQL_EDITOR_DATA, data, id); + }); return ( -
+
- {isExecutable && ( - <> - {isQuery && ( - <> - - - - )} -
diff --git a/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE.ts b/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE.ts index 405a2e7332..83df49609c 100644 --- a/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE.ts +++ b/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -10,4 +10,5 @@ import { createAction } from '@cloudbeaver/core-view'; export const ACTION_SQL_EDITOR_EXECUTE = createAction('sql-editor-execute', { icon: '/icons/sql_exec.svg', label: 'sql_editor_sql_execution_button_tooltip', + tooltip: 'sql_editor_sql_execution_button_tooltip', }); diff --git a/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE_NEW.ts b/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE_NEW.ts index 0798132271..3d6980b271 100644 --- a/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE_NEW.ts +++ b/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_EXECUTE_NEW.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -10,4 +10,5 @@ import { createAction } from '@cloudbeaver/core-view'; export const ACTION_SQL_EDITOR_EXECUTE_NEW = createAction('sql-editor-execute-new', { icon: '/icons/sql_exec_new.svg', label: 'sql_editor_sql_execution_new_tab_button_tooltip', + tooltip: 'sql_editor_sql_execution_new_tab_button_tooltip', }); diff --git a/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN.ts b/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN.ts index 229e9db1b6..275f726f1c 100644 --- a/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN.ts +++ b/webapp/packages/plugin-sql-editor/src/actions/ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2025 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -10,4 +10,5 @@ import { createAction } from '@cloudbeaver/core-view'; export const ACTION_SQL_EDITOR_SHOW_EXECUTION_PLAN = createAction('sql-editor-show-execution-plan', { icon: '/icons/sql_execution_plan.svg', label: 'sql_editor_execution_plan_button_tooltip', + tooltip: 'sql_editor_execution_plan_button_tooltip', }); diff --git a/webapp/packages/plugin-sql-editor/src/locales/en.ts b/webapp/packages/plugin-sql-editor/src/locales/en.ts index 209e66319b..68bd1d9f77 100644 --- a/webapp/packages/plugin-sql-editor/src/locales/en.ts +++ b/webapp/packages/plugin-sql-editor/src/locales/en.ts @@ -14,15 +14,15 @@ export default [ ['sql_editor_placeholder', 'Execute query with Ctrl+Enter to see results'], ['sql_editor_hint_empty', 'There is no proposals...'], ['sql_editor_tools_more_menu_tooltip', 'More tools'], - ['sql_editor_execution_plan_button_tooltip', 'Explain execution plan (Shift + Ctrl + E)'], - ['sql_editor_output_logs_button_tooltip', 'Show server output (Shift + Ctrl + O)'], + ['sql_editor_execution_plan_button_tooltip', 'Explain execution plan'], + ['sql_editor_output_logs_button_tooltip', 'Show server output'], ['sql_editor_output_logs_tab_title', 'Output'], ['sql_editor_output_logs_input_placeholder', 'Enter a part of a message to search for here'], ['sql_editor_output_logs_wrap_mode', 'Wrap mode'], - ['sql_editor_sql_execution_button_tooltip', 'Execute SQL Statement (Ctrl + Enter)'], - ['sql_editor_sql_execution_new_tab_button_tooltip', 'Execute SQL Statement in new tab (Ctrl + \\)(Shift + Ctrl + Enter)'], - ['sql_editor_sql_execution_script_button_tooltip', 'Execute SQL Script (Alt + X)'], - ['sql_editor_sql_format_button_tooltip', 'Format SQL Script (Shift + Ctrl + F)'], + ['sql_editor_sql_execution_button_tooltip', 'Execute SQL Statement'], + ['sql_editor_sql_execution_new_tab_button_tooltip', 'Execute SQL Statement in new tab'], + ['sql_editor_sql_execution_script_button_tooltip', 'Execute SQL Script'], + ['sql_editor_sql_format_button_tooltip', 'Format SQL Script'], ['sql_editor_sql_execution_script_lock_tooltip', 'Lock editor to prevent modifications'], ['sql_editor_sql_statistics_unavailable', 'Statistics is not available'], ['sql_editor_sql_execution_executed_queries', 'Executed queries:'], diff --git a/webapp/packages/plugin-sql-editor/src/locales/fr.ts b/webapp/packages/plugin-sql-editor/src/locales/fr.ts index 6c64b227f8..1b8d19bb8d 100644 --- a/webapp/packages/plugin-sql-editor/src/locales/fr.ts +++ b/webapp/packages/plugin-sql-editor/src/locales/fr.ts @@ -13,21 +13,21 @@ export default [ ['sql_editor_placeholder', 'Exécuter une requête (appuyez sur Ctrl+Entrée pour voir les résultats)'], ['sql_editor_hint_empty', "Il n'y a aucune proposition..."], ['sql_editor_tools_more_menu_tooltip', "Plus d'outils"], - ['sql_editor_execution_plan_button', "Afficher le plan d'exécution (Shift + Ctrl + E)"], - ['sql_editor_output_logs_button_tooltip', 'Afficher la sortie du serveur (Shift + Ctrl + O)'], + ['sql_editor_execution_plan_button', "Afficher le plan d'exécution"], + ['sql_editor_output_logs_button_tooltip', 'Afficher la sortie du serveur'], ['sql_editor_output_logs_tab_title', 'Journaux'], ['sql_editor_output_logs_hint', 'Aucun message du serveur'], ['sql_editor_output_logs_wrap_mode', 'Mode Wrap'], - ['sql_editor_execution_plan_button_tooltip', "Afficher le plan d'exécution (Shift + Ctrl + E)"], + ['sql_editor_execution_plan_button_tooltip', "Afficher le plan d'exécution"], ['sql_editor_execution_plan_button', "Afficher le plan d'exécution"], - ['sql_editor_execution_script_button_tooltip', 'Exécuter le script SQL (Alt + X)'], + ['sql_editor_execution_script_button_tooltip', 'Exécuter le script SQL'], ['sql_editor_execution_script_button', 'Exécuter le script SQL'], - ['sql_editor_execution_query_button_tooltip', 'Exécuter la déclaration SQL (Ctrl + Entrée)'], + ['sql_editor_execution_query_button_tooltip', 'Exécuter la déclaration SQL'], ['sql_editor_execution_query_button', 'Exécuter la déclaration SQL'], - ['sql_editor_execution_query_new_tab_button_tooltip', 'Exécuter la déclaration SQL dans un nouvel onglet (Ctrl + \\)(Shift + Ctrl + Entrée)'], + ['sql_editor_execution_query_new_tab_button_tooltip', 'Exécuter la déclaration SQL dans un nouvel onglet'], ['sql_editor_execution_query_new_tab_button', 'Exécuter dans un nouvel onglet'], ['sql_editor_execution_query_tooltip', 'Exécuter les requêtes'], - ['sql_editor_lock_button_tooltip', "Verrouiller l'éditeur pour éviter les modifications (Shift + Ctrl + F)"], + ['sql_editor_lock_button_tooltip', "Verrouiller l'éditeur pour éviter les modifications"], ['sql_editor_lock_button', "Verrouiller l'éditeur"], ['sql_editor_sql_statistics_unavailable', 'Les statistiques SQL ne sont pas disponibles'], ['sql_editor_queries_tab_title', 'Requêtes exécutées'], diff --git a/webapp/packages/plugin-sql-editor/src/locales/it.ts b/webapp/packages/plugin-sql-editor/src/locales/it.ts index a4c964ff40..3b91328921 100644 --- a/webapp/packages/plugin-sql-editor/src/locales/it.ts +++ b/webapp/packages/plugin-sql-editor/src/locales/it.ts @@ -14,15 +14,15 @@ export default [ ['sql_editor_placeholder', 'Esegui la query con Ctrl+Enter per vedere i risultati'], ['sql_editor_hint_empty', 'There is no proposals...'], ['sql_editor_tools_more_menu_tooltip', 'Più strumenti'], - ['sql_editor_execution_plan_button_tooltip', 'Mostra il piano di esecuzione (Shift + Ctrl + E)'], - ['sql_editor_output_logs_button_tooltip', 'Show server output (Shift + Ctrl + O)'], + ['sql_editor_execution_plan_button_tooltip', 'Mostra il piano di esecuzione'], + ['sql_editor_output_logs_button_tooltip', 'Show server output'], ['sql_editor_output_logs_tab_title', 'Output'], ['sql_editor_output_logs_input_placeholder', 'Enter a part of a message to search for here'], ['sql_editor_output_logs_wrap_mode', 'Wrap mode'], - ['sql_editor_sql_execution_button_tooltip', "Esegui l'istruzione SQL (Ctrl + Enter)"], - ['sql_editor_sql_execution_new_tab_button_tooltip', "Esegui l'istruzione SQL in una nuova tab (Ctrl + \\)(Shift + Ctrl + Enter)"], - ['sql_editor_sql_execution_script_button_tooltip', 'Esegui lo script SQL (Alt + X)'], - ['sql_editor_sql_format_button_tooltip', 'Format SQL Script (Shift + Ctrl + F)'], + ['sql_editor_sql_execution_button_tooltip', "Esegui l'istruzione SQL"], + ['sql_editor_sql_execution_new_tab_button_tooltip', "Esegui l'istruzione SQL in una nuova tab"], + ['sql_editor_sql_execution_script_button_tooltip', 'Esegui lo script SQL'], + ['sql_editor_sql_format_button_tooltip', 'Format SQL Script'], ['sql_editor_sql_execution_script_lock_tooltip', 'Lock editor to prevent modifications'], ['sql_editor_sql_statistics_unavailable', 'Statistiche non disponibili'], ['sql_editor_sql_execution_executed_queries', 'Executed queries:'], diff --git a/webapp/packages/plugin-sql-editor/src/locales/ru.ts b/webapp/packages/plugin-sql-editor/src/locales/ru.ts index 4f4e3f13e7..707c0442c3 100644 --- a/webapp/packages/plugin-sql-editor/src/locales/ru.ts +++ b/webapp/packages/plugin-sql-editor/src/locales/ru.ts @@ -14,15 +14,15 @@ export default [ ['sql_editor_placeholder', 'Нажмите Ctrl+Enter, чтобы выполнить запрос и увидеть результат'], ['sql_editor_hint_empty', 'Нет авто-дополнений...'], ['sql_editor_tools_more_menu_tooltip', 'Больше инструментов'], - ['sql_editor_execution_plan_button_tooltip', 'Посмотреть информацию о плане выполнения запроса (Shift + Ctrl + E)'], - ['sql_editor_output_logs_button_tooltip', 'Показать вывод сервера (Shift + Ctrl + O)'], + ['sql_editor_execution_plan_button_tooltip', 'Посмотреть информацию о плане выполнения запроса'], + ['sql_editor_output_logs_button_tooltip', 'Показать вывод сервера'], ['sql_editor_output_logs_tab_title', 'Вывод логов'], ['sql_editor_output_logs_input_placeholder', 'Введите часть сообщения для поиска'], ['sql_editor_output_logs_wrap_mode', 'Перенос строк'], - ['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_execution_button_tooltip', 'Выполнить SQL Выражение'], + ['sql_editor_sql_execution_new_tab_button_tooltip', 'Выполнить SQL Выражение в новой вкладке'], + ['sql_editor_sql_execution_script_button_tooltip', 'Исполнить SQL Скрипт'], + ['sql_editor_sql_format_button_tooltip', 'Форматировать SQL скрипт'], ['sql_editor_sql_execution_script_lock_tooltip', 'Заблокировать скрипт во избежание изменений'], ['sql_editor_sql_statistics_unavailable', 'Статистика не доступна'], ['sql_editor_sql_execution_executed_queries', 'Выполненные запросы:'], diff --git a/webapp/packages/plugin-sql-editor/src/locales/vi.ts b/webapp/packages/plugin-sql-editor/src/locales/vi.ts index ec346b91b0..5285a40865 100644 --- a/webapp/packages/plugin-sql-editor/src/locales/vi.ts +++ b/webapp/packages/plugin-sql-editor/src/locales/vi.ts @@ -14,15 +14,15 @@ export default [ ['sql_editor_placeholder', 'Thực thi truy vấn với Ctrl+Enter để xem kết quả'], ['sql_editor_hint_empty', 'Không có đề xuất nào...'], ['sql_editor_tools_more_menu_tooltip', 'Nhiều công cụ hơn'], - ['sql_editor_execution_plan_button_tooltip', 'Giải thích kế hoạch thực thi (Shift + Ctrl + E)'], - ['sql_editor_output_logs_button_tooltip', 'Hiển thị đầu ra máy chủ (Shift + Ctrl + O)'], + ['sql_editor_execution_plan_button_tooltip', 'Giải thích kế hoạch thực thi'], + ['sql_editor_output_logs_button_tooltip', 'Hiển thị đầu ra máy chủ'], ['sql_editor_output_logs_tab_title', 'Đầu ra'], ['sql_editor_output_logs_input_placeholder', 'Nhập một phần của tin nhắn để tìm kiếm tại đây'], ['sql_editor_output_logs_wrap_mode', 'Chế độ wrap'], - ['sql_editor_sql_execution_button_tooltip', 'Thực thi câu lệnh SQL (Ctrl + Enter)'], - ['sql_editor_sql_execution_new_tab_button_tooltip', 'Thực thi câu lệnh SQL trong tab mới (Ctrl + \\)(Shift + Ctrl + Enter)'], - ['sql_editor_sql_execution_script_button_tooltip', 'Thực thi kịch bản SQL (Alt + X)'], - ['sql_editor_sql_format_button_tooltip', 'Định dạng kịch bản SQL (Shift + Ctrl + F)'], + ['sql_editor_sql_execution_button_tooltip', 'Thực thi câu lệnh SQL'], + ['sql_editor_sql_execution_new_tab_button_tooltip', 'Thực thi câu lệnh SQL trong tab mới'], + ['sql_editor_sql_execution_script_button_tooltip', 'Thực thi kịch bản SQL'], + ['sql_editor_sql_format_button_tooltip', 'Định dạng kịch bản SQL'], ['sql_editor_sql_execution_script_lock_tooltip', 'Khóa trình soạn thảo để ngăn sửa đổi'], ['sql_editor_sql_statistics_unavailable', 'Thống kê không khả dụng'], ['sql_editor_sql_execution_executed_queries', 'Các truy vấn đã thực thi:'], diff --git a/webapp/packages/plugin-sql-editor/src/locales/zh.ts b/webapp/packages/plugin-sql-editor/src/locales/zh.ts index 1f25f216b3..2adb35a4f1 100644 --- a/webapp/packages/plugin-sql-editor/src/locales/zh.ts +++ b/webapp/packages/plugin-sql-editor/src/locales/zh.ts @@ -14,15 +14,15 @@ export default [ ['sql_editor_placeholder', '使用Ctrl + Enter执行查询以查看结果'], ['sql_editor_hint_empty', '无提示信息...'], ['sql_editor_tools_more_menu_tooltip', '更多工具'], - ['sql_editor_execution_plan_button_tooltip', '解释执行计划(Shift + Ctrl + E)'], - ['sql_editor_output_logs_button_tooltip', '显示服务端输出 (Shift + Ctrl + O)'], + ['sql_editor_execution_plan_button_tooltip', '解释执行计划'], + ['sql_editor_output_logs_button_tooltip', '显示服务端输出'], ['sql_editor_output_logs_tab_title', '输出'], ['sql_editor_output_logs_input_placeholder', '在此处输入要搜索的消息关键词'], ['sql_editor_output_logs_wrap_mode', '换行模式'], - ['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_execution_button_tooltip', '执行SQL语句'], + ['sql_editor_sql_execution_new_tab_button_tooltip', '在新选项卡中执行SQL语句'], + ['sql_editor_sql_execution_script_button_tooltip', '执行SQL脚本'], + ['sql_editor_sql_format_button_tooltip', '格式化SQL脚本'], ['sql_editor_sql_execution_script_lock_tooltip', '锁定编辑器阻止修改'], ['sql_editor_sql_statistics_unavailable', '统计不可用'], ['sql_editor_sql_execution_queries', '查询:'],