diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py index c8bc02b0b..fe2d3e5b0 100644 --- a/web/pgadmin/tools/datagrid/__init__.py +++ b/web/pgadmin/tools/datagrid/__init__.py @@ -24,6 +24,7 @@ from pgadmin.utils.ajax import make_json_response, bad_request, \ internal_server_error from config import PG_DEFAULT_DRIVER +from pgadmin.utils.preferences import Preferences class DataGridModule(PgAdminModule): @@ -135,7 +136,11 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id): # Store the grid dictionary into the session variable session['gridData'] = sql_grid_data - return make_json_response(data={'gridTransId': trans_id}) + pref = Preferences.module('sqleditor') + new_browser_tab = pref.preference('new_browser_tab').get() + + return make_json_response(data={'gridTransId': trans_id, + 'newBrowserTab': new_browser_tab}) @blueprint.route('/panel///', methods=["GET"]) @@ -171,10 +176,18 @@ def panel(trans_id, is_query_tool, editor_title): if "linux" in _platform: is_linux_platform = True + pref = Preferences.module('sqleditor') + if pref.preference('new_browser_tab').get(): + new_browser_tab = 'true' + else: + new_browser_tab = 'false' + return render_template("datagrid/index.html", _=gettext, uniqueId=trans_id, - is_query_tool=is_query_tool, editor_title=editor_title, - script_type_url=sURL, is_desktop_mode=app.PGADMIN_RUNTIME, - is_linux=is_linux_platform) + is_query_tool=is_query_tool, + editor_title=editor_title, script_type_url=sURL, + is_desktop_mode=app.PGADMIN_RUNTIME, + is_linux=is_linux_platform, + is_new_browser_tab=new_browser_tab) @blueprint.route( @@ -234,7 +247,11 @@ def initialize_query_tool(sid, did=None): # Store the grid dictionary into the session variable session['gridData'] = sql_grid_data - return make_json_response(data={'gridTransId': trans_id}) + pref = Preferences.module('sqleditor') + new_browser_tab = pref.preference('new_browser_tab').get() + + return make_json_response(data={'gridTransId': trans_id, + 'newBrowserTab': new_browser_tab}) @blueprint.route('/close/', methods=["GET"]) diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/index.html b/web/pgadmin/tools/datagrid/templates/datagrid/index.html index 72ce75164..81c6fd5f7 100644 --- a/web/pgadmin/tools/datagrid/templates/datagrid/index.html +++ b/web/pgadmin/tools/datagrid/templates/datagrid/index.html @@ -310,7 +310,8 @@ function($, pgAdmin, R, S) { {% endif %} // Start the query tool. - sqlEditorController.start({{ is_query_tool }}, "{{ editor_title }}", script_sql); + sqlEditorController.start({{ is_query_tool }}, "{{ editor_title }}", + script_sql, {{ is_new_browser_tab }}); }); }); {% endblock %} diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/js/datagrid.js b/web/pgadmin/tools/datagrid/templates/datagrid/js/datagrid.js index f568fa1d0..e8e403388 100644 --- a/web/pgadmin/tools/datagrid/templates/datagrid/js/datagrid.js +++ b/web/pgadmin/tools/datagrid/templates/datagrid/js/datagrid.js @@ -327,39 +327,57 @@ define( var panel_title = ' Query-' + self.title_index; self.title_index += 1; - var dashboardPanel = pgBrowser.docker.findPanels('dashboard'); - dataGridPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, dashboardPanel[0]); - dataGridPanel.title(panel_title); - dataGridPanel.icon('fa fa-bolt'); - dataGridPanel.focus(); - - // Listen on the panel closed event. - dataGridPanel.on(wcDocker.EVENT.CLOSED, function() { - $.ajax({ - url: "{{ url_for('datagrid.index') }}" + "close/" + res.data.gridTransId, - method: 'GET' - }); - }); - - // Open the panel if frame is initialized baseUrl = "{{ url_for('datagrid.index') }}" + "panel/" + res.data.gridTransId + "/false/" + encodeURIComponent(grid_title); - var openDataGridURL = function(j) { - j.data('embeddedFrame').$container.append(self.spinner_el); - setTimeout(function() { - var frameInitialized = j.data('frameInitialized'); - if (frameInitialized) { - var frame = j.data('embeddedFrame'); - if (frame) { - frame.openURL(baseUrl); - frame.$container.find('.wcLoadingContainer').hide(1); - } - } else { + + if (res.data.newBrowserTab) { + var newWin = window.open(baseUrl, '_blank'); + + // Listen on the window closed event. + newWin.addEventListener("unload", function(e){ + $.ajax({ + url: "{{ url_for('datagrid.index') }}" + "close/" + res.data.gridTransId, + method: 'GET' + }); + }, false); + + // add a load listener to the window so that the title gets changed on page load + newWin.addEventListener("load", function() { + newWin.document.title = panel_title; + }); + } else { + var dashboardPanel = pgBrowser.docker.findPanels('dashboard'); + dataGridPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, dashboardPanel[0]); + dataGridPanel.title(panel_title); + dataGridPanel.icon('fa fa-bolt'); + dataGridPanel.focus(); + + // Listen on the panel closed event. + dataGridPanel.on(wcDocker.EVENT.CLOSED, function() { + $.ajax({ + url: "{{ url_for('datagrid.index') }}" + "close/" + res.data.gridTransId, + method: 'GET' + }); + }); + + var openDataGridURL = function(j) { + j.data('embeddedFrame').$container.append(self.spinner_el); + setTimeout(function() { + var frameInitialized = j.data('frameInitialized'); + if (frameInitialized) { + var frame = j.data('embeddedFrame'); + if (frame) { + frame.openURL(baseUrl); + frame.$container.find('.wcLoadingContainer').hide(1); + } + } else { openDataGridURL(j); - } - }, 100); - }; - openDataGridURL($(dataGridPanel)); + } + }, 100); + }; + + openDataGridURL($(dataGridPanel)); + } }, error: function(e) { alertify.alert( @@ -422,42 +440,61 @@ define( contentType: "application/json", success: function(res) { - /* On successfully initialization find the dashboard panel, - * create new panel and add it to the dashboard panel. - */ - var dashboardPanel = pgBrowser.docker.findPanels('dashboard'); - queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, dashboardPanel[0]); - queryToolPanel.title(panel_title); - queryToolPanel.icon('fa fa-bolt'); - queryToolPanel.focus(); - - // Listen on the panel closed event. - queryToolPanel.on(wcDocker.EVENT.CLOSED, function() { - $.ajax({ - url: "{{ url_for('datagrid.index') }}" + "close/" + res.data.gridTransId, - method: 'GET' - }); - }); - // Open the panel if frame is initialized baseUrl = "{{ url_for('datagrid.index') }}" + "panel/" + res.data.gridTransId + "/true/" + encodeURIComponent(grid_title) + '?' + "query_url=" + encodeURI(sURL); - var openQueryToolURL = function(j) { - j.data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el); - setTimeout(function() { - var frameInitialized = j.data('frameInitialized'); - if (frameInitialized) { - var frame = j.data('embeddedFrame'); - if (frame) { - frame.openURL(baseUrl); - frame.$container.find('.wcLoadingContainer').delay(1000).hide(1); + + if (res.data.newBrowserTab) { + var newWin = window.open(baseUrl, '_blank'); + + // Listen on the window closed event. + newWin.addEventListener("unload", function(e){ + $.ajax({ + url: "{{ url_for('datagrid.index') }}" + "close/" + res.data.gridTransId, + method: 'GET' + }); + }, false); + + // add a load listener to the window so that the title gets changed on page load + newWin.addEventListener("load", function() { + newWin.document.title = panel_title; + }); + } else { + /* On successfully initialization find the dashboard panel, + * create new panel and add it to the dashboard panel. + */ + var dashboardPanel = pgBrowser.docker.findPanels('dashboard'); + queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, dashboardPanel[0]); + queryToolPanel.title(panel_title); + queryToolPanel.icon('fa fa-bolt'); + queryToolPanel.focus(); + + // Listen on the panel closed event. + queryToolPanel.on(wcDocker.EVENT.CLOSED, function() { + $.ajax({ + url: "{{ url_for('datagrid.index') }}" + "close/" + res.data.gridTransId, + method: 'GET' + }); + }); + + var openQueryToolURL = function(j) { + j.data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el); + setTimeout(function() { + var frameInitialized = j.data('frameInitialized'); + if (frameInitialized) { + var frame = j.data('embeddedFrame'); + if (frame) { + frame.openURL(baseUrl); + frame.$container.find('.wcLoadingContainer').delay(1000).hide(1); + } + } else { + openQueryToolURL(j); } - } else { - openQueryToolURL(j); - } - }, 100); - }; - openQueryToolURL($(queryToolPanel)); + }, 100); + }; + + openQueryToolURL($(queryToolPanel)); + } }, error: function(e) { alertify.alert( diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py index f34952f6a..2154d342e 100644 --- a/web/pgadmin/tools/debugger/__init__.py +++ b/web/pgadmin/tools/debugger/__init__.py @@ -25,6 +25,7 @@ from pgadmin.utils.driver import get_driver from config import PG_DEFAULT_DRIVER from pgadmin.model import db, DebuggerFunctionArguments +from pgadmin.utils.preferences import Preferences # Constants ASYNC_OK = 1 @@ -42,6 +43,7 @@ class DebuggerModule(PgAdminModule): - Method is used to load the required javascript files for debugger module """ + LABEL = gettext("Debugger") def get_own_javascripts(self): scripts = list() @@ -58,6 +60,14 @@ class DebuggerModule(PgAdminModule): return scripts + def register_preferences(self): + self.open_in_new_tab = self.preference.register( + 'display', 'debugger_new_browser_tab', + gettext("Open in New Browser Tab"), 'boolean', False, + category_label=gettext('Display'), + help_str=gettext('If set to True, the Debugger ' + 'will be opened in a new browser tab.') + ) blueprint = DebuggerModule(MODULE_NAME, __name__) @@ -317,7 +327,7 @@ def direct_new(trans_id): return render_template( "debugger/direct.html", _=gettext, - function_name='test', + function_name=obj['function_name'], uniqueId=trans_id, debug_type=debug_type, is_desktop_mode=current_app.PGADMIN_RUNTIME, @@ -435,6 +445,7 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None): 'database_id': did, 'schema_id': scid, 'function_id': func_id, + 'function_name': session['funcData']['name'], 'debug_type': debug_type, 'debugger_version': debugger_version, 'frame_id': 0, @@ -478,7 +489,13 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None): # Delete the 'funcData' session variables as it is not used now as target is initialized del session['funcData'] - return make_json_response(data={'status': status, 'debuggerTransId': trans_id}) + pref = Preferences.module('debugger') + new_browser_tab = pref.preference('debugger_new_browser_tab').get() + + + return make_json_response(data={'status': status, + 'debuggerTransId': trans_id, + 'newBrowserTab': new_browser_tab}) @blueprint.route('/close/', methods=["GET"]) diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js b/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js index 8a8b14eb3..ad1858c8d 100644 --- a/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js +++ b/web/pgadmin/tools/debugger/templates/debugger/js/debugger.js @@ -241,14 +241,26 @@ define( success: function(res) { var url = "{{ url_for('debugger.index') }}" + "direct/" + res.data.debuggerTransId; - pgBrowser.Events.once( - 'pgadmin-browser:frame:urlloaded:frm_debugger', function(frame) { - frame.openURL(url); - }); + if (res.data.newBrowserTab) { + var newWin = window.open(url, '_blank'); - // Create the debugger panel as per the data received from user input dialog. - var dashboardPanel = pgBrowser.docker.findPanels( - 'dashboard' + // Listen on the window closed event. + newWin.addEventListener("unload", function(e){ + var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; + $.ajax({ + url: closeUrl, + method: 'GET' + }); + }, false); + } else { + pgBrowser.Events.once( + 'pgadmin-browser:frame:urlloaded:frm_debugger', function(frame) { + frame.openURL(url); + }); + + // Create the debugger panel as per the data received from user input dialog. + var dashboardPanel = pgBrowser.docker.findPanels( + 'dashboard' ), panel = pgBrowser.docker.addPanel( 'frm_debugger', wcDocker.DOCK.STACKED, dashboardPanel[0] @@ -264,12 +276,13 @@ define( method: 'GET' }); }); - }, - error: function(e) { - Alertify.alert( - 'Debugger target Initialize Error' - ); } + }, + error: function(e) { + Alertify.alert( + 'Debugger target initialization error' + ); + } }); }, @@ -331,29 +344,42 @@ define( var url = "{{ url_for('debugger.index') }}" + "direct/" + res.data.debuggerTransId; - pgBrowser.Events.once( - 'pgadmin-browser:frame:urlloaded:frm_debugger', function(frame) { - frame.openURL(url); - }); + if (res.data.newBrowserTab) { + var newWin = window.open(url, '_blank'); - // Create the debugger panel as per the data received from user input dialog. - var dashboardPanel = pgBrowser.docker.findPanels( - 'dashboard' - ), - panel = pgBrowser.docker.addPanel( - 'frm_debugger', wcDocker.DOCK.STACKED, dashboardPanel[0] - ); - - panel.focus(); - - // Register Panel Closed event - panel.on(wcDocker.EVENT.CLOSED, function() { - var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; - $.ajax({ - url: closeUrl, - method: 'GET' + // Listen on the window closed event. + newWin.addEventListener("unload", function(e){ + var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; + $.ajax({ + url: closeUrl, + method: 'GET' + }); + }, false); + } else { + pgBrowser.Events.once( + 'pgadmin-browser:frame:urlloaded:frm_debugger', function(frame) { + frame.openURL(url); }); - }); + + // Create the debugger panel as per the data received from user input dialog. + var dashboardPanel = pgBrowser.docker.findPanels( + 'dashboard' + ), + panel = pgBrowser.docker.addPanel( + 'frm_debugger', wcDocker.DOCK.STACKED, dashboardPanel[0] + ); + + panel.focus(); + + // Register Panel Closed event + panel.on(wcDocker.EVENT.CLOSED, function() { + var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; + $.ajax({ + url: closeUrl, + method: 'GET' + }); + }); + } }, error: function(e) { Alertify.alert( diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js b/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js index 97b9bfe8d..5af7c8be0 100644 --- a/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js +++ b/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js @@ -553,29 +553,40 @@ define( var url = "{{ url_for('debugger.index') }}" + "direct/" + res.data.debuggerTransId; - pgBrowser.Events.once( - 'pgadmin-browser:frame:urlloaded:frm_debugger', function(frame) { - frame.openURL(url); - }); + if (res.data.newBrowserTab) { + var newWin = window.open(url, '_blank'); - // Create the debugger panel as per the data received from user input dialog. - var dashboardPanel = pgBrowser.docker.findPanels( - 'dashboard' - ), - panel = pgBrowser.docker.addPanel( - 'frm_debugger', wcDocker.DOCK.STACKED, dashboardPanel[0] - ); - - panel.focus(); - - // Panel Closed event - panel.on(wcDocker.EVENT.CLOSED, function() { - var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; - $.ajax({ - url: closeUrl, - method: 'GET' + // Listen on the window closed event. + newWin.addEventListener("unload", function(e){ + var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; + $.ajax({ + url: closeUrl, + method: 'GET' + }); + }, false); + } else { + pgBrowser.Events.once( + 'pgadmin-browser:frame:urlloaded:frm_debugger', function(frame) { + frame.openURL(url); }); - }); + + // Create the debugger panel as per the data received from user input dialog. + var dashboardPanel = pgBrowser.docker.findPanels('dashboard'), + panel = pgBrowser.docker.addPanel( + 'frm_debugger', wcDocker.DOCK.STACKED, dashboardPanel[0] + ); + + panel.focus(); + + // Panel Closed event + panel.on(wcDocker.EVENT.CLOSED, function() { + var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; + $.ajax({ + url: closeUrl, + method: 'GET' + }); + }); + } if (d._type == "function") { var _Url = "{{ url_for('debugger.index') }}" + "set_arguments/" + treeInfo.server._id + diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py index 70750c947..f08b02e7e 100644 --- a/web/pgadmin/tools/sqleditor/__init__.py +++ b/web/pgadmin/tools/sqleditor/__init__.py @@ -84,6 +84,14 @@ class SqlEditorModule(PgAdminModule): 'Values greater than 1 display the notifier for the number of seconds specified.') ) + self.open_in_new_tab = self.preference.register( + 'display', 'new_browser_tab', + gettext("Open in New Browser Tab"), 'boolean', False, + category_label=gettext('Display'), + help_str=gettext('If set to True, the Query Tool ' + 'will be opened in a new browser tab.') + ) + self.explain_verbose = self.preference.register( 'Explain', 'explain_verbose', gettext("Verbose output?"), 'boolean', False, diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js index fe6aaefd6..eed0e0964 100644 --- a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js @@ -228,36 +228,38 @@ define( self.render_history_grid(); - // Listen on the panel closed event and notify user to save modifications. - _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) { - if(p.isVisible()) { - p.on(wcDocker.EVENT.CLOSING, function() { - // Only if we can edit data then perform this check - var notify = false, msg; - if(self.handler.can_edit) { - var data_store = self.handler.data_store; - if(data_store && (_.size(data_store.added) || - _.size(data_store.updated))) { - msg = "{{ _('The data has been modified, but not saved. Are you sure you wish to discard the changes?') }}"; + if (!self.handler.is_new_browser_tab) { + // Listen on the panel closed event and notify user to save modifications. + _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) { + if(p.isVisible()) { + p.on(wcDocker.EVENT.CLOSING, function() { + // Only if we can edit data then perform this check + var notify = false, msg; + if(self.handler.can_edit) { + var data_store = self.handler.data_store; + if(data_store && (_.size(data_store.added) || + _.size(data_store.updated))) { + msg = "{{ _('The data has been modified, but not saved. Are you sure you wish to discard the changes?') }}"; + notify = true; + } + } else if(self.handler.is_query_tool && self.handler.is_query_changed) { + msg = "{{ _('The query has been modified, but not saved. Are you sure you wish to discard the changes?') }}"; notify = true; } - } else if(self.handler.is_query_tool && self.handler.is_query_changed) { - msg = "{{ _('The query has been modified, but not saved. Are you sure you wish to discard the changes?') }}"; - notify = true; - } - if(notify) {return self.user_confirmation(p, msg);} - return true; - }); - // Set focus on query tool of active panel - p.on(wcDocker.EVENT.GAIN_FOCUS, function() { - if (!$(p.$container).hasClass('wcPanelTabContentHidden')) { - setTimeout(function() { - self.handler.gridView.query_tool_obj.focus(); - }, 200); - } - }); - } - }); + if(notify) {return self.user_confirmation(p, msg);} + return true; + }); + // Set focus on query tool of active panel + p.on(wcDocker.EVENT.GAIN_FOCUS, function() { + if (!$(p.$container).hasClass('wcPanelTabContentHidden')) { + setTimeout(function() { + self.handler.gridView.query_tool_obj.focus(); + }, 200); + } + }); + } + }); + } // set focus on query tool once loaded setTimeout(function() { @@ -1517,7 +1519,7 @@ define( * call the render method of the grid view to render the backgrid * header and loading icon and start execution of the sql query. */ - start: function(is_query_tool, editor_title, script_sql) { + start: function(is_query_tool, editor_title, script_sql, is_new_browser_tab) { var self = this; self.is_query_tool = is_query_tool; @@ -1527,6 +1529,7 @@ define( self.explain_costs = false; self.explain_buffers = false; self.explain_timing = false; + self.is_new_browser_tab = is_new_browser_tab; // We do not allow to call the start multiple times. if (self.gridView) @@ -2423,11 +2426,17 @@ define( // Set panel title. setTitle: function(title) { - _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) { - if(p.isVisible()) { - p.title(decodeURIComponent(title)); - } - }); + var self = this; + + if (self.is_new_browser_tab) { + window.document.title = title; + } else { + _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) { + if(p.isVisible()) { + p.title(decodeURIComponent(title)); + } + }); + } }, // load select file dialog @@ -2571,14 +2580,18 @@ define( } else { var title = ''; - // Find the title of the visible panel - _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) { - if(p.isVisible()) { - self.gridView.panel_title = p._title; - } - }); + if (self.is_new_browser_tab) { + title = window.document.title + ' *'; + } else { + // Find the title of the visible panel + _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function(p) { + if(p.isVisible()) { + self.gridView.panel_title = p._title; + } + }); - title = self.gridView.panel_title + ' *'; + title = self.gridView.panel_title + ' *'; + } self.setTitle(title); }