mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Optimise display of Dependencies and Dependents, and use on-demand loading of rows in batches of 100. Fixes #3959
This commit is contained in:
committed by
Dave Page
parent
e5e154e268
commit
622b67684d
@@ -21,6 +21,7 @@ Bug fixes
|
||||
| `Bug #3906 <https://redmine.postgresql.org/issues/3906>`_ - Fix alignment of Close and Maximize button of Grant Wizard.
|
||||
| `Bug #3942 <https://redmine.postgresql.org/issues/3942>`_ - Close connections gracefully when the user logs out of pgAdmin.
|
||||
| `Bug #3946 <https://redmine.postgresql.org/issues/3946>`_ - Fix alignment of checkbox to drop multiple schedules of pgAgent job.
|
||||
| `Bug #3959 <https://redmine.postgresql.org/issues/3959>`_ - Optimise display of Dependencies and Dependents, and use on-demand loading of rows in batches of 100.
|
||||
| `Bug #3963 <https://redmine.postgresql.org/issues/3963>`_ - Fix alignment of import/export toggle switch.
|
||||
| `Bug #3970 <https://redmine.postgresql.org/issues/3970>`_ - Prevent an error when closing the Sort/Filter dialogue with an empty filter string.
|
||||
| `Bug #3974 <https://redmine.postgresql.org/issues/3974>`_ - Fix alignment of Connection type toggle switch of pgagent.
|
||||
|
||||
@@ -189,7 +189,7 @@ define('pgadmin.browser', [
|
||||
width: 500,
|
||||
isCloseable: false,
|
||||
isPrivate: true,
|
||||
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-depends-container d-none"></div></div>',
|
||||
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependencies-container d-none"></div></div>',
|
||||
events: panelEvents,
|
||||
}),
|
||||
// Dependents of the object
|
||||
@@ -200,7 +200,7 @@ define('pgadmin.browser', [
|
||||
width: 500,
|
||||
isCloseable: false,
|
||||
isPrivate: true,
|
||||
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-depends-container d-none"></div></div>',
|
||||
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>',
|
||||
events: panelEvents,
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -42,6 +42,7 @@ define([
|
||||
if (this.node_initialized)
|
||||
return;
|
||||
this.node_initialized = true;
|
||||
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'refresh', node: this.type, module: this,
|
||||
applies: ['object', 'context'], callback: 'refresh',
|
||||
@@ -77,12 +78,9 @@ define([
|
||||
content = $('<div></div>')
|
||||
.addClass('pg-prop-content col-12 has-pg-prop-btn-group'),
|
||||
node = pgBrowser.Nodes[that.node],
|
||||
$msgContainer = '',
|
||||
// This will be the URL, used for object manipulation.
|
||||
urlBase = this.generate_url(item, 'properties', data),
|
||||
collection = new (node.Collection.extend({
|
||||
url: urlBase,
|
||||
model: node.model,
|
||||
}))(),
|
||||
info = this.getTreeNodeHierarchy.apply(this, [item]),
|
||||
gridSchema = Backform.generateGridColumnsFromModel(
|
||||
info, node.model, 'properties', that.columns
|
||||
@@ -132,6 +130,10 @@ define([
|
||||
return null;
|
||||
}.bind(panel);
|
||||
|
||||
that.collection = new (node.Collection.extend({
|
||||
url: urlBase,
|
||||
model: node.model,
|
||||
}))();
|
||||
// Add the new column for the multi-select menus
|
||||
if((_.isFunction(that.canDrop) ?
|
||||
that.canDrop.apply(that, [data, item]) : that.canDrop) ||
|
||||
@@ -180,7 +182,7 @@ define([
|
||||
that.grid = new Backgrid.Grid({
|
||||
emptyText: 'No data found',
|
||||
columns: gridSchema.columns,
|
||||
collection: collection,
|
||||
collection: that.collection,
|
||||
className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
|
||||
});
|
||||
|
||||
@@ -199,6 +201,7 @@ define([
|
||||
};
|
||||
|
||||
if (view) {
|
||||
|
||||
// Avoid unnecessary reloads
|
||||
if (_.isEqual($(panel).data('node-prop'), urlBase)) {
|
||||
return;
|
||||
@@ -215,9 +218,14 @@ define([
|
||||
j.empty();
|
||||
j.data('obj-view', gridView);
|
||||
|
||||
$msgContainer = '<div class="alert alert-info pg-panel-message pg-panel-properties-message">' +
|
||||
gettext('Retrieving data from the server...') + '</div>';
|
||||
|
||||
$msgContainer = $($msgContainer).appendTo(j);
|
||||
|
||||
that.header = $('<div></div>').addClass(
|
||||
'pg-prop-header'
|
||||
).appendTo(j);
|
||||
);
|
||||
|
||||
// Render the buttons
|
||||
var buttons = [];
|
||||
@@ -255,26 +263,69 @@ define([
|
||||
// Render subNode grid
|
||||
content.append('<div class="pg-prop-coll-container"></div>');
|
||||
content.find('.pg-prop-coll-container').append(that.grid.render().$el);
|
||||
j.append(content);
|
||||
|
||||
// Fetch Data
|
||||
collection.fetch({
|
||||
reset: true,
|
||||
error: function(model, error, xhr) {
|
||||
pgBrowser.Events.trigger(
|
||||
'pgadmin:collection:retrieval:error', 'properties', xhr, error,
|
||||
error.message, item, that
|
||||
);
|
||||
if (!Alertify.pgHandleItemError(
|
||||
xhr, error, error.message, {item: item, info: info}
|
||||
)) {
|
||||
Alertify.pgNotifier(error, xhr, S(
|
||||
gettext('Error retrieving properties - %s.')
|
||||
).sprintf(error.message || that.label).value(), function() {
|
||||
var timer;
|
||||
|
||||
$.ajax({
|
||||
url: urlBase,
|
||||
type: 'GET',
|
||||
beforeSend: function() {
|
||||
// Generate a timer for the request
|
||||
timer = setTimeout(function() {
|
||||
// notify user if request is taking longer than 1 second
|
||||
|
||||
$msgContainer.text(gettext('Retrieving data from the server...'));
|
||||
$msgContainer.removeClass('d-none');
|
||||
if (self.grid) {
|
||||
self.grid.remove();
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
})
|
||||
.done(function(res) {
|
||||
clearTimeout(timer);
|
||||
|
||||
if (_.isUndefined(that.grid) || _.isNull(that.grid)) return;
|
||||
|
||||
that.data = res;
|
||||
|
||||
if (that.data.length > 0) {
|
||||
|
||||
if (!$msgContainer.hasClass('d-none')) {
|
||||
$msgContainer.addClass('d-none');
|
||||
}
|
||||
that.header.appendTo(j);
|
||||
j.append(content);
|
||||
|
||||
// Listen scroll event to load more rows
|
||||
$('.pg-prop-content').on('scroll', that.__loadMoreRows.bind(that));
|
||||
|
||||
that.collection.reset(that.data.splice(0, 50));
|
||||
} else {
|
||||
// Do not listen the scroll event
|
||||
$('.pg-prop-content').off('scroll', that.__loadMoreRows);
|
||||
|
||||
$msgContainer.text(gettext('No properties are available for the selected object.'));
|
||||
|
||||
}
|
||||
})
|
||||
.fail(function(xhr, error) {
|
||||
pgBrowser.Events.trigger(
|
||||
'pgadmin:node:retrieval:error', 'properties', xhr, error.message, item, that
|
||||
);
|
||||
if (!Alertify.pgHandleItemError(xhr, error.message, {
|
||||
item: item,
|
||||
info: info,
|
||||
})) {
|
||||
Alertify.pgNotifier(
|
||||
error, xhr,
|
||||
S(gettext('Error retrieving properties - %s')).sprintf(
|
||||
error.message || that.label).value(), function() {
|
||||
console.warn(arguments);
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
// show failed message.
|
||||
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
|
||||
});
|
||||
|
||||
var onDrop = function(type) {
|
||||
@@ -359,6 +410,14 @@ define([
|
||||
return;
|
||||
}.bind(that);
|
||||
},
|
||||
__loadMoreRows: function(e) {
|
||||
let elem = e.currentTarget;
|
||||
if ((elem.scrollHeight - 10) < elem.scrollTop + elem.offsetHeight) {
|
||||
if (this.data.length > 0) {
|
||||
this.collection.add(this.data.splice(0, 50));
|
||||
}
|
||||
}
|
||||
},
|
||||
generate_url: function(item, type) {
|
||||
/*
|
||||
* Using list, and collection functions of a node to get the nodes
|
||||
|
||||
30
web/pgadmin/misc/dependencies/__init__.py
Normal file
30
web/pgadmin/misc/dependencies/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2019, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""A blueprint module providing utility functions for the application."""
|
||||
|
||||
from flask import url_for
|
||||
from pgadmin.utils import PgAdminModule
|
||||
|
||||
MODULE_NAME = 'dependencies'
|
||||
|
||||
|
||||
class DependenciesModule(PgAdminModule):
|
||||
def get_own_javascripts(self):
|
||||
return [{
|
||||
'name': 'pgadmin.browser.dependencies',
|
||||
'path': url_for('dependencies.static',
|
||||
filename='js/dependencies'),
|
||||
'when': None
|
||||
}]
|
||||
|
||||
|
||||
# Initialise the module
|
||||
blueprint = DependenciesModule(MODULE_NAME, __name__,
|
||||
url_prefix='/misc/dependencies')
|
||||
246
web/pgadmin/misc/dependencies/static/js/dependencies.js
Normal file
246
web/pgadmin/misc/dependencies/static/js/dependencies.js
Normal file
@@ -0,0 +1,246 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2019, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define('misc.dependencies', [
|
||||
'sources/gettext', 'underscore', 'underscore.string', 'jquery', 'backbone',
|
||||
'pgadmin.browser', 'pgadmin.alertifyjs', 'pgadmin.backgrid',
|
||||
], function(gettext, _, S, $, Backbone, pgBrowser, Alertify, Backgrid) {
|
||||
|
||||
if (pgBrowser.NodeDependencies)
|
||||
return pgBrowser.NodeDependencies;
|
||||
|
||||
var wcDocker = window.wcDocker;
|
||||
|
||||
pgBrowser.NodeDependencies = pgBrowser.NodeDependencies || {};
|
||||
|
||||
_.extend(pgBrowser.NodeDependencies, {
|
||||
init: function() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
this.dependenciesPanel = pgBrowser.docker.findPanels('dependencies')[0];
|
||||
/* Parameter is used to set the proper label of the
|
||||
* backgrid header cell.
|
||||
*/
|
||||
_.bindAll(this, 'showDependencies', '__loadMoreRows', '__appendGridToPanel');
|
||||
|
||||
// Defining Backbone Model for Dependencies.
|
||||
var Model = Backbone.Model.extend({
|
||||
defaults: {
|
||||
icon: 'icon-unknown',
|
||||
type: undefined,
|
||||
name: undefined,
|
||||
/* field contains 'Database Name' for 'Tablespace and Role node',
|
||||
* for other node it contains 'Restriction'.
|
||||
*/
|
||||
field: undefined,
|
||||
},
|
||||
// This function is used to fetch/set the icon for the type(Function, Role, Database, ....)
|
||||
parse: function(res) {
|
||||
var node = pgBrowser.Nodes[res.type];
|
||||
res.icon = node ? (_.isFunction(node['node_image']) ?
|
||||
(node['node_image']).apply(node, [null, null]) :
|
||||
(node['node_image'] || ('icon-' + res.type))) :
|
||||
('icon-' + res.type);
|
||||
res.type = S.titleize(res.type.replace(/_/g, ' '), true);
|
||||
return res;
|
||||
},
|
||||
});
|
||||
|
||||
// Defining Backbone Collection for Dependencies.
|
||||
this.dependenciesCollection = new(Backbone.Collection.extend({
|
||||
model: Model,
|
||||
}))(null);
|
||||
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependencies);
|
||||
this.__appendGridToPanel();
|
||||
},
|
||||
|
||||
/* Function is used to create and render backgrid with
|
||||
* empty collection. We just want to add backgrid into the
|
||||
* panel only once.
|
||||
*/
|
||||
__appendGridToPanel: function() {
|
||||
var $container = this.dependenciesPanel.layout().scene().find('.pg-panel-content'),
|
||||
$gridContainer = $container.find('.pg-panel-dependencies-container'),
|
||||
grid = new Backgrid.Grid({
|
||||
emptyText: 'No data found',
|
||||
columns: [{
|
||||
name: 'type',
|
||||
label: gettext('Type'),
|
||||
// Extend it to render the icon as per the type.
|
||||
cell: Backgrid.Cell.extend({
|
||||
render: function() {
|
||||
Backgrid.Cell.prototype.render.apply(this, arguments);
|
||||
this.$el.prepend($('<i>', {
|
||||
class: 'wcTabIcon ' + this.model.get('icon'),
|
||||
}));
|
||||
return this;
|
||||
},
|
||||
}),
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
label: gettext('Name'),
|
||||
cell: 'string',
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
name: 'field',
|
||||
label: '', // label kept blank, it will change dynamically
|
||||
cell: 'string',
|
||||
editable: false,
|
||||
},
|
||||
],
|
||||
|
||||
collection: this.dependenciesCollection,
|
||||
className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
|
||||
});
|
||||
|
||||
// Condition is used to save grid object to change the label of the header.
|
||||
this.dependenciesGrid = grid;
|
||||
|
||||
$gridContainer.append(grid.render().el);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// Fetch the actual data and update the collection
|
||||
showDependencies: function(item, data, node) {
|
||||
let self = this,
|
||||
msg = gettext('Please select an object in the tree view.'),
|
||||
panel = this.dependenciesPanel,
|
||||
$container = panel.layout().scene().find('.pg-panel-content'),
|
||||
$msgContainer = $container.find('.pg-panel-depends-message'),
|
||||
$gridContainer = $container.find('.pg-panel-dependencies-container'),
|
||||
treeHierarchy = node.getTreeNodeHierarchy(item),
|
||||
n_type = data._type,
|
||||
url = node.generate_url(item, 'dependency', data, true);
|
||||
|
||||
if (node) {
|
||||
/* We fetch the Dependencies and Dependencies tab only for
|
||||
* those node who set the parameter hasDepends to true.
|
||||
*/
|
||||
msg = gettext('No dependency information is available for the selected object.');
|
||||
if (node.hasDepends) {
|
||||
/* Updating the label for the 'field' type of the backbone model.
|
||||
* Label should be "Database" if the node type is tablespace or role
|
||||
* and dependencies tab is selected. For other nodes and dependencies tab
|
||||
* it should be 'Restriction'.
|
||||
*/
|
||||
|
||||
this.dependenciesGrid.columns.models[2].set({
|
||||
'label': gettext('Restriction'),
|
||||
});
|
||||
|
||||
// Hide message container and show grid container.
|
||||
$msgContainer.addClass('d-none');
|
||||
$gridContainer.removeClass('d-none');
|
||||
|
||||
var timer = '';
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'GET',
|
||||
beforeSend: function() {
|
||||
// Generate a timer for the request
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
.fail(function(xhr, error, message) {
|
||||
var _label = treeHierarchy[n_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,
|
||||
S(gettext('Error retrieving data from the server: %s')).sprintf(
|
||||
message || _label).value(), function() {
|
||||
console.warn(arguments);
|
||||
});
|
||||
}
|
||||
// show failed message.
|
||||
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
|
||||
});
|
||||
}
|
||||
} if (msg != '') {
|
||||
$msgContainer.text(msg);
|
||||
$msgContainer.removeClass('d-none');
|
||||
if (!$gridContainer.hasClass('d-none')) {
|
||||
$gridContainer.addClass('d-none');
|
||||
}
|
||||
}
|
||||
},
|
||||
__loadMoreRows: function() {
|
||||
if (this.dependenciesPanel.length < 1) return ;
|
||||
|
||||
let elem = this.dependenciesPanel.$container.find('.pg-panel-dependencies-container').closest('.wcFrameCenter')[0];
|
||||
if ((elem.scrollHeight - 10) < elem.scrollTop + elem.offsetHeight) {
|
||||
if (this.dependenciesData.length > 0) {
|
||||
this.dependenciesCollection.add(this.dependenciesData.splice(0, 100), {parse: true});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return pgBrowser.NodeDependencies;
|
||||
});
|
||||
@@ -12,17 +12,18 @@
|
||||
from flask import url_for
|
||||
from pgadmin.utils import PgAdminModule
|
||||
|
||||
MODULE_NAME = 'depends'
|
||||
MODULE_NAME = 'dependents'
|
||||
|
||||
|
||||
class DependsModule(PgAdminModule):
|
||||
class DependentsModule(PgAdminModule):
|
||||
def get_own_javascripts(self):
|
||||
return [{
|
||||
'name': 'pgadmin.browser.object_depends',
|
||||
'path': url_for('depends.static', filename='js/depends'),
|
||||
'name': 'pgadmin.browser.dependents',
|
||||
'path': url_for('dependents.static', filename='js/dependents'),
|
||||
'when': None
|
||||
}]
|
||||
|
||||
|
||||
# Initialise the module
|
||||
blueprint = DependsModule(MODULE_NAME, __name__, url_prefix='/misc/depends')
|
||||
blueprint = DependentsModule(MODULE_NAME, __name__,
|
||||
url_prefix='/misc/dependents')
|
||||
252
web/pgadmin/misc/dependents/static/js/dependents.js
Normal file
252
web/pgadmin/misc/dependents/static/js/dependents.js
Normal file
@@ -0,0 +1,252 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2019, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define('misc.dependents', [
|
||||
'sources/gettext', 'underscore', 'underscore.string', 'jquery', 'backbone',
|
||||
'pgadmin.browser', 'pgadmin.alertifyjs', 'pgadmin.backgrid',
|
||||
], function(gettext, _, S, $, Backbone, pgBrowser, Alertify, Backgrid) {
|
||||
|
||||
if (pgBrowser.NodeDependents)
|
||||
return pgBrowser.NodeDependents;
|
||||
|
||||
var wcDocker = window.wcDocker;
|
||||
|
||||
pgBrowser.NodeDependents = pgBrowser.NodeDependents || {};
|
||||
|
||||
_.extend(pgBrowser.NodeDependents, {
|
||||
init: function() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
this.dependentsPanel = pgBrowser.docker.findPanels('dependents')[0];
|
||||
/* Parameter is used to set the proper label of the
|
||||
* backgrid header cell.
|
||||
*/
|
||||
_.bindAll(this, 'showDependents', '__loadMoreRows', '__appendGridToPanel');
|
||||
|
||||
// Defining Backbone Model for Dependents.
|
||||
var Model = Backbone.Model.extend({
|
||||
defaults: {
|
||||
icon: 'icon-unknown',
|
||||
type: undefined,
|
||||
name: undefined,
|
||||
/* field contains 'Database Name' for 'Tablespace and Role node',
|
||||
* for other node it contains 'Restriction'.
|
||||
*/
|
||||
field: undefined,
|
||||
},
|
||||
// This function is used to fetch/set the icon for the type(Function, Role, Database, ....)
|
||||
parse: function(res) {
|
||||
var node = pgBrowser.Nodes[res.type];
|
||||
res.icon = node ? (_.isFunction(node['node_image']) ?
|
||||
(node['node_image']).apply(node, [null, null]) :
|
||||
(node['node_image'] || ('icon-' + res.type))) :
|
||||
('icon-' + res.type);
|
||||
res.type = S.titleize(res.type.replace(/_/g, ' '), true);
|
||||
return res;
|
||||
},
|
||||
});
|
||||
|
||||
// Defining Backbone Collection for Dependents.
|
||||
this.dependentCollection = new(Backbone.Collection.extend({
|
||||
model: Model,
|
||||
}))(null);
|
||||
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependents);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', this.refreshDependents, this);
|
||||
this.__appendGridToPanel();
|
||||
},
|
||||
|
||||
/* Function is used to create and render backgrid with
|
||||
* empty collection. We just want to add backgrid into the
|
||||
* panel only once.
|
||||
*/
|
||||
__appendGridToPanel: function() {
|
||||
var $container = this.dependentsPanel.layout().scene().find('.pg-panel-content'),
|
||||
$gridContainer = $container.find('.pg-panel-dependents-container'),
|
||||
grid = new Backgrid.Grid({
|
||||
emptyText: 'No data found',
|
||||
columns: [{
|
||||
name: 'type',
|
||||
label: gettext('Type'),
|
||||
// Extend it to render the icon as per the type.
|
||||
cell: Backgrid.Cell.extend({
|
||||
render: function() {
|
||||
Backgrid.Cell.prototype.render.apply(this, arguments);
|
||||
this.$el.prepend($('<i>', {
|
||||
class: 'wcTabIcon ' + this.model.get('icon'),
|
||||
}));
|
||||
return this;
|
||||
},
|
||||
}),
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
label: gettext('Name'),
|
||||
cell: 'string',
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
name: 'field',
|
||||
label: '', // label kept blank, it will change dynamically
|
||||
cell: 'string',
|
||||
editable: false,
|
||||
},
|
||||
],
|
||||
|
||||
collection: this.dependentCollection,
|
||||
className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
|
||||
});
|
||||
|
||||
// Condition is used to save grid object to change the label of the header.
|
||||
this.dependentGrid = grid;
|
||||
|
||||
$gridContainer.append(grid.render().el);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// Fetch the actual data and update the collection
|
||||
showDependents: function(item, data, node) {
|
||||
let self = this,
|
||||
msg = gettext('Please select an object in the tree view.'),
|
||||
panel = this.dependentsPanel,
|
||||
$container = panel.layout().scene().find('.pg-panel-content'),
|
||||
$msgContainer = $container.find('.pg-panel-depends-message'),
|
||||
$gridContainer = $container.find('.pg-panel-dependents-container'),
|
||||
treeHierarchy = node.getTreeNodeHierarchy(item),
|
||||
n_type = data._type,
|
||||
url = node.generate_url(item, 'dependent', data, true);
|
||||
|
||||
if (node) {
|
||||
/* We fetch the Dependencies and Dependents tab only for
|
||||
* those node who set the parameter hasDepends to true.
|
||||
*/
|
||||
msg = gettext('No dependent information is available for the selected object.');
|
||||
if (node.hasDepends) {
|
||||
/* Updating the label for the 'field' type of the backbone model.
|
||||
* Label should be "Database" if the node type is tablespace or role
|
||||
* and dependent tab is selected. For other nodes and dependencies tab
|
||||
* it should be 'Restriction'.
|
||||
*/
|
||||
if (node.type == 'tablespace' || node.type == 'role') {
|
||||
this.dependentGrid.columns.models[2].set({
|
||||
'label': gettext('Database'),
|
||||
});
|
||||
} else {
|
||||
this.dependentGrid.columns.models[2].set({
|
||||
'label': gettext('Restriction'),
|
||||
});
|
||||
}
|
||||
|
||||
// Hide message container and show grid container.
|
||||
$msgContainer.addClass('d-none');
|
||||
$gridContainer.removeClass('d-none');
|
||||
|
||||
var timer = '';
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'GET',
|
||||
beforeSend: function() {
|
||||
// Generate a timer for the request
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
.fail(function(xhr, error, message) {
|
||||
var _label = treeHierarchy[n_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,
|
||||
S(gettext('Error retrieving data from the server: %s')).sprintf(
|
||||
message || _label).value(), function() {
|
||||
console.warn(arguments);
|
||||
});
|
||||
}
|
||||
// show failed message.
|
||||
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
|
||||
});
|
||||
}
|
||||
} if (msg != '') {
|
||||
$msgContainer.text(msg);
|
||||
$msgContainer.removeClass('d-none');
|
||||
if (!$gridContainer.hasClass('d-none')) {
|
||||
$gridContainer.addClass('d-none');
|
||||
}
|
||||
}
|
||||
},
|
||||
__loadMoreRows: function() {
|
||||
if (this.dependentsPanel.length < 1) return ;
|
||||
|
||||
let elem = this.dependentsPanel.$container.find('.pg-panel-dependents-container').closest('.wcFrameCenter')[0];
|
||||
if ((elem.scrollHeight - 10) < elem.scrollTop + elem.offsetHeight) {
|
||||
if (this.dependentData.length > 0) {
|
||||
this.dependentCollection.add(this.dependentData.splice(0, 100), {parse: true});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return pgBrowser.NodeDependents;
|
||||
});
|
||||
@@ -1,432 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2019, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define('misc.depends', [
|
||||
'sources/gettext', 'underscore', 'underscore.string', 'jquery', 'backbone',
|
||||
'pgadmin.browser', 'pgadmin.alertifyjs', 'pgadmin.backgrid',
|
||||
], function(gettext, _, S, $, Backbone, pgBrowser, Alertify, Backgrid) {
|
||||
|
||||
if (pgBrowser.ShowNodeDepends)
|
||||
return pgBrowser.ShowNodeDepends;
|
||||
|
||||
var wcDocker = window.wcDocker;
|
||||
|
||||
pgBrowser.ShowNodeDepends = pgBrowser.ShowNodeDepends || {};
|
||||
|
||||
_.extend(pgBrowser.ShowNodeDepends, {
|
||||
init: function() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
/* Parameter is used to set the proper label of the
|
||||
* backgrid header cell.
|
||||
*/
|
||||
_.bindAll(this, 'showDependents', 'dependentsPanelVisibilityChanged',
|
||||
'showDependencies', 'dependenciesPanelVisibilityChanged', '__updateCollection'
|
||||
);
|
||||
|
||||
// We will listened to the visibility change of the Dependencies and Dependents panel
|
||||
pgBrowser.Events.on('pgadmin-browser:panel-dependencies:' + wcDocker.EVENT.VISIBILITY_CHANGED,
|
||||
this.dependenciesPanelVisibilityChanged);
|
||||
pgBrowser.Events.on('pgadmin-browser:panel-dependents:' + wcDocker.EVENT.VISIBILITY_CHANGED,
|
||||
this.dependentsPanelVisibilityChanged);
|
||||
|
||||
// Defining Backbone Model for Dependencies and Dependents.
|
||||
var Model = Backbone.Model.extend({
|
||||
defaults: {
|
||||
icon: 'icon-unknown',
|
||||
type: undefined,
|
||||
name: undefined,
|
||||
/* field contains 'Database Name' for 'Tablespace and Role node',
|
||||
* for other node it contains 'Restriction'.
|
||||
*/
|
||||
field: undefined,
|
||||
},
|
||||
// This function is used to fetch/set the icon for the type(Function, Role, Database, ....)
|
||||
parse: function(res) {
|
||||
var node = pgBrowser.Nodes[res.type];
|
||||
res.icon = node ? (_.isFunction(node['node_image']) ?
|
||||
(node['node_image']).apply(node, [null, null]) :
|
||||
(node['node_image'] || ('icon-' + res.type))) :
|
||||
('icon-' + res.type);
|
||||
res.type = S.titleize(res.type.replace(/_/g, ' '), true);
|
||||
return res;
|
||||
},
|
||||
});
|
||||
|
||||
// Defining Backbone Collection for Dependents.
|
||||
this.dependentCollection = new(Backbone.Collection.extend({
|
||||
model: Model,
|
||||
}))(null);
|
||||
|
||||
// Defining Backbone Collection for Dependencies.
|
||||
this.dependenciesCollection = new(Backbone.Collection.extend({
|
||||
model: Model,
|
||||
}))(null);
|
||||
|
||||
var self = this;
|
||||
|
||||
/* Function is used to create and render backgrid with
|
||||
* empty collection. We just want to add backgrid into the
|
||||
* panel only once.
|
||||
*/
|
||||
var appendGridToPanel = function(collection, panel, is_dependent) {
|
||||
var $container = panel[0].layout().scene().find('.pg-panel-content'),
|
||||
$gridContainer = $container.find('.pg-panel-depends-container'),
|
||||
grid = new Backgrid.Grid({
|
||||
emptyText: 'No data found',
|
||||
columns: [{
|
||||
name: 'type',
|
||||
label: gettext('Type'),
|
||||
// Extend it to render the icon as per the type.
|
||||
cell: Backgrid.Cell.extend({
|
||||
render: function() {
|
||||
Backgrid.Cell.prototype.render.apply(this, arguments);
|
||||
this.$el.prepend($('<i>', {
|
||||
class: 'wcTabIcon ' + this.model.get('icon'),
|
||||
}));
|
||||
return this;
|
||||
},
|
||||
}),
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
label: gettext('Name'),
|
||||
cell: 'string',
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
name: 'field',
|
||||
label: '', // label kept blank, it will change dynamically
|
||||
cell: 'string',
|
||||
editable: false,
|
||||
},
|
||||
],
|
||||
|
||||
collection: collection,
|
||||
className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
|
||||
});
|
||||
|
||||
// Condition is used to save grid object to change the label of the header.
|
||||
if (is_dependent)
|
||||
self.dependentGrid = grid;
|
||||
else
|
||||
self.dependenciesGrid = grid;
|
||||
|
||||
$gridContainer.append(grid.render().el);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// We will listened to the visibility change of the Dependencies and Dependents panel
|
||||
pgBrowser.Events.on('pgadmin-browser:panel-dependencies:' + wcDocker.EVENT.VISIBILITY_CHANGED,
|
||||
this.dependenciesPanelVisibilityChanged);
|
||||
pgBrowser.Events.on('pgadmin-browser:panel-dependents:' + wcDocker.EVENT.VISIBILITY_CHANGED,
|
||||
this.dependentsPanelVisibilityChanged);
|
||||
pgBrowser.Events.on(
|
||||
'pgadmin:browser:node:updated',
|
||||
function() {
|
||||
if (this.dependenciesPanels && this.dependenciesPanels.length) {
|
||||
$(this.dependenciesPanels[0]).data('node-prop', '');
|
||||
this.dependenciesPanelVisibilityChanged(this.dependenciesPanels[0]);
|
||||
}
|
||||
if (this.dependentsPanels && this.dependentsPanels.length) {
|
||||
$(this.dependentsPanels[0]).data('node-prop', '');
|
||||
this.dependentsPanelVisibilityChanged(this.dependentsPanels[0]);
|
||||
}
|
||||
}, this
|
||||
);
|
||||
|
||||
// We will render the grid objects in the panel after some time, because -
|
||||
// it is possible, it is not yet available.
|
||||
// Find the panels to render the grid.
|
||||
var dependenciesPanels = this.dependenciesPanels = pgBrowser.docker.findPanels('dependencies');
|
||||
var dependentsPanels = this.dependentsPanels = pgBrowser.docker.findPanels('dependents');
|
||||
|
||||
if (dependenciesPanels.length == 0) {
|
||||
pgBrowser.Events.on(
|
||||
'pgadmin-browser:panel-dependencies:' + wcDocker.EVENT.INIT,
|
||||
function() {
|
||||
this.dependenciesPanels = pgBrowser.docker.findPanels('dependencies');
|
||||
appendGridToPanel(this.dependenciesCollection, this.dependenciesPanels, false);
|
||||
|
||||
// If Dependencies panel exists and is focused then we need to listen the browser tree selection events.
|
||||
if ((dependenciesPanels[0].isVisible()) || dependenciesPanels.length != 1) {
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependencies);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', this.refreshDependencies, this);
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
} else {
|
||||
appendGridToPanel(this.dependenciesCollection, this.dependenciesPanels, false);
|
||||
|
||||
// If Dependencies panel exists and is focused then we need to listen the browser tree selection events.
|
||||
if ((dependenciesPanels[0].isVisible()) || dependenciesPanels.length != 1) {
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependencies);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', this.refreshDependencies, this);
|
||||
}
|
||||
}
|
||||
|
||||
if (dependentsPanels.length == 0) {
|
||||
pgBrowser.Events.on(
|
||||
'pgadmin-browser:panel-dependents:' + wcDocker.EVENT.INIT,
|
||||
function() {
|
||||
this.dependentsPanels = pgBrowser.docker.findPanels('dependents');
|
||||
appendGridToPanel(this.dependentCollection, this.dependentsPanels, true);
|
||||
|
||||
// If Dependents panel exists and is focused then we need to listen the browser tree selection events.
|
||||
if ((dependentsPanels[0].isVisible()) || dependentsPanels.length != 1) {
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependents);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', this.refreshDependents, this);
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
} else {
|
||||
appendGridToPanel(this.dependentCollection, this.dependentsPanels, true);
|
||||
|
||||
// If Dependents panel exists and is focused then we need to listen the browser tree selection events.
|
||||
if ((dependentsPanels[0].isVisible()) || dependentsPanels.length != 1) {
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showDependents);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', this.refreshDependents, this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Fetch the actual data and update the collection
|
||||
__updateCollection: function(collection, panel, url, messages, node, item, type) {
|
||||
var msg = messages[0],
|
||||
$container = panel[0].layout().scene().find('.pg-panel-content'),
|
||||
$msgContainer = $container.find('.pg-panel-depends-message'),
|
||||
$gridContainer = $container.find('.pg-panel-depends-container'),
|
||||
treeHierarchy = node.getTreeNodeHierarchy(item),
|
||||
n_type = type,
|
||||
cache_flag = {
|
||||
node_type: n_type,
|
||||
url: url,
|
||||
};
|
||||
|
||||
// Avoid unnecessary reloads
|
||||
if (_.isEqual($(panel[0]).data('node-prop'), cache_flag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache the current IDs for next time
|
||||
$(panel[0]).data('node-prop', cache_flag);
|
||||
|
||||
// Hide the grid container and show the default message container
|
||||
if (!$gridContainer.hasClass('d-none'))
|
||||
$gridContainer.addClass('d-none');
|
||||
$msgContainer.removeClass('d-none');
|
||||
|
||||
if (node) {
|
||||
msg = messages[1];
|
||||
/* We fetch the Dependencies and Dependents tab only for
|
||||
* those node who set the parameter hasDepends to true.
|
||||
*/
|
||||
if (node.hasDepends) {
|
||||
/* Set the message because ajax request may take time to
|
||||
* fetch the information from the server.
|
||||
*/
|
||||
msg = messages[2];
|
||||
$msgContainer.text(msg);
|
||||
|
||||
/* Updating the label for the 'field' type of the backbone model.
|
||||
* Label should be "Database" if the node type is tablespace or role
|
||||
* and dependent tab is selected. For other nodes and dependencies tab
|
||||
* it should be 'Restriction'.
|
||||
*/
|
||||
if (this.dependent && (node.type == 'tablespace' || node.type == 'role'))
|
||||
this.dependentGrid.columns.models[2].set({
|
||||
'label': gettext('Database'),
|
||||
});
|
||||
else {
|
||||
this.dependenciesGrid.columns.models[2].set({
|
||||
'label': gettext('Restriction'),
|
||||
});
|
||||
this.dependentGrid.columns.models[2].set({
|
||||
'label': gettext('Restriction'),
|
||||
});
|
||||
}
|
||||
|
||||
// Hide message container and show grid container.
|
||||
$msgContainer.addClass('d-none');
|
||||
$gridContainer.removeClass('d-none');
|
||||
|
||||
var timer = setTimeout(function() {
|
||||
// notify user if request is taking longer than 1 second
|
||||
|
||||
$msgContainer.text(gettext('Retrieving data from the server...'));
|
||||
$msgContainer.removeClass('d-none');
|
||||
if ($gridContainer) {
|
||||
$gridContainer.addClass('d-none');
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Set the url, fetch the data and update the collection
|
||||
collection.url = url;
|
||||
collection.fetch({
|
||||
reset: true,
|
||||
success: function() {
|
||||
clearTimeout(timer);
|
||||
$gridContainer.removeClass('d-none');
|
||||
if (!$msgContainer.hasClass('d-none')) {
|
||||
$msgContainer.addClass('d-none');
|
||||
}
|
||||
},
|
||||
error: function(coll, xhr, error, message) {
|
||||
var _label = treeHierarchy[n_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,
|
||||
S(
|
||||
gettext('Error retrieving the information - %s')
|
||||
).sprintf(message || _label).value(),
|
||||
function() {
|
||||
console.warn(arguments);
|
||||
}
|
||||
);
|
||||
}
|
||||
// show failed message.
|
||||
$msgContainer.text(gettext('Failed to retrieve data from the server.'));
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
if (msg != '') {
|
||||
$msgContainer.text(msg);
|
||||
}
|
||||
},
|
||||
refreshDependents: function(item, data, node) {
|
||||
var that = this,
|
||||
cache_flag = {
|
||||
node_type: data._type,
|
||||
url: node.generate_url(item, 'dependent', data, true),
|
||||
};
|
||||
|
||||
if (_.isEqual($(that.dependentsPanels[0]).data('node-prop'), cache_flag)) {
|
||||
// Reset the current item selection
|
||||
$(that.dependentsPanels[0]).data('node-prop', '');
|
||||
that.showDependents(item, data, node);
|
||||
}
|
||||
},
|
||||
showDependents: function(item, data, node) {
|
||||
/**
|
||||
* We can't start fetching the Dependents immediately, it is possible the user
|
||||
* is just using the keyboard to select the node, and just traversing
|
||||
* through. We will wait for some time before fetching the Dependents
|
||||
**/
|
||||
var self = this;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
self.dependent = true;
|
||||
if (self.timeout) {
|
||||
clearTimeout(self.timeout);
|
||||
}
|
||||
self.timeout = setTimeout(
|
||||
self.__updateCollection(
|
||||
self.dependentCollection, self.dependentsPanels,
|
||||
node.generate_url(item, 'dependent', data, true), [
|
||||
gettext('No object selected.'),
|
||||
gettext('No dependent information is available for the current object.'),
|
||||
gettext('Fetching dependent information from the server...'),
|
||||
], node, item, data._type
|
||||
), 400
|
||||
);
|
||||
},
|
||||
dependentsPanelVisibilityChanged: 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.ShowNodeDepends.showDependents.apply(pgBrowser.ShowNodeDepends, [i, d, n]);
|
||||
|
||||
// We will start listening the tree selection event.
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', pgBrowser.ShowNodeDepends.showDependents);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', pgBrowser.ShowNodeDepends.refreshDependents, this);
|
||||
} else {
|
||||
|
||||
// We don't need to listen the tree item selection event.
|
||||
pgBrowser.Events.off('pgadmin-browser:tree:selected', pgBrowser.ShowNodeDepends.showDependents);
|
||||
pgBrowser.Events.off('pgadmin-browser:tree:refreshing', pgBrowser.ShowNodeDepends.refreshDependents, this);
|
||||
}
|
||||
},
|
||||
refreshDependencies: function(item, data, node) {
|
||||
var that = this,
|
||||
cache_flag = {
|
||||
node_type: data._type,
|
||||
url: node.generate_url(item, 'dependency', data, true),
|
||||
};
|
||||
|
||||
if (_.isEqual($(that.dependenciesPanels[0]).data('node-prop'), cache_flag)) {
|
||||
// Reset the current item selection
|
||||
$(that.dependenciesPanels[0]).data('node-prop', '');
|
||||
that.showDependencies(item, data, node);
|
||||
}
|
||||
},
|
||||
showDependencies: function(item, data, node) {
|
||||
/**
|
||||
* We can't start fetching the Dependencies immediately, it is possible the user
|
||||
* is just using the keyboard to select the node, and just traversing
|
||||
* through. We will wait for some time before fetching the Dependencies
|
||||
**/
|
||||
var self = this;
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
self.dependent = false;
|
||||
if (self.timeout) {
|
||||
clearTimeout(self.timeout);
|
||||
}
|
||||
self.timeout = setTimeout(
|
||||
self.__updateCollection(
|
||||
self.dependenciesCollection,
|
||||
self.dependenciesPanels,
|
||||
node.generate_url(item, 'dependency', data, true), [gettext('Please select an object in the tree view.'), gettext('No dependency information is available for the current object.'),
|
||||
gettext('Fetching dependency information from the server...'),
|
||||
],
|
||||
node,
|
||||
item,
|
||||
data._type
|
||||
), 400
|
||||
);
|
||||
},
|
||||
dependenciesPanelVisibilityChanged: 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.ShowNodeDepends.showDependencies.apply(pgBrowser.ShowNodeDepends, [i, d, n]);
|
||||
|
||||
// We will start listening the tree selection event.
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:selected', pgBrowser.ShowNodeDepends.showDependencies);
|
||||
pgBrowser.Events.on('pgadmin-browser:tree:refreshing', pgBrowser.ShowNodeDepends.refreshDependencies, this);
|
||||
} else {
|
||||
// We don't need to listen the tree item selection event.
|
||||
pgBrowser.Events.off('pgadmin-browser:tree:selected', pgBrowser.ShowNodeDepends.showDependencies);
|
||||
pgBrowser.Events.off('pgadmin-browser:tree:refreshing', pgBrowser.ShowNodeDepends.refreshDependencies, this);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return pgBrowser.ShowNodeDepends;
|
||||
});
|
||||
@@ -235,7 +235,8 @@ module.exports = {
|
||||
'pgadmin.dashboard' +
|
||||
',pgadmin.tools.user_management' +
|
||||
',pgadmin.browser.object_statistics' +
|
||||
',pgadmin.browser.object_depends' +
|
||||
',pgadmin.browser.dependencies' +
|
||||
',pgadmin.browser.dependents' +
|
||||
',pgadmin.browser.object_sql' +
|
||||
',pgadmin.browser.bgprocess' +
|
||||
',pgadmin.node.server_group' +
|
||||
|
||||
@@ -195,7 +195,8 @@ var webpackShimConfig = {
|
||||
'pgadmin.browser.messages': '/browser/js/messages',
|
||||
'pgadmin.browser.node': path.join(__dirname, './pgadmin/browser/static/js/node'),
|
||||
'pgadmin.browser.node.ui': path.join(__dirname, './pgadmin/browser/static/js/node.ui'),
|
||||
'pgadmin.browser.object_depends': path.join(__dirname, './pgadmin/misc/depends/static/js/depends'),
|
||||
'pgadmin.browser.dependencies': path.join(__dirname, './pgadmin/misc/dependencies/static/js/dependencies'),
|
||||
'pgadmin.browser.dependents': path.join(__dirname, './pgadmin/misc/dependents/static/js/dependents'),
|
||||
'pgadmin.browser.object_sql': path.join(__dirname, './pgadmin/misc/sql/static/js/sql'),
|
||||
'pgadmin.browser.object_statistics': path.join(__dirname, './pgadmin/misc/statistics/static/js/statistics'),
|
||||
'pgadmin.browser.panel': path.join(__dirname, './pgadmin/browser/static/js/panel'),
|
||||
|
||||
Reference in New Issue
Block a user