mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Add missing files related to previous commit: Infrastructure and changes to the Query Tool for realtime preference handling. Refs #3294
This commit is contained in:
parent
bdb7e3fde2
commit
73530c05aa
@ -16,6 +16,7 @@ Features
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Bug #3294 <https://redmine.postgresql.org/issues/3294>`_ - Infrastructure (and changes to the Query Tool) for realtime preference handling.
|
||||
| `Bug #3309 <https://redmine.postgresql.org/issues/3309>`_ - Fix Directory format support for backups.
|
||||
| `Bug #3319 <https://redmine.postgresql.org/issues/3319>`_ - Cleanup and fix handling of Query Tool Cancel button status.
|
||||
| `Bug #3363 <https://redmine.postgresql.org/issues/3363>`_ - Fix restoring of restore options for sections.
|
||||
|
146
web/pgadmin/browser/static/js/preferences.js
Normal file
146
web/pgadmin/browser/static/js/preferences.js
Normal file
@ -0,0 +1,146 @@
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import url_for from 'sources/url_for';
|
||||
import * as modifyAnimation from 'sources/modify_animation';
|
||||
import $ from 'jquery';
|
||||
import * as Alertify from 'pgadmin.alertifyjs';
|
||||
import * as SqlEditorUtils from 'sources/sqleditor_utils';
|
||||
|
||||
const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
|
||||
/* Add cache related methods and properties */
|
||||
_.extend(pgBrowser, {
|
||||
/* This will hold preference data (Works as a cache object)
|
||||
* Here node will be a key and it's preference data will be value
|
||||
*/
|
||||
preferences_cache: [],
|
||||
|
||||
/* This will be used by poller of new tabs/windows to check
|
||||
* if preference cache is updated in parent/window.opener.
|
||||
*/
|
||||
prefcache_version: 0,
|
||||
|
||||
/* Generate a unique version number */
|
||||
generate_preference_version: function() {
|
||||
return (new Date()).getTime();
|
||||
},
|
||||
|
||||
preference_version: function(version) {
|
||||
if(version) {
|
||||
this.prefcache_version = version;
|
||||
}
|
||||
else {
|
||||
return this.prefcache_version;
|
||||
}
|
||||
},
|
||||
|
||||
/* Get cached preference */
|
||||
get_preference: function(module, preference){
|
||||
const self = this;
|
||||
// If cache is not yet loaded then keep checking
|
||||
if(_.size(self.preferences_cache) == 0) {
|
||||
var check_preference = function() {
|
||||
if(self.preferences_cache.length > 0) {
|
||||
clearInterval(preferenceTimeout);
|
||||
return _.findWhere(
|
||||
self.preferences_cache, {'module': module, 'name': preference}
|
||||
);
|
||||
}
|
||||
},
|
||||
preferenceTimeout = setInterval(check_preference, 1000);
|
||||
}
|
||||
else {
|
||||
return _.findWhere(
|
||||
self.preferences_cache, {'module': module, 'name': preference}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/* Get all the preferences of a module */
|
||||
get_preferences_for_module: function(module) {
|
||||
var self = this;
|
||||
let preferences = {};
|
||||
_.each(
|
||||
_.where(self.preferences_cache, {'module': module}),
|
||||
(preference) => {
|
||||
preferences[preference.name] = preference.value;
|
||||
}
|
||||
);
|
||||
return preferences;
|
||||
},
|
||||
|
||||
/* Get preference of an id, id is numeric */
|
||||
get_preference_for_id : function(id) {
|
||||
var self = this;
|
||||
return _.findWhere(self.preferences_cache, {'id': id});
|
||||
},
|
||||
|
||||
// Get and cache the preferences
|
||||
cache_preferences: function (modulesChanged) {
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
$.ajax({
|
||||
url: url_for('preferences.get_all'),
|
||||
success: function(res) {
|
||||
self.preferences_cache = res;
|
||||
self.preference_version(self.generate_preference_version());
|
||||
|
||||
pgBrowser.keyboardNavigation.init();
|
||||
if(pgBrowser.tree) {
|
||||
modifyAnimation.modifyAcitreeAnimation(self);
|
||||
modifyAnimation.modifyAlertifyAnimation(self);
|
||||
}
|
||||
|
||||
/* Once the cache is loaded after changing the preferences,
|
||||
* notify the modules of the change
|
||||
*/
|
||||
if(modulesChanged) {
|
||||
if(typeof modulesChanged === 'string'){
|
||||
$.event.trigger('prefchange:'+modulesChanged);
|
||||
} else {
|
||||
_.each(modulesChanged, (val, key)=> {
|
||||
$.event.trigger('prefchange:'+key);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
Alertify.pgRespErrorNotify(xhr, error);
|
||||
},
|
||||
});
|
||||
}, 500);
|
||||
},
|
||||
|
||||
reflectPreferences: function(module) {
|
||||
let obj = this;
|
||||
|
||||
if(module === 'sqleditor' || module === null || typeof module === 'undefined') {
|
||||
let sqlEditPreferences = obj.get_preferences_for_module('sqleditor');
|
||||
|
||||
$(obj.editor.getWrapperElement()).css(
|
||||
'font-size',SqlEditorUtils.calcFontSize(sqlEditPreferences.sql_font_size)
|
||||
);
|
||||
obj.editor.setOption('tabSize', sqlEditPreferences.tab_size);
|
||||
obj.editor.setOption('lineWrapping', sqlEditPreferences.wrap_code);
|
||||
obj.editor.setOption('autoCloseBrackets', sqlEditPreferences.insert_pair_brackets);
|
||||
obj.editor.setOption('matchBrackets', sqlEditPreferences.brace_matching);
|
||||
obj.editor.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
onPreferencesChange: function(module, eventHandler) {
|
||||
window.parent.$(parent.document).on('prefchange:'+module, function(event) {
|
||||
/* If a sqleditor is closed, event handler will be called
|
||||
* but the window.top will be null. Unbind the event handler
|
||||
*/
|
||||
if(window.top === null) {
|
||||
window.$(document).off(event);
|
||||
}
|
||||
else {
|
||||
eventHandler(event);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export {pgBrowser};
|
179
web/pgadmin/static/js/sqleditor/query_tool_preferences.js
Normal file
179
web/pgadmin/static/js/sqleditor/query_tool_preferences.js
Normal file
@ -0,0 +1,179 @@
|
||||
import {shortcut_key, shortcut_accesskey_title, shortcut_title}
|
||||
from 'sources/keyboard_shortcuts';
|
||||
import * as SqlEditorUtils from 'sources/sqleditor_utils';
|
||||
import $ from 'jquery';
|
||||
|
||||
function updateUIPreferences(sqlEditor) {
|
||||
let $el = sqlEditor.$el,
|
||||
preferences = sqlEditor.preferences;
|
||||
|
||||
if(sqlEditor.handler.slickgrid) {
|
||||
sqlEditor.handler.slickgrid.CSVOptions = {
|
||||
quoting: sqlEditor.preferences.results_grid_quoting,
|
||||
quote_char: sqlEditor.preferences.results_grid_quote_char,
|
||||
field_separator: sqlEditor.preferences.results_grid_field_separator,
|
||||
};
|
||||
}
|
||||
|
||||
/* Accessed using accesskey direct w/o ctrl,atl,shift */
|
||||
$el.find('#btn-load-file')
|
||||
.attr('title', shortcut_accesskey_title('Open File',preferences.btn_open_file))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_open_file));
|
||||
|
||||
$el.find('#btn-save')
|
||||
.attr('title', shortcut_accesskey_title('Save File',preferences.btn_save_file))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_save_file));
|
||||
|
||||
$el.find('#btn-find-menu-dropdown')
|
||||
.attr('title', shortcut_accesskey_title('Find',preferences.btn_find_options))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_find_options));
|
||||
|
||||
$el.find('#btn-copy-row')
|
||||
.attr('title', shortcut_accesskey_title('Copy',preferences.btn_copy_row))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_copy_row));
|
||||
|
||||
$el.find('#btn-paste-row')
|
||||
.attr('title', shortcut_accesskey_title('Paste',preferences.btn_paste_row))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_paste_row));
|
||||
|
||||
$el.find('#btn-delete-row')
|
||||
.attr('title', shortcut_accesskey_title('Delete',preferences.btn_delete_row))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_delete_row));
|
||||
|
||||
$el.find('#btn-filter')
|
||||
.attr('title', shortcut_accesskey_title('Filter',preferences.btn_filter_dialog))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_filter_dialog));
|
||||
|
||||
$el.find('#btn-filter-dropdown')
|
||||
.attr('title', shortcut_accesskey_title('Filter options',preferences.btn_filter_options))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_filter_options));
|
||||
|
||||
$el.find('#btn-rows-limit')
|
||||
.attr('title', shortcut_accesskey_title('Rows limit',preferences.btn_rows_limit))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_rows_limit));
|
||||
|
||||
$el.find('#btn-query-dropdown')
|
||||
.attr('title', shortcut_accesskey_title('Execute options',preferences.btn_execute_options))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_execute_options));
|
||||
|
||||
$el.find('#btn-cancel-query')
|
||||
.attr('title', shortcut_accesskey_title('Cancel query',preferences.btn_cancel_query))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_cancel_query));
|
||||
|
||||
$el.find('#btn-clear-dropdown')
|
||||
.attr('title', shortcut_accesskey_title('Clear',preferences.btn_clear_options))
|
||||
.attr('accesskey', shortcut_key(preferences.btn_clear_options));
|
||||
|
||||
$el.find('#btn-conn-status')
|
||||
.attr('accesskey', shortcut_key(preferences.btn_conn_status))
|
||||
.find('i')
|
||||
.attr('title',
|
||||
shortcut_accesskey_title('Connection status (click for details)',
|
||||
preferences.btn_conn_status));
|
||||
|
||||
/* Accessed using ctrl,atl,shift and key */
|
||||
$el.find('#btn-flash')
|
||||
.attr('title',
|
||||
shortcut_title('Execute/Refresh',preferences.execute_query));
|
||||
|
||||
$el.find('#btn-flash-menu span')
|
||||
.text(shortcut_title('Execute/Refresh',preferences.execute_query));
|
||||
|
||||
$el.find('#btn-explain span')
|
||||
.text(shortcut_title('Explain',preferences.explain_query));
|
||||
|
||||
$el.find('#btn-explain-analyze span')
|
||||
.text(shortcut_title('Explain Analyze',preferences.explain_analyze_query));
|
||||
|
||||
$el.find('#btn-download')
|
||||
.attr('title',
|
||||
shortcut_title('Download as CSV',preferences.download_csv));
|
||||
|
||||
/* Set Auto-commit and auto-rollback on query editor */
|
||||
if (preferences.auto_commit) {
|
||||
$el.find('.auto-commit').removeClass('visibility-hidden');
|
||||
}
|
||||
else {
|
||||
$el.find('.auto-commit').addClass('visibility-hidden');
|
||||
}
|
||||
if (preferences.auto_rollback) {
|
||||
$el.find('.auto-rollback').removeClass('visibility-hidden');
|
||||
}
|
||||
else {
|
||||
$el.find('.auto-rollback').addClass('visibility-hidden');
|
||||
}
|
||||
|
||||
/* Set explain options on query editor */
|
||||
if (preferences.explain_verbose){
|
||||
$el.find('.explain-verbose').removeClass('visibility-hidden');
|
||||
}
|
||||
else {
|
||||
$el.find('.explain-verbose').addClass('visibility-hidden');
|
||||
}
|
||||
|
||||
if (preferences.explain_costs){
|
||||
$el.find('.explain-costs').removeClass('visibility-hidden');
|
||||
}
|
||||
else {
|
||||
$el.find('.explain-costs').addClass('visibility-hidden');
|
||||
}
|
||||
|
||||
if (preferences.explain_buffers){
|
||||
$el.find('.explain-buffers').removeClass('visibility-hidden');
|
||||
}
|
||||
else {
|
||||
$el.find('.explain-buffers').addClass('visibility-hidden');
|
||||
}
|
||||
|
||||
if (preferences.explain_timing) {
|
||||
$el.find('.explain-timing').removeClass('visibility-hidden');
|
||||
}
|
||||
else {
|
||||
$el.find('.explain-timing').addClass('visibility-hidden');
|
||||
}
|
||||
|
||||
/* Connection status check */
|
||||
/* remove the status checker if present */
|
||||
if(sqlEditor.connIntervalId != null) {
|
||||
clearInterval(sqlEditor.connIntervalId);
|
||||
sqlEditor.connIntervalId = null;
|
||||
}
|
||||
if (preferences.connection_status) {
|
||||
let $conn_status = $el.find('#btn-conn-status'),
|
||||
$status_el = $conn_status.find('i');
|
||||
$conn_status.popover();
|
||||
|
||||
$conn_status.removeClass('connection-status-hide');
|
||||
$el.find('.editor-title').addClass('editor-title-connection');
|
||||
|
||||
// To set initial connection
|
||||
SqlEditorUtils.fetchConnectionStatus(sqlEditor.handler, $conn_status, $status_el);
|
||||
|
||||
// Calling it again in specified interval
|
||||
sqlEditor.connIntervalId = setInterval(
|
||||
SqlEditorUtils.fetchConnectionStatus.bind(null, sqlEditor.handler, $conn_status, $status_el),
|
||||
preferences.connection_status_fetch_time * 1000
|
||||
);
|
||||
}
|
||||
else {
|
||||
$el.find('#btn-conn-status').addClass('connection-status-hide');
|
||||
$el.find('.editor-title').removeClass('editor-title-connection');
|
||||
}
|
||||
|
||||
/* Code Mirror Preferences */
|
||||
let sql_font_size = SqlEditorUtils.calcFontSize(preferences.sql_font_size);
|
||||
$(sqlEditor.query_tool_obj.getWrapperElement()).css('font-size', sql_font_size);
|
||||
|
||||
sqlEditor.query_tool_obj.setOption('indentWithTabs', !preferences.use_spaces);
|
||||
sqlEditor.query_tool_obj.setOption('indentUnit', preferences.tab_size);
|
||||
sqlEditor.query_tool_obj.setOption('tabSize', preferences.tab_size);
|
||||
sqlEditor.query_tool_obj.setOption('lineWrapping', preferences.wrap_code);
|
||||
sqlEditor.query_tool_obj.setOption('autoCloseBrackets', preferences.insert_pair_brackets);
|
||||
sqlEditor.query_tool_obj.setOption('matchBrackets', preferences.brace_matching);
|
||||
sqlEditor.query_tool_obj.refresh();
|
||||
|
||||
/* Render history to reflect Font size change */
|
||||
sqlEditor.render_history_grid();
|
||||
}
|
||||
|
||||
export {updateUIPreferences};
|
152
web/regression/javascript/browser/preferences_spec.js
Normal file
152
web/regression/javascript/browser/preferences_spec.js
Normal file
@ -0,0 +1,152 @@
|
||||
import {pgBrowser} from 'pgadmin.browser.preferences';
|
||||
import $ from 'jquery';
|
||||
|
||||
var dummy_cache = [
|
||||
{
|
||||
id: 1,
|
||||
mid: 1,
|
||||
module:'module1',
|
||||
name:'pref1',
|
||||
value:{
|
||||
alt: false,
|
||||
shift: false,
|
||||
control: false,
|
||||
key: {
|
||||
char: 'a',
|
||||
key_code: 65,
|
||||
},
|
||||
},
|
||||
},{
|
||||
id: 2,
|
||||
mid: 1,
|
||||
module:'module1',
|
||||
name:'pref2',
|
||||
value: 123,
|
||||
},{
|
||||
id: 3,
|
||||
mid: 2,
|
||||
module:'module2',
|
||||
name:'pref2',
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
|
||||
describe('preferences related functions test', function() {
|
||||
describe('get preference data related functions', function(){
|
||||
beforeEach(function(){
|
||||
pgBrowser.preferences_cache = dummy_cache;
|
||||
});
|
||||
|
||||
it('generate_preference_version', function() {
|
||||
pgBrowser.generate_preference_version();
|
||||
expect(pgBrowser.generate_preference_version()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('preference_version', function() {
|
||||
let version = 123;
|
||||
pgBrowser.preference_version(version);
|
||||
expect(pgBrowser.prefcache_version).toEqual(version);
|
||||
expect(pgBrowser.preference_version()).toEqual(version);
|
||||
});
|
||||
|
||||
it('get_preference', function(){
|
||||
expect(pgBrowser.get_preference('module1','pref1')).toEqual({
|
||||
id: 1,
|
||||
mid: 1,
|
||||
module:'module1',
|
||||
name:'pref1',
|
||||
value:{
|
||||
alt: false,
|
||||
shift: false,
|
||||
control: false,
|
||||
key: {
|
||||
char: 'a',
|
||||
key_code: 65,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('get_preferences_for_module', function() {
|
||||
expect(pgBrowser.get_preferences_for_module('module1')).toEqual({
|
||||
'pref1':{
|
||||
alt: false,
|
||||
shift: false,
|
||||
control: false,
|
||||
key: {
|
||||
char: 'a',
|
||||
key_code: 65,
|
||||
},
|
||||
},
|
||||
'pref2': 123,
|
||||
});
|
||||
});
|
||||
|
||||
it('get_preference_for_id', function() {
|
||||
expect(pgBrowser.get_preference_for_id(3)).toEqual({
|
||||
id: 3,
|
||||
mid: 2,
|
||||
module:'module2',
|
||||
name:'pref2',
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('reflectPreferences', function() {
|
||||
|
||||
let editorOptions = {
|
||||
'tabSize':2,
|
||||
'lineWrapping':false,
|
||||
'autoCloseBrackets':true,
|
||||
'matchBrackets':true,
|
||||
};
|
||||
pgBrowser.preferences_cache.push({
|
||||
id: 4, mid: 3, module:'sqleditor', name:'sql_font_size', value: 1.456,
|
||||
});
|
||||
pgBrowser.preferences_cache.push({
|
||||
id: 4, mid: 3, module:'sqleditor', name:'tab_size', value: editorOptions.tabSize,
|
||||
});
|
||||
pgBrowser.preferences_cache.push({
|
||||
id: 4, mid: 3, module:'sqleditor', name:'wrap_code', value: editorOptions.lineWrapping,
|
||||
});
|
||||
pgBrowser.preferences_cache.push({
|
||||
id: 4, mid: 3, module:'sqleditor', name:'insert_pair_brackets', value: editorOptions.autoCloseBrackets,
|
||||
});
|
||||
pgBrowser.preferences_cache.push({
|
||||
id: 4, mid: 3, module:'sqleditor', name:'brace_matching', value: editorOptions.matchBrackets,
|
||||
});
|
||||
|
||||
/* Spies */
|
||||
pgBrowser.editor = jasmine.createSpyObj(
|
||||
'CodeMirror', ['setOption','refresh','getWrapperElement']
|
||||
);
|
||||
spyOn($.fn, 'css');
|
||||
|
||||
/* Call */
|
||||
pgBrowser.reflectPreferences();
|
||||
|
||||
/* Tests */
|
||||
expect(pgBrowser.editor.getWrapperElement).toHaveBeenCalled();
|
||||
expect($.fn.css).toHaveBeenCalledWith('font-size', '1.46em');
|
||||
|
||||
let setOptionCalls = pgBrowser.editor.setOption.calls;
|
||||
expect(setOptionCalls.count()).toBe(Object.keys(editorOptions).length);
|
||||
|
||||
for(let i = 0; i < Object.keys(editorOptions).length; i++) {
|
||||
let option = Object.keys(editorOptions)[i];
|
||||
expect(setOptionCalls.argsFor(i)).toEqual([option, editorOptions[option]]);
|
||||
}
|
||||
expect(pgBrowser.editor.refresh).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onPreferencesChange', function() {
|
||||
|
||||
window.parent.$ = $;
|
||||
spyOn($.fn, 'on');
|
||||
|
||||
var eventHandler = jasmine.createSpy('eventHandler');
|
||||
pgBrowser.onPreferencesChange('somemodule', eventHandler);
|
||||
expect($.fn.on.calls.mostRecent().args[0]).toEqual('prefchange:somemodule');
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user