mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
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:
parent
18f055fa5e
commit
73b6b95fbc
@ -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.
|
||||||
|
@ -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,
|
||||||
}),
|
}),
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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 != '') {
|
||||||
|
@ -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 != '') {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user