mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-12-23 07:34:35 -06:00
Add keyboard navigation options for the main browser windows. Fixes #2895
This commit is contained in:
parent
2042f89ce0
commit
262d01bf01
BIN
docs/en_US/images/preferences_browser_keyboard_shortcuts.png
Normal file
BIN
docs/en_US/images/preferences_browser_keyboard_shortcuts.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 KiB |
@ -3,6 +3,7 @@ Keyboard Shortcuts
|
||||
******************
|
||||
|
||||
Keyboard shortcuts are provided in pgAdmin to allow easy access to specific functions.
|
||||
The shortcuts can be configured through File > Preferences dialogue as per the need.
|
||||
|
||||
|
||||
**Desktop Runtime**
|
||||
@ -27,6 +28,27 @@ When running in the Desktop Runtime, the following keyboard shortcuts are availa
|
||||
| Ctrl+0 | Cmd+0 | Reset the zoom level |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
|
||||
**Main Browser Window**
|
||||
|
||||
When using main browser window, the following keyboard shortcuts are available:
|
||||
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
| Shortcut for all platform | Function |
|
||||
+===========================+========================================================+
|
||||
| Alt+Shift+F | Open the File menu |
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
| Alt+Shift+O | Open the Object menu |
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
| Alt+Shift+L | Open the Tools menu |
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
| Alt+Shift+H | Open the Help menu |
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
| Alt+Shift+B | Focus the browser tree |
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
| Alt+Shift+[ | Move tabbed panel backward/forward |
|
||||
| Alt+Shift+] | |
|
||||
+---------------------------+--------------------------------------------------------+
|
||||
|
||||
|
||||
**SQL Editors**
|
||||
|
||||
|
@ -20,6 +20,13 @@ Use the fields on the *Display* panel to specify general display preferences:
|
||||
|
||||
* When the *Show system objects* switch is set to *True*, the client will display system objects such as system schemas (for example, *pg_temp*) or system columns (for example, *xmin* or *ctid*) in the tree control.
|
||||
|
||||
Use the fields on the *Keyboard shortcuts* panel to configure shortcuts for the main window navigation:
|
||||
|
||||
.. image:: images/preferences_browser_keyboard_shortcuts.png
|
||||
:alt: Preferences dialog browser keyboard shortcuts section
|
||||
|
||||
* The panel displays a list of keyboard shortcuts available for the main window; select the combination of the modifier keys along with the key to configure each shortcut.
|
||||
|
||||
Use the fields on the *Nodes* panel to select the object types that will be displayed in the *Browser* tree control:
|
||||
|
||||
.. image:: images/preferences_browser_nodes.png
|
||||
|
@ -37,3 +37,4 @@ BigNumber 3.0.1 MIT http://mikemcl.github.io/bignumb
|
||||
Source Code Pro 1.1 SIL OFL https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700
|
||||
Open Sans 2.0 AL https://fonts.googleapis.com/css?family=Open+Sans:400,400i,600,700
|
||||
Spectrum 1.8 MIT https://bgrins.github.io/spectrum/
|
||||
Mousetrap 1.6.1 AL https://github.com/ccampbell/mousetrap
|
||||
|
@ -70,6 +70,7 @@
|
||||
"jquery-contextmenu": "^2.5.0",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"moment": "^2.18.1",
|
||||
"mousetrap": "^1.6.1",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "file:../web/pgadmin/static/vendor/react",
|
||||
"react-dom": "file:../web/pgadmin/static/vendor/react-dom",
|
||||
|
@ -213,7 +213,117 @@ class BrowserModule(PgAdminModule):
|
||||
gettext("Count rows if estimated less than"), 'integer', 2000,
|
||||
category_label=gettext('Properties')
|
||||
)
|
||||
fields = [
|
||||
{'name': 'alt', 'type': 'checkbox', 'label': gettext('Alt / Option')},
|
||||
{'name': 'shift', 'type': 'checkbox', 'label': gettext('Shift')},
|
||||
{'name': 'control', 'type': 'checkbox', 'label': gettext('Ctrl')},
|
||||
{'name': 'key', 'type': 'keyCode', 'label': gettext('Key')}
|
||||
]
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'browser_tree',
|
||||
gettext('Browser tree'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 66, 'char': 'b'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'tabbed_panel_backward',
|
||||
gettext('Tabbed panel backward'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 91, 'char': '['}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'tabbed_panel_forward',
|
||||
gettext('Tabbed panel forward'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 93, 'char': ']'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'main_menu_file',
|
||||
gettext('File main menu'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 70, 'char': 'f'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'main_menu_object',
|
||||
gettext('Object main menu'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 79, 'char': 'o'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'main_menu_tools',
|
||||
gettext('Tools main menu'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 76, 'char': 'l'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
|
||||
self.preference.register(
|
||||
'keyboard_shortcuts',
|
||||
'main_menu_help',
|
||||
gettext('Help main menu'),
|
||||
'keyboardshortcut',
|
||||
{
|
||||
'alt': True,
|
||||
'shift': True,
|
||||
'control': False,
|
||||
'key': {'key_code': 72, 'char': 'h'}
|
||||
},
|
||||
category_label=gettext('Keyboard shortcuts'),
|
||||
fields=fields
|
||||
)
|
||||
def get_exposed_url_endpoints(self):
|
||||
"""
|
||||
Returns:
|
||||
|
@ -8,6 +8,7 @@ define('pgadmin.browser', [
|
||||
'pgadmin.browser.error', 'pgadmin.browser.frame',
|
||||
'pgadmin.browser.node', 'pgadmin.browser.collection',
|
||||
'sources/codemirror/addon/fold/pgadmin-sqlfoldcode',
|
||||
'pgadmin.browser.keyboard',
|
||||
], function(
|
||||
gettext, url_for, require, $, _, S, Bootstrap, pgAdmin, Alertify,
|
||||
codemirror, checkNodeVisibility
|
||||
@ -544,7 +545,7 @@ define('pgadmin.browser', [
|
||||
menus[m.name] = new MenuItem({
|
||||
name: m.name, label: m.label, module: m.module,
|
||||
category: m.category, callback: m.callback,
|
||||
priority: m.priority, data: m.data, url: m.url,
|
||||
priority: m.priority, data: m.data, url: m.url || '#',
|
||||
target: m.target, icon: m.icon,
|
||||
enable: (m.enable == '' ? true : (_.isString(m.enable) &&
|
||||
m.enable.toLowerCase() == 'false') ?
|
||||
@ -678,6 +679,7 @@ define('pgadmin.browser', [
|
||||
url: url_for('preferences.get_all'),
|
||||
success: function(res) {
|
||||
self.preferences_cache = res;
|
||||
pgBrowser.keyboardNavigation.init();
|
||||
},
|
||||
error: function(xhr) {
|
||||
try {
|
||||
@ -1958,8 +1960,8 @@ define('pgadmin.browser', [
|
||||
pgAdmin.Browser.editor_shortcut_keys.Tab = 'insertSoftTab';
|
||||
}
|
||||
|
||||
window.onbeforeunload = function(ev) {
|
||||
var e = ev || window.event,
|
||||
window.onbeforeunload = function() {
|
||||
var e = window.event,
|
||||
msg = S(gettext('Are you sure you wish to close the %s browser?')).sprintf(pgBrowser.utils.app_name).value();
|
||||
|
||||
// For IE and Firefox prior to version 4
|
||||
@ -1971,5 +1973,6 @@ define('pgadmin.browser', [
|
||||
return msg;
|
||||
};
|
||||
|
||||
|
||||
return pgAdmin.Browser;
|
||||
});
|
||||
|
159
web/pgadmin/browser/static/js/keyboard.js
Normal file
159
web/pgadmin/browser/static/js/keyboard.js
Normal file
@ -0,0 +1,159 @@
|
||||
/* eslint-disable */
|
||||
define(
|
||||
['underscore', 'underscore.string', 'sources/pgadmin', 'jquery', 'mousetrap'],
|
||||
function(_, S, pgAdmin, $, Mousetrap) {
|
||||
'use strict';
|
||||
|
||||
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
|
||||
pgBrowser.keyboardNavigation = pgBrowser.keyboardNavigation || {};
|
||||
|
||||
_.extend(pgBrowser.keyboardNavigation, {
|
||||
init: function() {
|
||||
Mousetrap.reset();
|
||||
if (pgBrowser.preferences_cache.length > 0) {
|
||||
this.keyboardShortcut = {
|
||||
'file_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_file').value),
|
||||
'object_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_object').value),
|
||||
'tools_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_tools').value),
|
||||
'help_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_help').value),
|
||||
'left_tree_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'browser_tree').value),
|
||||
'tabbed_panel_backward': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_backward').value),
|
||||
'tabbed_panel_forward': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_forward').value)
|
||||
};
|
||||
this.shortcutMethods = {
|
||||
'bindMainMenu': {'shortcuts': [this.keyboardShortcut.file_shortcut,
|
||||
this.keyboardShortcut.object_shortcut, this.keyboardShortcut.tools_shortcut,
|
||||
this.keyboardShortcut.help_shortcut]}, // Main menu
|
||||
'bindRightPanel': {'shortcuts': [this.keyboardShortcut.tabbed_panel_backward, this.keyboardShortcut.tabbed_panel_forward]}, // Main window panels
|
||||
'bindMainMenuLeft': {'shortcuts': 'left', 'bindElem': '.pg-navbar'}, // Main menu
|
||||
'bindMainMenuRight': {'shortcuts': 'right', 'bindElem': '.pg-navbar'}, // Main menu
|
||||
'bindMainMenuUpDown': {'shortcuts': ['up', 'down']}, // Main menu
|
||||
'bindLeftTree': {'shortcuts': this.keyboardShortcut.left_tree_shortcut}, // Main menu
|
||||
};
|
||||
this.bindShortcuts();
|
||||
}
|
||||
},
|
||||
bindShortcuts: function() {
|
||||
var self = this;
|
||||
_.each(self.shortcutMethods, function(keyCombo, callback) {
|
||||
self._bindWithMousetrap(keyCombo.shortcuts, self[callback], keyCombo.bindElem);
|
||||
});
|
||||
},
|
||||
_bindWithMousetrap: function(shortcuts, callback, bindElem) {
|
||||
if (bindElem) {
|
||||
var elem = document.querySelector(bindElem);
|
||||
Mousetrap(elem).bind(shortcuts, function() {
|
||||
callback.apply(this, arguments);
|
||||
}.bind(elem));
|
||||
} else {
|
||||
Mousetrap.bind(shortcuts, function() {
|
||||
callback.apply(this, arguments);
|
||||
});
|
||||
}
|
||||
},
|
||||
attachShortcut: function(shortcut, callback, bindElem) {
|
||||
this._bindWithMousetrap(shortcut, callback, bindElem);
|
||||
},
|
||||
detachShortcut: function(shortcut, bindElem) {
|
||||
if (bindElem) Mousetrap(bindElem).unbind(shortcut);
|
||||
else Mousetrap.unbind(shortcut);
|
||||
},
|
||||
bindMainMenu: function(e, combo) {
|
||||
var shortcut_obj = pgAdmin.Browser.keyboardNavigation.keyboardShortcut;
|
||||
if (combo == shortcut_obj.file_shortcut) $('#mnu_file a.dropdown-toggle').dropdown('toggle');
|
||||
if (combo == shortcut_obj.object_shortcut) $('#mnu_obj a.dropdown-toggle').first().dropdown('toggle');
|
||||
if (combo == shortcut_obj.tools_shortcut) $('#mnu_tools a.dropdown-toggle').dropdown('toggle');
|
||||
if (combo == shortcut_obj.help_shortcut) $('#mnu_help a.dropdown-toggle').dropdown('toggle');
|
||||
},
|
||||
bindRightPanel: function(e, combo) {
|
||||
var allPanels = pgAdmin.Browser.docker.findPanels(),
|
||||
activePanel = 0,
|
||||
nextPanel = allPanels.length,
|
||||
prevPanel = 1,
|
||||
activePanelId = 0,
|
||||
activePanelFlag = false,
|
||||
shortcut_obj = pgAdmin.Browser.keyboardNavigation.keyboardShortcut;
|
||||
|
||||
_.each(pgAdmin.Browser.docker.findPanels(), function(panel, index){
|
||||
if (panel.isVisible() && !activePanelFlag && panel._type != 'browser'){
|
||||
activePanelId = index;
|
||||
activePanelFlag = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (combo == shortcut_obj.tabbed_panel_backward) activePanel = (activePanelId > 0) ? activePanelId - 1 : prevPanel;
|
||||
else if (combo == shortcut_obj.tabbed_panel_forward) activePanel = (activePanelId < nextPanel) ? activePanelId + 1 : nextPanel;
|
||||
|
||||
pgAdmin.Browser.docker.findPanels()[activePanel].focus();
|
||||
setTimeout(function() {
|
||||
if (document.activeElement instanceof HTMLIFrameElement) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
bindMainMenuLeft: function(e) {
|
||||
var prevMenu;
|
||||
if ($(e.target).hasClass('menu-link')) { // Menu items
|
||||
prevMenu = $(e.target).parent().parent().parent().prev('.dropdown');
|
||||
}
|
||||
else if ($(e.target).parent().hasClass('dropdown-submenu')) { // Sub menu
|
||||
$(e.target).parent().toggleClass('open');
|
||||
return;
|
||||
}
|
||||
else { //Menu headers
|
||||
prevMenu = $(e.target).parent().prev('.dropdown');
|
||||
}
|
||||
|
||||
if (prevMenu.hasClass('hide')) prevMenu = prevMenu.prev('.dropdown'); // Skip hidden menus
|
||||
|
||||
prevMenu.find('a:first').dropdown('toggle');
|
||||
},
|
||||
bindMainMenuRight: function(e) {
|
||||
var nextMenu;
|
||||
if ($(e.target).hasClass('menu-link')) { // Menu items
|
||||
nextMenu = $(e.target).parent().parent().parent().next('.dropdown');
|
||||
}
|
||||
else if ($(e.target).parent().hasClass('dropdown-submenu')) { // Sub menu
|
||||
$(e.target).parent().toggleClass('open');
|
||||
return;
|
||||
}
|
||||
else { //Menu headers
|
||||
nextMenu = $(e.target).parent().next('.dropdown');
|
||||
}
|
||||
|
||||
if (nextMenu.hasClass('hide')) nextMenu = nextMenu.next('.dropdown'); // Skip hidden menus
|
||||
|
||||
nextMenu.find('a:first').dropdown('toggle');
|
||||
},
|
||||
bindMainMenuUpDown: function(e, combo) {
|
||||
// Handle Sub-menus
|
||||
if (combo == 'up' && $(e.target).parent().prev().prev('.dropdown-submenu').length > 0) {
|
||||
$(e.target).parent().prev().prev('.dropdown-submenu').find('a:first').focus();
|
||||
} else {
|
||||
if ($(e.target).parent().hasClass('dropdown-submenu')) {
|
||||
$(e.target).parent().parent().parent().find('a:first').dropdown('toggle');
|
||||
$(e.target).parent().parent().children().eq(2).find('a:first').focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
bindLeftTree: function() {
|
||||
var t = pgAdmin.Browser.tree,
|
||||
item = t.selected().length > 0 ? t.selected() : t.first();
|
||||
$('#tree').focus();
|
||||
t.focus(item);
|
||||
t.select(item);
|
||||
},
|
||||
parseShortcutValue: function(obj) {
|
||||
var shortcut = "";
|
||||
if (obj.alt) { shortcut += 'alt+'; }
|
||||
if (obj.shift) { shortcut += 'shift+'; }
|
||||
if (obj.control) { shortcut += 'ctrl+'; }
|
||||
shortcut += String.fromCharCode(obj.key.key_code).toLowerCase();
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return pgAdmin.keyboardNavigation;
|
||||
});
|
@ -42,7 +42,8 @@ define(
|
||||
if (!that.showTitle)
|
||||
myPanel.title(false);
|
||||
else {
|
||||
myPanel.title(title || that.title);
|
||||
var title_elem = '<a href="#" tabindex="0" class="panel-link-heading">' + (title || that.title) + '</a>';
|
||||
myPanel.title(title_elem);
|
||||
if (that.icon != '')
|
||||
myPanel.icon(that.icon);
|
||||
}
|
||||
|
@ -131,37 +131,37 @@ window.onload = function(e){
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbar-menu">
|
||||
<div class="collapse navbar-collapse" id="navbar-menu" role="navigation">
|
||||
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<li id="mnu_file" class="dropdown hide">
|
||||
<a href="#" accesskey="f" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
_('File') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu navbar-inverse" role="menu"></ul>
|
||||
</li>
|
||||
<li id="mnu_edit" class="dropdown hide">
|
||||
<a href="#" accesskey="e" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
_('Edit') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu navbar-inverse" role="menu"></ul>
|
||||
</li>
|
||||
<li id="mnu_obj" class="dropdown ">
|
||||
<a href="#" accesskey="o" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
_('Object') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu navbar-inverse" role="menu"></ul>
|
||||
</li>
|
||||
<li id="mnu_management" class="dropdown hide">
|
||||
<a href="#" accesskey="m" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
_('Management') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu navbar-inverse" role="menu"></ul>
|
||||
</li>
|
||||
<li id="mnu_tools" accesskey="t" class="dropdown hide">
|
||||
<li id="mnu_tools" class="dropdown hide">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
_('Tools') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu navbar-inverse" role="menu"></ul>
|
||||
</li>
|
||||
<li id="mnu_help" class="dropdown hide">
|
||||
<a href="#" accesskey="h" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{
|
||||
_('Help') }} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu navbar-inverse" role="menu"></ul>
|
||||
</li>
|
||||
|
95
web/pgadmin/feature_tests/keyboard_shortcut_test.py
Normal file
95
web/pgadmin/feature_tests/keyboard_shortcut_test.py
Normal file
@ -0,0 +1,95 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver import ActionChains
|
||||
from regression.feature_utils.base_feature_test import BaseFeatureTest
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
|
||||
class KeyboardShortcutFeatureTest(BaseFeatureTest):
|
||||
"""
|
||||
This feature test will test the keyboard short is working
|
||||
properly.
|
||||
"""
|
||||
|
||||
scenarios = [
|
||||
("Test for keyboard shortcut", dict())
|
||||
]
|
||||
|
||||
def before(self):
|
||||
self.new_shortcuts = {
|
||||
'mnu_file': {'shortcut': [Keys.ALT, Keys.SHIFT, 'i'], 'locator': 'File main menu'},
|
||||
'mnu_obj': {'shortcut': [Keys.ALT, Keys.SHIFT, 'j'], 'locator': 'Object main menu'}
|
||||
}
|
||||
|
||||
self.wait = WebDriverWait(self.page.driver, 10)
|
||||
|
||||
def runTest(self):
|
||||
self._update_preferences()
|
||||
# On updating keyboard shortcuts, preference cache is updated.
|
||||
# There is no UI event through which we can identify that the cache is updated,
|
||||
# So, added time.sleep()
|
||||
time.sleep(1)
|
||||
self._check_shortcuts()
|
||||
|
||||
def _check_shortcuts(self):
|
||||
action = ActionChains(self.driver)
|
||||
for s in self.new_shortcuts:
|
||||
key_combo = self.new_shortcuts[s]['shortcut']
|
||||
action.key_down(key_combo[0]).key_down(key_combo[1]).key_down(key_combo[2]).key_up(Keys.ALT).perform()
|
||||
|
||||
self.wait.until(EC.presence_of_element_located(
|
||||
(By.XPATH, "//li[contains(@id, " + s + ") and contains(@class, 'open')]"))
|
||||
)
|
||||
|
||||
is_open = 'open' in self.page.find_by_id(s).get_attribute('class')
|
||||
|
||||
assert is_open is True, "Keyboard shortcut change is unsuccessful."
|
||||
|
||||
def _update_preferences(self):
|
||||
self.page.find_by_id("mnu_file").click()
|
||||
self.page.find_by_id("mnu_preferences").click()
|
||||
|
||||
self.wait.until(EC.presence_of_element_located(
|
||||
(By.XPATH, "//*[contains(string(), 'Show system objects?')]"))
|
||||
)
|
||||
|
||||
self.page.find_by_css_selector(".ajs-dialog.pg-el-container .ajs-maximize").click()
|
||||
|
||||
browser = self.page.find_by_xpath(
|
||||
"//*[contains(@class,'aciTreeLi') and contains(.,'Browser')]")
|
||||
|
||||
browser.find_element_by_xpath(
|
||||
"//*[contains(@class,'aciTreeText') and contains(.,'Keyboard shortcuts')]") \
|
||||
.click()
|
||||
|
||||
for s in self.new_shortcuts:
|
||||
key = self.new_shortcuts[s]['shortcut'][2]
|
||||
locator = self.new_shortcuts[s]['locator']
|
||||
file_menu = self.page.find_by_xpath(
|
||||
"//div[contains(@class,'pgadmin-control-group') and contains(.,'" + locator + "')]")
|
||||
|
||||
field = file_menu.find_element_by_name('key')
|
||||
field.click()
|
||||
field.send_keys(key)
|
||||
|
||||
# save and close the preference dialog.
|
||||
self.page.find_by_xpath(
|
||||
"//*[contains(@class,'pg-alertify-button') and contains(.,'OK')]").click()
|
||||
|
||||
self.page.wait_for_element_to_disappear(
|
||||
lambda driver: driver.find_element_by_css_selector(".ajs-modal")
|
||||
)
|
||||
|
File diff suppressed because one or more lines are too long
@ -8,7 +8,8 @@ const EDIT_KEY = 71, // Key: G -> Grid values
|
||||
F7_KEY = 118,
|
||||
F8_KEY = 119,
|
||||
PERIOD_KEY = 190,
|
||||
FWD_SLASH_KEY = 191;
|
||||
FWD_SLASH_KEY = 191,
|
||||
ESC_KEY = 27;
|
||||
|
||||
function isMac() {
|
||||
return window.navigator.platform.search('Mac') != -1;
|
||||
@ -158,6 +159,8 @@ function keyboardShortcutsQueryTool(sqlEditorController, queryToolActions, event
|
||||
panel_id = this.getInnerPanel(
|
||||
sqlEditorController.container, 'right'
|
||||
);
|
||||
} else if (keyCode == ESC_KEY) {
|
||||
queryToolActions.focusOut(sqlEditorController);
|
||||
}
|
||||
return panel_id;
|
||||
}
|
||||
|
@ -96,6 +96,11 @@ let queryToolActions = {
|
||||
{lineComment: '--'}
|
||||
);
|
||||
},
|
||||
|
||||
focusOut: function() {
|
||||
document.activeElement.blur();
|
||||
window.top.document.activeElement.blur();
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = queryToolActions;
|
||||
|
@ -143,6 +143,7 @@ var webpackShimConfig = {
|
||||
'bignumber': path.join(__dirname, './node_modules/bignumber.js/bignumber'),
|
||||
'snap.svg': path.join(__dirname, './node_modules/snapsvg/dist/snap.svg'),
|
||||
'spectrum': path.join(__dirname, './node_modules/spectrum-colorpicker/spectrum'),
|
||||
'mousetrap': path.join(__dirname, './node_modules/mousetrap'),
|
||||
|
||||
// AciTree
|
||||
'jquery.acitree': path.join(__dirname, './node_modules/acitree/js/jquery.aciTree.min'),
|
||||
@ -259,6 +260,7 @@ var webpackShimConfig = {
|
||||
'pgadmin.browser.frame': path.join(__dirname, './pgadmin/browser/static/js/frame'),
|
||||
'pgadmin.node.type': path.join(__dirname, './pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type'),
|
||||
'pgadmin.file_manager': path.join(__dirname, './pgadmin/misc/file_manager/static/js/file_manager'),
|
||||
'pgadmin.browser.keyboard': path.join(__dirname, './pgadmin/browser/static/js/keyboard'),
|
||||
},
|
||||
externals: [
|
||||
'pgadmin.user_management.current_user',
|
||||
|
@ -4895,6 +4895,10 @@ moment-timezone@^0.4.0:
|
||||
version "2.18.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
||||
|
||||
mousetrap@^1.6.1:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.1.tgz#2a085f5c751294c75e7e81f6ec2545b29cbf42d9"
|
||||
|
||||
mozjpeg@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/mozjpeg/-/mozjpeg-4.1.1.tgz#859030b24f689a53db9b40f0160d89195b88fd50"
|
||||
|
Loading…
Reference in New Issue
Block a user