diff --git a/docs/en_US/images/preferences_browser_display.png b/docs/en_US/images/preferences_browser_display.png index a3c636239..c4463aad7 100644 Binary files a/docs/en_US/images/preferences_browser_display.png and b/docs/en_US/images/preferences_browser_display.png differ diff --git a/docs/en_US/preferences.rst b/docs/en_US/preferences.rst index 1f2796116..c22365fbb 100644 --- a/docs/en_US/preferences.rst +++ b/docs/en_US/preferences.rst @@ -18,7 +18,11 @@ Use preferences found in the *Browser* node of the tree control to personalize y 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. +* 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. + +* When the *Enable browser tree animation?* switch is set to *True*, the client will display the animated tree control otherwise it will be unanimated. + +* When the *Enable dialogue/notification animation?* switch is set to *True*, the client will display the animated dialogues/notifications otherwise it will be unanimated. Use the fields on the *Keyboard shortcuts* panel to configure shortcuts for the main window navigation: diff --git a/docs/en_US/release_notes_3_0.rst b/docs/en_US/release_notes_3_0.rst index cc7559567..4e153d3bd 100644 --- a/docs/en_US/release_notes_3_0.rst +++ b/docs/en_US/release_notes_3_0.rst @@ -11,6 +11,7 @@ Features ******** | `Feature #1305 `_ - Enable building of the runtime from the top level Makefile +| `Feature #1978 `_ - Add the ability to enable/disable UI animations | `Feature #2895 `_ - Add keyboard navigation options for the main browser windows | `Feature #2896 `_ - Add keyboard navigation in Query tool module via Tab/Shift-Tab key | `Feature #2897 `_ - Support keyboard navigation in the debugger @@ -111,4 +112,5 @@ Bug fixes | `Bug #3197 `_ - Appropriately set the cookie path | `Bug #3200 `_ - Ensure the host parameter is correctly pickup up from the service file | `Bug #3219 `_ - Update required ChromeDriver version for current versions of Chrome -| `Bug #3226 `_ - Move the field error indicators in front of the affected fields so they don't obscure spinners or drop downs etc. \ No newline at end of file +| `Bug #3226 `_ - Move the field error indicators in front of the affected fields so they don't obscure spinners or drop downs etc. +| `Bug #3244 `_ - Show more granular timing info in the query tool history panel \ No newline at end of file diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py index 724e677b3..57e8510ce 100644 --- a/web/pgadmin/browser/__init__.py +++ b/web/pgadmin/browser/__init__.py @@ -216,6 +216,19 @@ class BrowserModule(PgAdminModule): gettext("Show system objects?"), 'boolean', False, category_label=gettext('Display') ) + + self.preference.register( + 'display', 'enable_acitree_animation', + gettext("Enable browser tree animation?"), 'boolean', True, + category_label=gettext('Display') + ) + + self.preference.register( + 'display', 'enable_alertify_animation', + gettext("Enable dialogue/notification animation?"), 'boolean', + True, category_label=gettext('Display') + ) + self.table_row_count_threshold = self.preference.register( 'properties', 'table_row_count_threshold', gettext("Count rows if estimated less than"), 'integer', 2000, diff --git a/web/pgadmin/browser/static/js/browser.js b/web/pgadmin/browser/static/js/browser.js index 46b60332d..0f640a906 100644 --- a/web/pgadmin/browser/static/js/browser.js +++ b/web/pgadmin/browser/static/js/browser.js @@ -1,7 +1,7 @@ define('pgadmin.browser', [ 'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore', 'underscore.string', 'bootstrap', 'sources/pgadmin', 'pgadmin.alertifyjs', 'bundled_codemirror', - 'sources/check_node_visibility', 'pgadmin.browser.utils', 'wcdocker', + 'sources/check_node_visibility', 'sources/modify_animation', 'pgadmin.browser.utils', 'wcdocker', 'jquery.contextmenu', 'jquery.aciplugin', 'jquery.acitree', 'pgadmin.browser.messages', 'pgadmin.browser.menu', 'pgadmin.browser.panel', @@ -11,7 +11,7 @@ define('pgadmin.browser', [ 'pgadmin.browser.keyboard', ], function( gettext, url_for, require, $, _, S, Bootstrap, pgAdmin, Alertify, - codemirror, checkNodeVisibility + codemirror, checkNodeVisibility, modifyAnimation ) { window.jQuery = window.$ = $; // Some scripts do export their object in the window only. @@ -81,6 +81,8 @@ define('pgadmin.browser', [ view: { duration: 75, }, + animateRoot: true, + unanimated: false, }); b.tree = $('#tree').aciTree('api'); @@ -686,6 +688,8 @@ define('pgadmin.browser', [ success: function(res) { self.preferences_cache = res; pgBrowser.keyboardNavigation.init(); + modifyAnimation.modify_acitree_animation(self); + modifyAnimation.modify_alertify_animation(self); }, error: function(xhr) { try { @@ -1951,7 +1955,6 @@ define('pgadmin.browser', [ brace_matching: pgBrowser.utils.braceMatching, indent_with_tabs: pgBrowser.utils.is_indent_with_tabs, }, - }); /* Remove paste event mapping from CodeMirror's emacsy KeyMap binding diff --git a/web/pgadmin/preferences/static/js/preferences.js b/web/pgadmin/preferences/static/js/preferences.js index 7014d625d..8cea92208 100644 --- a/web/pgadmin/preferences/static/js/preferences.js +++ b/web/pgadmin/preferences/static/js/preferences.js @@ -1,9 +1,10 @@ define('pgadmin.preferences', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'backbone', 'pgadmin.alertifyjs', 'sources/pgadmin', 'pgadmin.backform', - 'pgadmin.browser', + 'pgadmin.browser', 'sources/modify_animation', ], function( - gettext, url_for, $, _, Backbone, Alertify, pgAdmin, Backform, pgBrowser + gettext, url_for, $, _, Backbone, Alertify, pgAdmin, Backform, pgBrowser, + modifyAnimation ) { // This defines the Preference/Options Dialog for pgAdmin IV. @@ -379,8 +380,15 @@ define('pgadmin.preferences', [ ajax: { url: url_for('preferences.index'), }, + animateRoot: true, + unanimated: false, + show: {duration: 75}, + hide: {duration: 75}, + view: {duration: 75}, }); + modifyAnimation.modify_acitree_animation(pgBrowser, jTree.aciTree('api')); + this.show(); }, setup: function() { diff --git a/web/pgadmin/static/css/alertify.noanimation.css b/web/pgadmin/static/css/alertify.noanimation.css new file mode 100644 index 000000000..6d7589a9d --- /dev/null +++ b/web/pgadmin/static/css/alertify.noanimation.css @@ -0,0 +1,41 @@ +.alertify .ajs-dimmer, +.alertify .ajs-modal, +.alertify-notifier, +.alertify-notifier .ajs-message.ajs-visible, +.alertify-notifier .ajs-message, +.alertify-notifier.ajs-center .ajs-message.ajs-visible, +.alertify-notifier.ajs-center .ajs-message +{ + -moz-transition: none; + -webkit-transition: none; + -o-transition: none; + transition: none; + -webkit-transform: none; + transform: none; +} + +.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog { + -webkit-animation-name: ajs-zoomIn; + animation-name: ajs-zoomIn; +} +.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog { + -webkit-animation-name: ajs-zoomOut; + animation-name: ajs-zoomOut; +} + +@-webkit-keyframes ajs-zoomIn { + -webkit-transform: none; + transform: none; +} +@keyframes ajs-zoomIn { + -webkit-transform: none; + transform: none; +} +@-webkit-keyframes ajs-zoomOut { + -webkit-transform: none; + transform: none; +} +@keyframes ajs-zoomeOut { + -webkit-transform: none; + transform: none; +} diff --git a/web/pgadmin/static/js/modify_animation.js b/web/pgadmin/static/js/modify_animation.js new file mode 100644 index 000000000..2e04c11c9 --- /dev/null +++ b/web/pgadmin/static/js/modify_animation.js @@ -0,0 +1,57 @@ +////////////////////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2018, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////////////////// + +import $ from 'jquery'; +import _ from 'underscore'; + +function modify_acitree_animation(pgBrowser, tree) { + if (_.isUndefined(tree)) { + tree = pgBrowser.tree; + } + var enable_acitree_animation = pgBrowser.get_preference('browser', + 'enable_acitree_animation').value; + if(enable_acitree_animation == true) { + tree.options({ + animateRoot: true, + unanimated: false, + show: _.extend(tree.options().show, {duration: 75}), + hide: _.extend(tree.options().hide, {duration: 75}), + view: _.extend(tree.options().view, {duration: 75}), + }); + } else { + tree.options({ + animateRoot: false, + unanimated: true, + show: _.extend(tree.options().show, {duration: 0}), + hide: _.extend(tree.options().hide, {duration: 0}), + view: _.extend(tree.options().view, {duration: 0}), + }); + } +} + +function modify_alertify_animation(pgBrowser) { + var enable_alertify_animation = pgBrowser.get_preference('browser', + 'enable_alertify_animation').value; + if(enable_alertify_animation == true) { + $(document).find('link#alertify-no-animation').attr('disabled', 'disabled'); + _.each(document.getElementsByTagName('iframe'), function(frame){ + $(frame.contentDocument).find('link#alertify-no-animation').attr('disabled', 'disabled'); + }); + } else { + $(document).find('link#alertify-no-animation').removeAttr('disabled', 'disabled'); + _.each(document.getElementsByTagName('iframe'), function(frame){ + $(frame.contentDocument).find('link#alertify-no-animation').removeAttr('disabled', 'disabled'); + }); + } +} + +module.exports = { + modify_acitree_animation : modify_acitree_animation, + modify_alertify_animation: modify_alertify_animation, +}; diff --git a/web/pgadmin/templates/base.html b/web/pgadmin/templates/base.html index c7a61742b..72a3156c0 100755 --- a/web/pgadmin/templates/base.html +++ b/web/pgadmin/templates/base.html @@ -23,6 +23,7 @@ + {% block css_link %}{% endblock %} diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index 56bdaf1bb..0409a879a 100644 --- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js @@ -20,6 +20,7 @@ define('tools.querytool', [ 'sources/keyboard_shortcuts', 'sources/sqleditor/query_tool_actions', 'pgadmin.datagrid', + 'sources/modify_animation', 'sources/sqleditor/calculate_query_run_time', 'sources/sqleditor/call_render_after_poll', 'sources/../bundle/slickgrid', @@ -34,7 +35,7 @@ define('tools.querytool', [ pgExplain, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent, XCellSelectionModel, setStagedRows, SqlEditorUtils, ExecuteQuery, transaction, HistoryBundle, queryHistory, React, ReactDOM, - keyboardShortcuts, queryToolActions, Datagrid, + keyboardShortcuts, queryToolActions, Datagrid, modifyAnimation, calculateQueryRunTime, callRenderAfterPoll) { /* Return back, this has been called more than once */ if (pgAdmin.SqlEditor) @@ -4292,6 +4293,8 @@ define('tools.querytool', [ pgAdmin.SqlEditor = { // This function is used to create and return the object of grid controller. create: function(container) { + var browser = (!_.isNull(window.opener)) ? window.opener.pgAdmin.Browser:window.parent.pgAdmin.Browser; + modifyAnimation.modify_alertify_animation(browser); return new SqlEditorController(container); }, jquery: $, diff --git a/web/regression/javascript/browser/modify_animation_spec.js b/web/regression/javascript/browser/modify_animation_spec.js new file mode 100644 index 000000000..b47057fb1 --- /dev/null +++ b/web/regression/javascript/browser/modify_animation_spec.js @@ -0,0 +1,94 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2018, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import $ from 'jquery' +import modifyAnimation from 'sources/modify_animation' + + +describe('modifyAnimation', function () { + let pgBrowser; + let dummyElement; + + beforeEach(() => { + pgBrowser = jasmine.createSpyObj('pgBrowser', ['get_preference', 'tree']) + pgBrowser.tree = jasmine.createSpyObj('tree', ['options']); + pgBrowser.tree.options.and.returnValue({ + show: {}, + hide: {}, + view: {}, + }); + dummyElement = document.createElement('link'); + spyOn($.fn, 'find').and.returnValue($(dummyElement)); + spyOn($.fn, 'removeAttr'); + spyOn($.fn, 'attr'); + }); + + describe('When browser tree animation is disabled', () => { + beforeEach(() => { + pgBrowser.get_preference.and.returnValue({value: false}); + modifyAnimation.modify_acitree_animation(pgBrowser); + }); + it('tree options to animate should be disabled', function() { + expect(pgBrowser.get_preference).toHaveBeenCalled(); + expect(pgBrowser.tree.options).toHaveBeenCalledTimes(4); + expect(pgBrowser.tree.options).toHaveBeenCalledWith({ + animateRoot: false, + unanimated: true, + show: {duration: 0}, + hide: {duration: 0}, + view: {duration: 0}, + }); + }); + }); + + describe('When browser tree animation is enabled', () => { + beforeEach(() => { + pgBrowser.get_preference.and.returnValue({value: true}); + modifyAnimation.modify_acitree_animation(pgBrowser); + }); + it('tree options to animate should be enabled', function() { + expect(pgBrowser.get_preference).toHaveBeenCalled(); + expect(pgBrowser.tree.options).toHaveBeenCalledTimes(4); + expect(pgBrowser.tree.options).toHaveBeenCalledWith({ + animateRoot: true, + unanimated: false, + show: {duration: 75}, + hide: {duration: 75}, + view: {duration: 75}, + }); + }); + }); + + describe('When alertify animation is disabled', () => { + beforeEach(() => { + pgBrowser.get_preference.and.returnValue({value: false}); + modifyAnimation.modify_alertify_animation(pgBrowser); + + }); + it('alertify disalogue/notification animation should be disabled', function() { + expect(pgBrowser.get_preference).toHaveBeenCalled(); + expect($.fn.find).toHaveBeenCalled(); + expect($.fn.removeAttr).toHaveBeenCalledWith('disabled', 'disabled'); + }); + }); + + describe('When alertify animation is enabled', () => { + beforeEach(() => { + pgBrowser.get_preference.and.returnValue({value: true}); + modifyAnimation.modify_alertify_animation(pgBrowser); + }); + it('alertify disalogue/notification animation should be enabled', function() { + expect(pgBrowser.get_preference).toHaveBeenCalled(); + expect($.fn.find).toHaveBeenCalled(); + expect($.fn.attr).toHaveBeenCalledWith('disabled', 'disabled'); + }); + }); + +}); +