Make Statistics, Dependencies, Dependants tabs closable and the user can add them back using the 'Add panel' option. Fixes #5091

This commit is contained in:
Aditya Toshniwal 2021-02-03 12:46:32 +05:30 committed by Akshay Joshi
parent 18f055fa5e
commit 73b6b95fbc
7 changed files with 338 additions and 272 deletions

View File

@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o
New features New features
************ ************
| `Issue #5091 <https://redmine.postgresql.org/issues/5091>`_ - Make Statistics, Dependencies, Dependants tabs closable and the user can add them back using the 'Add panel' option.
| `Issue #5912 <https://redmine.postgresql.org/issues/5912>`_ - Added support for Logical Replication. | `Issue #5912 <https://redmine.postgresql.org/issues/5912>`_ - Added support for Logical Replication.
| `Issue #5967 <https://redmine.postgresql.org/issues/5967>`_ - Implemented runtime using NWjs to open pgAdmin4 in a standalone window instead of the system tray and web browser. | `Issue #5967 <https://redmine.postgresql.org/issues/5967>`_ - Implemented runtime using NWjs to open pgAdmin4 in a standalone window instead of the system tray and web browser.
| `Issue #6148 <https://redmine.postgresql.org/issues/6148>`_ - Added Quick Search functionality for menu items and help articles. | `Issue #6148 <https://redmine.postgresql.org/issues/6148>`_ - Added Quick Search functionality for menu items and help articles.

View File

@ -251,8 +251,9 @@ define('pgadmin.browser', [
title: gettext('Statistics'), title: gettext('Statistics'),
icon: '', icon: '',
width: 500, width: 500,
isCloseable: false, isCloseable: true,
isPrivate: true, isPrivate: false,
canHide: true,
content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-statistics-message">' + select_object_msg + '</div><div class="pg-panel-statistics-container d-none"></div></div>', content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-statistics-message">' + select_object_msg + '</div><div class="pg-panel-statistics-container d-none"></div></div>',
events: panelEvents, events: panelEvents,
}), }),
@ -272,8 +273,9 @@ define('pgadmin.browser', [
title: gettext('Dependencies'), title: gettext('Dependencies'),
icon: '', icon: '',
width: 500, width: 500,
isCloseable: false, isCloseable: true,
isPrivate: true, isPrivate: false,
canHide: true,
content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependencies-container d-none"></div></div>', content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependencies-container d-none"></div></div>',
events: panelEvents, events: panelEvents,
}), }),
@ -283,8 +285,9 @@ define('pgadmin.browser', [
title: gettext('Dependents'), title: gettext('Dependents'),
icon: '', icon: '',
width: 500, width: 500,
isCloseable: false, isCloseable: true,
isPrivate: true, isPrivate: false,
canHide: true,
content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>', content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>',
events: panelEvents, events: panelEvents,
}), }),

View File

@ -183,26 +183,26 @@ define(
} }
}, },
handleVisibility: function(eventName) { handleVisibility: function(eventName) {
// Currently this function only works with dashboard panel but // Supported modules
// as per need it can be extended let type_module = {
if (this._type != 'dashboard' || _.isUndefined(pgAdmin.Dashboard)) 'dashboard': pgAdmin.Dashboard,
'statistics': pgBrowser.NodeStatistics,
'dependencies': pgBrowser.NodeDependencies,
'dependents': pgBrowser.NodeDependents,
};
let module = type_module[this._type];
if(_.isUndefined(module))
return;
if(_.isUndefined(module.toggleVisibility))
return; return;
if (eventName == 'panelClosed') { if (eventName == 'panelClosed') {
/* Pass the closed flag also */ /* Pass the closed flag also */
pgAdmin.Dashboard.toggleVisibility(false, true); module.toggleVisibility.call(module, [false, true]);
} else if (eventName == 'panelVisibilityChanged') { } else if (eventName == 'panelVisibilityChanged') {
if (pgBrowser.tree) { module.toggleVisibility.call(module, [pgBrowser.docker.findPanels(this._type)[0].isVisible()]);
var selectedNode = pgBrowser.tree.selected();
if (!_.isUndefined(pgAdmin.Dashboard)) {
pgAdmin.Dashboard.toggleVisibility(pgBrowser.panels.dashboard.panel.isVisible());
}
// Explicitly trigger tree selected event when we add the tab.
if(selectedNode.length) {
pgBrowser.Events.trigger('pgadmin-browser:tree:selected', selectedNode,
pgBrowser.tree.itemData(selectedNode), pgBrowser.Node);
}
}
} }
}, },

View File

@ -225,7 +225,6 @@ define('pgadmin.dashboard', [
var dashboardPanel = pgBrowser.panels['dashboard'].panel; var dashboardPanel = pgBrowser.panels['dashboard'].panel;
if (dashboardPanel) { if (dashboardPanel) {
var div = dashboardPanel.layout().scene().find('.pg-panel-content'); var div = dashboardPanel.layout().scene().find('.pg-panel-content');
if (div) { if (div) {
var ajaxHook = function() { var ajaxHook = function() {
$.ajax({ $.ajax({
@ -1100,7 +1099,13 @@ define('pgadmin.dashboard', [
if(closed) { if(closed) {
this.chartsDomObj && this.chartsDomObj.unmount(); this.chartsDomObj && this.chartsDomObj.unmount();
} else { } else {
var t = pgBrowser.tree,
i = t.selected(),
d = i && t.itemData(i),
n = i && d && pgBrowser.Nodes[d._type];
this.chartsDomObj && this.chartsDomObj.setPageVisible(dashboardVisible); this.chartsDomObj && this.chartsDomObj.setPageVisible(dashboardVisible);
this.object_selected(i, d, n);
} }
}, },
can_take_action: function(m) { can_take_action: function(m) {

View File

@ -31,7 +31,8 @@ define('misc.dependencies', [
/* Parameter is used to set the proper label of the /* Parameter is used to set the proper label of the
* backgrid header cell. * backgrid header cell.
*/ */
_.bindAll(this, 'showDependencies', '__loadMoreRows', '__appendGridToPanel'); _.bindAll(this, 'showDependencies', '__updateCollection', '__loadMoreRows',
'__appendGridToPanel', 'toggleVisibility');
// Defining Backbone Model for Dependencies. // Defining Backbone Model for Dependencies.
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
@ -63,8 +64,28 @@ define('misc.dependencies', [
model: Model, model: Model,
}))(null); }))(null);
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependencies); if(this.dependenciesPanel) this.toggleVisibility(this.dependenciesPanel.isVisible());
this.__appendGridToPanel(); },
toggleVisibility: function(visible, closed=false) {
if (visible) {
this.dependenciesPanel = pgBrowser.docker.findPanels('dependencies')[0];
var t = pgBrowser.tree,
i = t.selected(),
d = i && t.itemData(i),
n = i && d && pgBrowser.Nodes[d._type];
this.showDependencies(i, d, n);
// We will start listening the tree selection event.
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependencies);
} else {
if(closed) {
$(this.dependenciesPanel).data('node-prop', '');
}
// We don't need to listen the tree item selection event.
pgBrowser.Events.off('pgadmin-browser:tree:selected', this.showDependencies);
}
}, },
/* Function is used to create and render backgrid with /* Function is used to create and render backgrid with
@ -112,6 +133,7 @@ define('misc.dependencies', [
// Condition is used to save grid object to change the label of the header. // Condition is used to save grid object to change the label of the header.
this.dependenciesGrid = grid; this.dependenciesGrid = grid;
$gridContainer.empty();
$gridContainer.append(grid.render().el); $gridContainer.append(grid.render().el);
return true; return true;
@ -119,15 +141,34 @@ define('misc.dependencies', [
// Fetch the actual data and update the collection // Fetch the actual data and update the collection
showDependencies: function(item, data, node) { showDependencies: function(item, data, node) {
if (!node) {
return;
}
/**
* We can't start fetching the statistics immediately, it is possible -
* the user is just using keyboards to select the node, and just
* traversing through.
*
* We will wait for some time before fetching
**/
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => {
this.__updateCollection(node.generate_url(item, 'dependency', data, true), node, item, data._type);
}, 400);
},
// Fetch the actual data and update the collection
__updateCollection: function(url, node, item, node_type) {
let self = this, let self = this,
msg = gettext('Please select an object in the tree view.'), msg = gettext('Please select an object in the tree view.'),
panel = this.dependenciesPanel, panel = this.dependenciesPanel,
$container = panel.layout().scene().find('.pg-panel-content'), $container = panel.layout().scene().find('.pg-panel-content'),
$msgContainer = $container.find('.pg-panel-depends-message'), $msgContainer = $container.find('.pg-panel-depends-message'),
$gridContainer = $container.find('.pg-panel-dependencies-container'), $gridContainer = $container.find('.pg-panel-dependencies-container'),
treeHierarchy = node.getTreeNodeHierarchy(item), treeHierarchy = node.getTreeNodeHierarchy(item);
n_type = data._type,
url = node.generate_url(item, 'dependency', data, true);
if (node) { if (node) {
/* We fetch the Dependencies and Dependencies tab only for /* We fetch the Dependencies and Dependencies tab only for
@ -135,12 +176,24 @@ define('misc.dependencies', [
*/ */
msg = gettext('No dependency information is available for the selected object.'); msg = gettext('No dependency information is available for the selected object.');
if (node.hasDepends) { if (node.hasDepends) {
// Avoid unnecessary reloads
var cache_flag = {
node_type: node_type,
url: url,
};
if (_.isEqual($(panel).data('node-prop'), cache_flag)) {
return;
}
// Cache the current IDs for next time
$(panel).data('node-prop', cache_flag);
/* Updating the label for the 'field' type of the backbone model. /* Updating the label for the 'field' type of the backbone model.
* Label should be "Database" if the node type is tablespace or role * Label should be "Database" if the node type is tablespace or role
* and dependencies tab is selected. For other nodes and dependencies tab * and dependencies tab is selected. For other nodes and dependencies tab
* it should be 'Restriction'. * it should be 'Restriction'.
*/ */
self.__appendGridToPanel();
this.dependenciesGrid.columns.models[2].set({ this.dependenciesGrid.columns.models[2].set({
'label': gettext('Restriction'), 'label': gettext('Restriction'),
}); });
@ -150,85 +203,87 @@ define('misc.dependencies', [
$gridContainer.removeClass('d-none'); $gridContainer.removeClass('d-none');
var timer = ''; var timer = '';
$.ajax({ var ajaxHook = function() {
url: url, $.ajax({
type: 'GET', url: url,
beforeSend: function(xhr) { type: 'GET',
xhr.setRequestHeader(pgAdmin.csrf_token_header, pgAdmin.csrf_token); beforeSend: function(xhr) {
// Generate a timer for the request xhr.setRequestHeader(pgAdmin.csrf_token_header, pgAdmin.csrf_token);
timer = setTimeout(function() { // Generate a timer for the request
// notify user if request is taking longer than 1 second timer = setTimeout(function() {
// notify user if request is taking longer than 1 second
$msgContainer.text(gettext('Fetching dependency information from the server...'));
$msgContainer.removeClass('d-none');
msg = '';
}, 1000);
},
})
.done(function(res) {
clearTimeout(timer);
if (res.length > 0) {
if (!$msgContainer.hasClass('d-none')) {
$msgContainer.addClass('d-none');
}
$gridContainer.removeClass('d-none');
self.dependenciesData = res;
// Load only 100 rows
self.dependenciesCollection.reset(self.dependenciesData.splice(0, 100), {parse: true});
// Load more rows on scroll down
pgBrowser.Events.on(
'pgadmin-browser:panel-dependencies:' +
wcDocker.EVENT.SCROLLED,
self.__loadMoreRows
);
} else {
// Do not listen the scroll event
pgBrowser.Events.off(
'pgadmin-browser:panel-dependencies:' +
wcDocker.EVENT.SCROLLED
);
self.dependenciesCollection.reset({silent: true});
$msgContainer.text(msg);
$msgContainer.removeClass('d-none');
if (!$gridContainer.hasClass('d-none')) {
$gridContainer.addClass('d-none');
}
}
$msgContainer.text(gettext('Fetching dependency information from the server...'));
$msgContainer.removeClass('d-none');
msg = '';
}, 1000);
},
}) })
.fail(function(xhr, error, message) { .done(function(res) {
var _label = treeHierarchy[n_type].label; clearTimeout(timer);
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'depends', xhr, error, message if (res.length > 0) {
);
if (!Alertify.pgHandleItemError(xhr, error, message, { if (!$msgContainer.hasClass('d-none')) {
item: item, $msgContainer.addClass('d-none');
info: treeHierarchy, }
})) { $gridContainer.removeClass('d-none');
Alertify.pgNotifier(
error, xhr, self.dependenciesData = res;
gettext('Error retrieving data from the server: %s', message || _label),
function(alertMsg) { // Load only 100 rows
if(alertMsg === 'CRYPTKEY_SET') { self.dependenciesCollection.reset(self.dependenciesData.splice(0, 100), {parse: true});
self.showDependencies(item, data, node);
} else { // Load more rows on scroll down
console.warn(arguments); pgBrowser.Events.on(
} 'pgadmin-browser:panel-dependencies:' +
}); wcDocker.EVENT.SCROLLED,
} self.__loadMoreRows
// show failed message. );
$msgContainer.text(gettext('Failed to retrieve data from the server.')); } else {
}); // Do not listen the scroll event
pgBrowser.Events.off(
'pgadmin-browser:panel-dependencies:' +
wcDocker.EVENT.SCROLLED
);
self.dependenciesCollection.reset({silent: true});
$msgContainer.text(msg);
$msgContainer.removeClass('d-none');
if (!$gridContainer.hasClass('d-none')) {
$gridContainer.addClass('d-none');
}
}
})
.fail(function(xhr, error, message) {
var _label = treeHierarchy[node_type].label;
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'depends', xhr, error, message
);
if (!Alertify.pgHandleItemError(xhr, error, message, {
item: item,
info: treeHierarchy,
})) {
Alertify.pgNotifier(
error, xhr,
gettext('Error retrieving data from the server: %s', message || _label),
function(alertMsg) {
if(alertMsg === 'CRYPTKEY_SET') {
ajaxHook();
} else {
console.warn(arguments);
}
});
}
// show failed message.
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
});
};
ajaxHook();
} }
} }
if (msg != '') { if (msg != '') {

View File

@ -31,7 +31,8 @@ define('misc.dependents', [
/* Parameter is used to set the proper label of the /* Parameter is used to set the proper label of the
* backgrid header cell. * backgrid header cell.
*/ */
_.bindAll(this, 'showDependents', '__loadMoreRows', '__appendGridToPanel'); _.bindAll(this, 'showDependents', '__updateCollection', '__loadMoreRows',
'__appendGridToPanel', 'toggleVisibility');
// Defining Backbone Model for Dependents. // Defining Backbone Model for Dependents.
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
@ -63,9 +64,28 @@ define('misc.dependents', [
model: Model, model: Model,
}))(null); }))(null);
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependents); if(this.dependentsPanel) this.toggleVisibility(this.dependentsPanel.isVisible());
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', this.refreshDependents, this); },
this.__appendGridToPanel();
toggleVisibility: function(visible, closed=false) {
if (visible) {
this.dependentsPanel = pgBrowser.docker.findPanels('dependents')[0];
var t = pgBrowser.tree,
i = t.selected(),
d = i && t.itemData(i),
n = i && d && pgBrowser.Nodes[d._type];
this.showDependents(i, d, n);
// We will start listening the tree selection event.
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependents);
} else {
if(closed) {
$(this.dependentsPanel).data('node-prop', '');
}
// We don't need to listen the tree item selection event.
pgBrowser.Events.off('pgadmin-browser:tree:selected', this.showDependents);
}
}, },
/* Function is used to create and render backgrid with /* Function is used to create and render backgrid with
@ -113,6 +133,7 @@ define('misc.dependents', [
// Condition is used to save grid object to change the label of the header. // Condition is used to save grid object to change the label of the header.
this.dependentGrid = grid; this.dependentGrid = grid;
$gridContainer.empty();
$gridContainer.append(grid.render().el); $gridContainer.append(grid.render().el);
return true; return true;
@ -120,15 +141,34 @@ define('misc.dependents', [
// Fetch the actual data and update the collection // Fetch the actual data and update the collection
showDependents: function(item, data, node) { showDependents: function(item, data, node) {
if (!node) {
return;
}
/**
* We can't start fetching the statistics immediately, it is possible -
* the user is just using keyboards to select the node, and just
* traversing through.
*
* We will wait for some time before fetching
**/
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(() => {
this.__updateCollection(node.generate_url(item, 'dependent', data, true), node, item, data._type);
}, 400);
},
// Fetch the actual data and update the collection
__updateCollection: function(url, node, item, node_type) {
let self = this, let self = this,
msg = gettext('Please select an object in the tree view.'), msg = gettext('Please select an object in the tree view.'),
panel = this.dependentsPanel, panel = this.dependentsPanel,
$container = panel.layout().scene().find('.pg-panel-content'), $container = panel.layout().scene().find('.pg-panel-content'),
$msgContainer = $container.find('.pg-panel-depends-message'), $msgContainer = $container.find('.pg-panel-depends-message'),
$gridContainer = $container.find('.pg-panel-dependents-container'), $gridContainer = $container.find('.pg-panel-dependents-container'),
treeHierarchy = node.getTreeNodeHierarchy(item), treeHierarchy = node.getTreeNodeHierarchy(item);
n_type = data._type,
url = node.generate_url(item, 'dependent', data, true);
if (node) { if (node) {
/* We fetch the Dependencies and Dependents tab only for /* We fetch the Dependencies and Dependents tab only for
@ -136,11 +176,23 @@ define('misc.dependents', [
*/ */
msg = gettext('No dependent information is available for the selected object.'); msg = gettext('No dependent information is available for the selected object.');
if (node.hasDepends) { if (node.hasDepends) {
// Avoid unnecessary reloads
var cache_flag = {
node_type: node_type,
url: url,
};
if (_.isEqual($(panel).data('node-prop'), cache_flag)) {
return;
}
// Cache the current IDs for next time
$(panel).data('node-prop', cache_flag);
/* Updating the label for the 'field' type of the backbone model. /* Updating the label for the 'field' type of the backbone model.
* Label should be "Database" if the node type is tablespace or role * Label should be "Database" if the node type is tablespace or role
* and dependent tab is selected. For other nodes and dependencies tab * and dependent tab is selected. For other nodes and dependencies tab
* it should be 'Restriction'. * it should be 'Restriction'.
*/ */
this.__appendGridToPanel();
if (node.type == 'tablespace' || node.type == 'role') { if (node.type == 'tablespace' || node.type == 'role') {
this.dependentGrid.columns.models[2].set({ this.dependentGrid.columns.models[2].set({
'label': gettext('Database'), 'label': gettext('Database'),
@ -156,85 +208,88 @@ define('misc.dependents', [
$gridContainer.removeClass('d-none'); $gridContainer.removeClass('d-none');
var timer = ''; var timer = '';
$.ajax({ var ajaxHook = function() {
url: url, $.ajax({
type: 'GET', url: url,
beforeSend: function(xhr) { type: 'GET',
xhr.setRequestHeader(pgAdmin.csrf_token_header, pgAdmin.csrf_token); beforeSend: function(xhr) {
// Generate a timer for the request xhr.setRequestHeader(pgAdmin.csrf_token_header, pgAdmin.csrf_token);
timer = setTimeout(function() { // Generate a timer for the request
// notify user if request is taking longer than 1 second timer = setTimeout(function() {
// notify user if request is taking longer than 1 second
$msgContainer.text(gettext('Fetching dependent information from the server...'));
$msgContainer.removeClass('d-none');
msg = '';
}, 1000);
},
})
.done(function(res) {
clearTimeout(timer);
if (res.length > 0) {
if (!$msgContainer.hasClass('d-none')) {
$msgContainer.addClass('d-none');
}
$gridContainer.removeClass('d-none');
self.dependentData = res;
// Load only 100 rows
self.dependentCollection.reset(self.dependentData.splice(0, 100), {parse: true});
// Load more rows on scroll down
pgBrowser.Events.on(
'pgadmin-browser:panel-dependents:' +
wcDocker.EVENT.SCROLLED,
self.__loadMoreRows
);
} else {
// Do not listen the scroll event
pgBrowser.Events.off(
'pgadmin-browser:panel-dependents:' +
wcDocker.EVENT.SCROLLED
);
self.dependentCollection.reset({silent: true});
$msgContainer.text(msg);
$msgContainer.removeClass('d-none');
if (!$gridContainer.hasClass('d-none')) {
$gridContainer.addClass('d-none');
}
}
$msgContainer.text(gettext('Fetching dependent information from the server...'));
$msgContainer.removeClass('d-none');
msg = '';
}, 1000);
},
}) })
.fail(function(xhr, error, message) { .done(function(res) {
var _label = treeHierarchy[n_type].label; clearTimeout(timer);
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'depends', xhr, error, message if (res.length > 0) {
);
if (!Alertify.pgHandleItemError(xhr, error, message, { if (!$msgContainer.hasClass('d-none')) {
item: item, $msgContainer.addClass('d-none');
info: treeHierarchy, }
})) { $gridContainer.removeClass('d-none');
Alertify.pgNotifier(
error, xhr, self.dependentData = res;
gettext('Error retrieving data from the server: %s', message || _label),
function(alertMsg) { // Load only 100 rows
if(alertMsg === 'CRYPTKEY_SET') { self.dependentCollection.reset(self.dependentData.splice(0, 100), {parse: true});
self.showDependents(item, data, node);
} else { // Load more rows on scroll down
console.warn(arguments); pgBrowser.Events.on(
} 'pgadmin-browser:panel-dependents:' +
}); wcDocker.EVENT.SCROLLED,
} self.__loadMoreRows
// show failed message. );
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
}); } else {
// Do not listen the scroll event
pgBrowser.Events.off(
'pgadmin-browser:panel-dependents:' +
wcDocker.EVENT.SCROLLED
);
self.dependentCollection.reset({silent: true});
$msgContainer.text(msg);
$msgContainer.removeClass('d-none');
if (!$gridContainer.hasClass('d-none')) {
$gridContainer.addClass('d-none');
}
}
})
.fail(function(xhr, error, message) {
var _label = treeHierarchy[node_type].label;
pgBrowser.Events.trigger(
'pgadmin:node:retrieval:error', 'depends', xhr, error, message
);
if (!Alertify.pgHandleItemError(xhr, error, message, {
item: item,
info: treeHierarchy,
})) {
Alertify.pgNotifier(
error, xhr,
gettext('Error retrieving data from the server: %s', message || _label),
function(alertMsg) {
if(alertMsg === 'CRYPTKEY_SET') {
ajaxHook();
} else {
console.warn(arguments);
}
});
}
// show failed message.
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
});
};
ajaxHook();
} }
} }
if (msg != '') { if (msg != '') {

View File

@ -116,12 +116,11 @@ define('misc.statistics', [
this.initialized = true; this.initialized = true;
_.bindAll( _.bindAll(
this, this,
'showStatistics', 'panelVisibilityChanged', 'showStatistics', 'toggleVisibility',
'__createMultiLineStatistics', '__createSingleLineStatistics', '__loadMoreRows'); '__createMultiLineStatistics', '__createSingleLineStatistics', '__loadMoreRows');
_.extend( _.extend(
this, { this, {
initialized: true,
collection: new(Backbone.Collection)(null), collection: new(Backbone.Collection)(null),
statistic_columns: [{ statistic_columns: [{
editable: false, editable: false,
@ -136,66 +135,49 @@ define('misc.statistics', [
label: gettext('Value'), label: gettext('Value'),
cell: 'string', cell: 'string',
}], }],
panel: pgBrowser.docker.findPanels('statistics'),
columns: null, columns: null,
grid: null, grid: null,
}); });
var self = this; this.panel = pgBrowser.docker.findPanels('statistics');
if(this.panel.length > 0) this.toggleVisibility(this.panel[0].isVisible());
},
// We will listen to the visibility change of the statistics panel toggleVisibility: function(visible, closed=false) {
pgBrowser.Events.on( if (visible) {
'pgadmin-browser:panel-statistics:' + this.panel = pgBrowser.docker.findPanels('statistics');
wcDocker.EVENT.VISIBILITY_CHANGED, var t = pgBrowser.tree,
this.panelVisibilityChanged i = t.selected(),
); d = i && t.itemData(i),
n = i && d && pgBrowser.Nodes[d._type];
pgBrowser.Events.on( pgBrowser.NodeStatistics.showStatistics.apply(
'pgadmin:browser:node:updated', pgBrowser.NodeStatistics, [i, d, n]
function() { );
if (this.panel && this.panel.length) {
$(this.panel[0]).data('node-prop', '');
this.panelVisibilityChanged(this.panel[0]);
}
}, this
);
// Hmm.. Did we find the statistics panel, and is it visible (openned)? // We will start listening the tree selection event.
// If that is the case - we need to listen the browser tree selection
// events.
if (this.panel.length == 0) {
pgBrowser.Events.on( pgBrowser.Events.on(
'pgadmin-browser:panel-statistics:' + wcDocker.EVENT.INIT, 'pgadmin-browser:tree:selected',
function() { pgBrowser.NodeStatistics.showStatistics
self.panel = pgBrowser.docker.findPanels('statistics'); );
if (self.panel[0].isVisible() || pgBrowser.Events.on(
self.panel.length != 1) { 'pgadmin-browser:tree:refreshing',
pgBrowser.Events.on( pgBrowser.NodeStatistics.refreshStatistics,
'pgadmin-browser:tree:selected', this.showStatistics this
);
pgBrowser.Events.on(
'pgadmin-browser:tree:refreshing', this.refreshStatistics, this
);
}
}.bind(this)
); );
} else { } else {
if (self.panel[0].isVisible() || if(closed) {
self.panel.length != 1) { $(this.panel[0]).data('node-prop', '');
pgBrowser.Events.on(
'pgadmin-browser:tree:selected', this.showStatistics
);
pgBrowser.Events.on(
'pgadmin-browser:tree:refreshing', this.refreshStatistics, this
);
} }
} // We don't need to listen the tree item selection event.
if (self.panel.length > 0 && self.panel[0].isVisible()) { pgBrowser.Events.off(
pgBrowser.Events.on( 'pgadmin-browser:tree:selected',
'pgadmin-browser:tree:selected', this.showStatistics pgBrowser.NodeStatistics.showStatistics
); );
pgBrowser.Events.on( pgBrowser.Events.off(
'pgadmin-browser:tree:refreshing', this.refreshStatistics, this 'pgadmin-browser:tree:refreshing',
pgBrowser.NodeStatistics.refreshStatistics,
this
); );
} }
}, },
@ -440,41 +422,6 @@ define('misc.statistics', [
this.collection.reset(res); this.collection.reset(res);
}, },
panelVisibilityChanged: function(panel) {
if (panel.isVisible()) {
var t = pgBrowser.tree,
i = t.selected(),
d = i && t.itemData(i),
n = i && d && pgBrowser.Nodes[d._type];
pgBrowser.NodeStatistics.showStatistics.apply(
pgBrowser.NodeStatistics, [i, d, n]
);
// We will start listening the tree selection event.
pgBrowser.Events.on(
'pgadmin-browser:tree:selected',
pgBrowser.NodeStatistics.showStatistics
);
pgBrowser.Events.on(
'pgadmin-browser:tree:refreshing',
pgBrowser.NodeStatistics.refreshStatistics,
this
);
} else {
// We don't need to listen the tree item selection event.
pgBrowser.Events.off(
'pgadmin-browser:tree:selected',
pgBrowser.NodeStatistics.showStatistics
);
pgBrowser.Events.off(
'pgadmin-browser:tree:refreshing',
pgBrowser.NodeStatistics.refreshStatistics,
this
);
}
},
}); });
return pgBrowser.NodeStatistics; return pgBrowser.NodeStatistics;