mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Realtime preference handling for the Dashboards and Debugger. Fixes #3294
This commit is contained in:
parent
ae814d76d3
commit
f7e43d5e50
@ -21,7 +21,7 @@ Bug fixes
|
||||
|
||||
| `Bug #3185 <https://redmine.postgresql.org/issues/3185>`_ - Fix the upgrade check on macOS.
|
||||
| `Bug #3191 <https://redmine.postgresql.org/issues/3191>`_ - Fix a number of debugger execution issues.
|
||||
| `Bug #3294 <https://redmine.postgresql.org/issues/3294>`_ - Infrastructure (and changes to the Query Tool) for realtime preference handling.
|
||||
| `Bug #3294 <https://redmine.postgresql.org/issues/3294>`_ - Infrastructure (and changes to the Query Tool, Dashboards and Debugger) for realtime preference handling.
|
||||
| `Bug #3309 <https://redmine.postgresql.org/issues/3309>`_ - Fix Directory format support for backups.
|
||||
| `Bug #3316 <https://redmine.postgresql.org/issues/3316>`_ - Support running on systems without a system tray.
|
||||
| `Bug #3319 <https://redmine.postgresql.org/issues/3319>`_ - Cleanup and fix handling of Query Tool Cancel button status.
|
||||
|
@ -170,10 +170,9 @@ define(
|
||||
if (pgBrowser.tree) {
|
||||
pgBrowser.save_current_layout(pgBrowser);
|
||||
var selectedNode = pgBrowser.tree.selected();
|
||||
// Discontinue this event after first time visible
|
||||
this.off(wcDocker.EVENT.VISIBILITY_CHANGED);
|
||||
if (!_.isUndefined(pgAdmin.Dashboard))
|
||||
pgAdmin.Dashboard.toggleVisibility(true);
|
||||
if (!_.isUndefined(pgAdmin.Dashboard)) {
|
||||
pgAdmin.Dashboard.toggleVisibility(pgBrowser.panels.dashboard.panel.isVisible());
|
||||
}
|
||||
// Explicitly trigger tree selected event when we add the tab.
|
||||
pgBrowser.Events.trigger('pgadmin-browser:tree:selected', selectedNode,
|
||||
pgBrowser.tree.itemData(selectedNode), pgBrowser.Node);
|
||||
|
@ -280,8 +280,6 @@ def index(sid=None, did=None):
|
||||
rates = {}
|
||||
settings = {}
|
||||
|
||||
prefs = Preferences.module('dashboards')
|
||||
|
||||
# Get the server version
|
||||
if sid is not None:
|
||||
g.manager = get_driver(
|
||||
@ -293,22 +291,6 @@ def index(sid=None, did=None):
|
||||
if not g.conn.connected():
|
||||
g.version = 0
|
||||
|
||||
session_stats_refresh_pref = prefs.preference('session_stats_refresh')
|
||||
rates['session_stats_refresh'] = session_stats_refresh_pref.get()
|
||||
tps_stats_refresh_pref = prefs.preference('tps_stats_refresh')
|
||||
rates['tps_stats_refresh'] = tps_stats_refresh_pref.get()
|
||||
ti_stats_refresh_pref = prefs.preference('ti_stats_refresh')
|
||||
rates['ti_stats_refresh'] = ti_stats_refresh_pref.get()
|
||||
to_stats_refresh_pref = prefs.preference('to_stats_refresh')
|
||||
rates['to_stats_refresh'] = to_stats_refresh_pref.get()
|
||||
bio_stats_refresh_pref = prefs.preference('bio_stats_refresh')
|
||||
rates['bio_stats_refresh'] = bio_stats_refresh_pref.get()
|
||||
# Whether to display graphs and server activity preferences
|
||||
show_graphs_pref = prefs.preference('show_graphs')
|
||||
settings['show_graphs'] = show_graphs_pref.get()
|
||||
show_activity_pref = prefs.preference('show_activity')
|
||||
settings['show_activity'] = show_activity_pref.get()
|
||||
|
||||
# Show the appropriate dashboard based on the identifiers passed to us
|
||||
if sid is None and did is None:
|
||||
return render_template('/dashboard/welcome_dashboard.html')
|
||||
@ -317,8 +299,7 @@ def index(sid=None, did=None):
|
||||
'/dashboard/server_dashboard.html',
|
||||
sid=sid,
|
||||
rates=rates,
|
||||
version=g.version,
|
||||
settings=settings
|
||||
version=g.version
|
||||
)
|
||||
else:
|
||||
return render_template(
|
||||
@ -326,8 +307,7 @@ def index(sid=None, did=None):
|
||||
sid=sid,
|
||||
did=did,
|
||||
rates=rates,
|
||||
version=g.version,
|
||||
settings=settings
|
||||
version=g.version
|
||||
)
|
||||
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.dashboard-header-spacer {
|
||||
padding-top: 15px;
|
||||
.dashboard-row {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.dashboard-link {
|
||||
@ -175,4 +175,6 @@
|
||||
margin-bottom: 0%;
|
||||
}
|
||||
|
||||
/* CSS to make subnode control look preety in backgrid - END */
|
||||
.dashboard-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
@ -192,6 +192,10 @@ define('pgadmin.dashboard', [
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
this.sid = this.did = -1;
|
||||
this.version = -1;
|
||||
|
||||
|
||||
// Bind the Dashboard object with the 'object_selected' function
|
||||
var selected = this.object_selected.bind(this);
|
||||
var disconnected = this.object_disconnected.bind(this);
|
||||
@ -205,6 +209,11 @@ define('pgadmin.dashboard', [
|
||||
// Load the default welcome dashboard
|
||||
var url = url_for('dashboard.index');
|
||||
|
||||
/* Store the interval ids of the graph interval functions so that we can clear
|
||||
* them when graphs are disabled
|
||||
*/
|
||||
this.intervalIds = {};
|
||||
|
||||
var dashboardPanel = pgBrowser.panels['dashboard'].panel;
|
||||
if (dashboardPanel) {
|
||||
var div = dashboardPanel.layout().scene().find('.pg-panel-content');
|
||||
@ -238,14 +247,17 @@ define('pgadmin.dashboard', [
|
||||
|
||||
// Handle treeview clicks
|
||||
object_selected: function(item, itemData, node) {
|
||||
let self = this;
|
||||
/* Clear all the interval functions of previous dashboards */
|
||||
self.clearIntervalId();
|
||||
if (itemData && itemData._type && dashboardVisible) {
|
||||
var treeHierarchy = node.getTreeNodeHierarchy(item),
|
||||
url = url_for('dashboard.index'),
|
||||
sid = -1,
|
||||
did = -1,
|
||||
b = pgAdmin.Browser,
|
||||
m = b && b.Nodes[itemData._type];
|
||||
|
||||
self.sid = self.did = -1;
|
||||
self.version = itemData.version;
|
||||
cancel_query_url = url_for('dashboard.index') + 'cancel_query/';
|
||||
terminate_session_url = url_for('dashboard.index') + 'terminate_session/';
|
||||
|
||||
@ -271,20 +283,21 @@ define('pgadmin.dashboard', [
|
||||
}
|
||||
} else {
|
||||
if ('database' in treeHierarchy) {
|
||||
sid = treeHierarchy.server._id;
|
||||
did = treeHierarchy.database._id;
|
||||
self.sid = treeHierarchy.server._id;
|
||||
self.did = treeHierarchy.database._id;
|
||||
is_server_dashboard = false;
|
||||
is_database_dashboard = true;
|
||||
url += sid + '/' + did;
|
||||
cancel_query_url += sid + '/' + did + '/';
|
||||
terminate_session_url += sid + '/' + did + '/';
|
||||
url += self.sid + '/' + self.did;
|
||||
cancel_query_url += self.sid + '/' + self.did + '/';
|
||||
terminate_session_url += self.sid + '/' + self.did + '/';
|
||||
} else if ('server' in treeHierarchy) {
|
||||
sid = treeHierarchy.server._id;
|
||||
self.sid = treeHierarchy.server._id;
|
||||
self.did = -1;
|
||||
is_server_dashboard = true;
|
||||
is_database_dashboard = false;
|
||||
url += sid;
|
||||
cancel_query_url += sid + '/';
|
||||
terminate_session_url += sid + '/';
|
||||
url += self.sid;
|
||||
cancel_query_url += self.sid + '/';
|
||||
terminate_session_url += self.sid + '/';
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +312,6 @@ define('pgadmin.dashboard', [
|
||||
// Avoid unnecessary reloads
|
||||
if (url != $(dashboardPanel).data('dashboard_url') ||
|
||||
(url == $(dashboardPanel).data('dashboard_url') && $(dashboardPanel).data('server_status') == false)) {
|
||||
// Clear out everything so any existing timers die off
|
||||
$(div).empty();
|
||||
|
||||
$.ajax({
|
||||
@ -309,6 +321,7 @@ define('pgadmin.dashboard', [
|
||||
})
|
||||
.done(function(data) {
|
||||
$(div).html(data);
|
||||
self.init_dashboard();
|
||||
})
|
||||
.fail(function() {
|
||||
$(div).html(
|
||||
@ -317,7 +330,9 @@ define('pgadmin.dashboard', [
|
||||
});
|
||||
$(dashboardPanel).data('server_status', true);
|
||||
}
|
||||
|
||||
else {
|
||||
self.init_dashboard();
|
||||
}
|
||||
} else {
|
||||
$(div).empty();
|
||||
$(div).html(
|
||||
@ -327,102 +342,16 @@ define('pgadmin.dashboard', [
|
||||
}
|
||||
// Cache the current IDs for next time
|
||||
$(dashboardPanel).data('dashboard_url', url);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Render a chart
|
||||
render_chart: function(
|
||||
container, data, dataset, sid, did, url, options, counter, refresh
|
||||
) {
|
||||
renderChartLoop: function(container, sid, did, url, options, counter, refresh) {
|
||||
var data = [],
|
||||
dataset = [];
|
||||
|
||||
// Data format:
|
||||
// [
|
||||
// { data: [[0, y0], [1, y1]...], label: 'Label 1', [options] },
|
||||
// { data: [[0, y0], [1, y1]...], label: 'Label 2', [options] },
|
||||
// { data: [[0, y0], [1, y1]...], label: 'Label 3', [options] }
|
||||
// ]
|
||||
|
||||
if (!dashboardVisible)
|
||||
return;
|
||||
|
||||
var y = 0,
|
||||
x;
|
||||
if (dataset.length == 0) {
|
||||
if (counter == true) {
|
||||
// Have we stashed initial values?
|
||||
if (_.isUndefined($(container).data('counter_previous_vals'))) {
|
||||
$(container).data('counter_previous_vals', data[0]);
|
||||
} else {
|
||||
// Create the initial data structure
|
||||
for (x in data[0]) {
|
||||
dataset.push({
|
||||
'data': [
|
||||
[0, data[0][x] - $(container).data('counter_previous_vals')[x]],
|
||||
],
|
||||
'label': x,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Create the initial data structure
|
||||
for (x in data[0]) {
|
||||
dataset.push({
|
||||
'data': [
|
||||
[0, data[0][x]],
|
||||
],
|
||||
'label': x,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (x in data[0]) {
|
||||
// Push new values onto the existing data structure
|
||||
// If this is a counter stat, we need to subtract the previous value
|
||||
if (counter == false) {
|
||||
dataset[y]['data'].unshift([0, data[0][x]]);
|
||||
} else {
|
||||
// Store the current value, minus the previous one we stashed.
|
||||
// It's possible the tab has been reloaded, in which case out previous values are gone
|
||||
if (_.isUndefined($(container).data('counter_previous_vals')))
|
||||
return;
|
||||
|
||||
dataset[y]['data'].unshift([0, data[0][x] - $(container).data('counter_previous_vals')[x]]);
|
||||
}
|
||||
|
||||
// Reset the time index to get a proper scrolling display
|
||||
for (var z = 0; z < dataset[y]['data'].length; z++) {
|
||||
dataset[y]['data'][z][0] = z;
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
$(container).data('counter_previous_vals', data[0]);
|
||||
}
|
||||
|
||||
// Remove uneeded elements
|
||||
for (x = 0; x < dataset.length; x++) {
|
||||
// Remove old data points
|
||||
if (dataset[x]['data'].length > 101) {
|
||||
dataset[x]['data'].pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw Graph, if the container still exists and has a size
|
||||
var dashboardPanel = pgBrowser.panels['dashboard'].panel;
|
||||
var div = dashboardPanel.layout().scene().find('.pg-panel-content');
|
||||
if ($(div).find(container).length) { // Exists?
|
||||
if (container.clientHeight > 0 && container.clientWidth > 0) { // Not hidden?
|
||||
Flotr.draw(container, dataset, options);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Animate
|
||||
var setTimeoutFunc = function() {
|
||||
var theIntervalFunc = function() {
|
||||
var path = url + sid;
|
||||
if (did != -1) {
|
||||
path += '/' + did;
|
||||
@ -435,7 +364,82 @@ define('pgadmin.dashboard', [
|
||||
.done(function(resp) {
|
||||
$(container).removeClass('graph-error');
|
||||
data = JSON.parse(resp);
|
||||
pgAdmin.Dashboard.render_chart(container, data, dataset, sid, did, url, options, counter, refresh);
|
||||
if (!dashboardVisible)
|
||||
return;
|
||||
|
||||
var y = 0,
|
||||
x;
|
||||
if (dataset.length == 0) {
|
||||
if (counter == true) {
|
||||
// Have we stashed initial values?
|
||||
if (_.isUndefined($(container).data('counter_previous_vals'))) {
|
||||
$(container).data('counter_previous_vals', data[0]);
|
||||
} else {
|
||||
// Create the initial data structure
|
||||
for (x in data[0]) {
|
||||
dataset.push({
|
||||
'data': [
|
||||
[0, data[0][x] - $(container).data('counter_previous_vals')[x]],
|
||||
],
|
||||
'label': x,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Create the initial data structure
|
||||
for (x in data[0]) {
|
||||
dataset.push({
|
||||
'data': [
|
||||
[0, data[0][x]],
|
||||
],
|
||||
'label': x,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (x in data[0]) {
|
||||
// Push new values onto the existing data structure
|
||||
// If this is a counter stat, we need to subtract the previous value
|
||||
if (counter == false) {
|
||||
dataset[y]['data'].unshift([0, data[0][x]]);
|
||||
} else {
|
||||
// Store the current value, minus the previous one we stashed.
|
||||
// It's possible the tab has been reloaded, in which case out previous values are gone
|
||||
if (_.isUndefined($(container).data('counter_previous_vals')))
|
||||
return;
|
||||
|
||||
dataset[y]['data'].unshift([0, data[0][x] - $(container).data('counter_previous_vals')[x]]);
|
||||
}
|
||||
|
||||
// Reset the time index to get a proper scrolling display
|
||||
for (var z = 0; z < dataset[y]['data'].length; z++) {
|
||||
dataset[y]['data'][z][0] = z;
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
$(container).data('counter_previous_vals', data[0]);
|
||||
}
|
||||
|
||||
// Remove uneeded elements
|
||||
for (x = 0; x < dataset.length; x++) {
|
||||
// Remove old data points
|
||||
if (dataset[x]['data'].length > 101) {
|
||||
dataset[x]['data'].pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw Graph, if the container still exists and has a size
|
||||
var dashboardPanel = pgBrowser.panels['dashboard'].panel;
|
||||
var div = dashboardPanel.layout().scene().find('.pg-panel-content');
|
||||
if ($(div).find(container).length) { // Exists?
|
||||
if (container.clientHeight > 0 && container.clientWidth > 0) { // Not hidden?
|
||||
Flotr.draw(container, dataset, options);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
})
|
||||
.fail(function(xhr) {
|
||||
let err = '';
|
||||
@ -463,15 +467,36 @@ define('pgadmin.dashboard', [
|
||||
$(container).html(
|
||||
'<div class="alert alert-' + cls + ' pg-panel-message" role="alert">' + msg + '</div>'
|
||||
);
|
||||
|
||||
// Try again...
|
||||
if (container.clientHeight > 0 && container.clientWidth > 0) {
|
||||
setTimeout(setTimeoutFunc, refresh * 1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
/* Execute once for the first time as setInterval will not do */
|
||||
theIntervalFunc();
|
||||
return setInterval(theIntervalFunc, refresh * 1000);
|
||||
},
|
||||
|
||||
setTimeout(setTimeoutFunc, refresh * 1000);
|
||||
// Render a chart
|
||||
render_chart: function(
|
||||
container, url, options, counter, chartName, prefName
|
||||
) {
|
||||
|
||||
// Data format:
|
||||
// [
|
||||
// { data: [[0, y0], [1, y1]...], label: 'Label 1', [options] },
|
||||
// { data: [[0, y0], [1, y1]...], label: 'Label 2', [options] },
|
||||
// { data: [[0, y0], [1, y1]...], label: 'Label 3', [options] }
|
||||
// ]
|
||||
|
||||
let self = this;
|
||||
if(self.intervalIds[chartName]
|
||||
&& self.old_preferences[prefName] != self.preferences[prefName]) {
|
||||
self.clearIntervalId(chartName);
|
||||
}
|
||||
if(!self.intervalIds[chartName]) {
|
||||
self.intervalIds[chartName] = self.renderChartLoop(
|
||||
container, self.sid, self.did, url,
|
||||
options, counter, self.preferences[prefName]
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// Handler function to support the "Add Server" link
|
||||
@ -503,12 +528,13 @@ define('pgadmin.dashboard', [
|
||||
},
|
||||
|
||||
// Render a grid
|
||||
render_grid: function(container, sid, did, url, columns) {
|
||||
var Datum = Backbone.Model.extend({});
|
||||
render_grid: function(container, url, columns) {
|
||||
var Datum = Backbone.Model.extend({}),
|
||||
self = this;
|
||||
|
||||
var path = url + sid;
|
||||
if (did != -1) {
|
||||
path += '/' + did;
|
||||
var path = url + self.sid;
|
||||
if (self.did != -1) {
|
||||
path += '/' + self.did;
|
||||
}
|
||||
|
||||
var Data = Backbone.Collection.extend({
|
||||
@ -527,6 +553,7 @@ define('pgadmin.dashboard', [
|
||||
});
|
||||
|
||||
// Render the grid
|
||||
$(container).empty();
|
||||
$(container).append(grid.render().el);
|
||||
|
||||
// Initialize a client-side filter to filter on the client
|
||||
@ -615,41 +642,59 @@ define('pgadmin.dashboard', [
|
||||
});
|
||||
},
|
||||
|
||||
// Rock n' roll on the server dashboard
|
||||
init_server_dashboard: function(
|
||||
sid,
|
||||
version,
|
||||
session_stats_refresh,
|
||||
tps_stats_refresh,
|
||||
ti_stats_refresh,
|
||||
to_stats_refresh,
|
||||
bio_stats_refresh,
|
||||
show_graphs,
|
||||
show_server_activity
|
||||
) {
|
||||
clearIntervalId: function(intervalId) {
|
||||
var self = this;
|
||||
if(!intervalId){
|
||||
_.each(self.intervalIds, function(id, key) {
|
||||
clearInterval(id);
|
||||
delete self.intervalIds[key];
|
||||
});
|
||||
}
|
||||
else {
|
||||
clearInterval(self.intervalIds[intervalId]);
|
||||
delete self.intervalIds[intervalId];
|
||||
}
|
||||
},
|
||||
|
||||
// Rock n' roll on the dashboard
|
||||
init_dashboard: function() {
|
||||
let self = this;
|
||||
|
||||
if(self.sid === -1 && self.did === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cache may take time to load for the first time
|
||||
* Keep trying till available
|
||||
*/
|
||||
let cacheIntervalId = setInterval(function() {
|
||||
try {
|
||||
if(window.top.pgAdmin.Browser.preference_version() > 0) {
|
||||
clearInterval(cacheIntervalId);
|
||||
self.reflectPreferences();
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
clearInterval(cacheIntervalId);
|
||||
throw err;
|
||||
}
|
||||
},0);
|
||||
|
||||
/* Register for preference changed event broadcasted */
|
||||
pgBrowser.onPreferencesChange('dashboards', function() {
|
||||
self.reflectPreferences();
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
reflectPreferences: function() {
|
||||
/* Common things can come here */
|
||||
var self = this;
|
||||
var div_sessions = $('.dashboard-container').find('#graph-sessions')[0];
|
||||
var div_tps = $('.dashboard-container').find('#graph-tps')[0];
|
||||
var div_ti = $('.dashboard-container').find('#graph-ti')[0];
|
||||
var div_to = $('.dashboard-container').find('#graph-to')[0];
|
||||
var div_bio = $('.dashboard-container').find('#graph-bio')[0];
|
||||
var div_server_activity = $('.dashboard-container').find('#server_activity');
|
||||
var div_server_locks = $('.dashboard-container').find('#server_locks');
|
||||
var div_server_prepared = $('.dashboard-container').find('#server_prepared');
|
||||
var div_server_config = $('.dashboard-container').find('#server_config');
|
||||
var dataset_sessions = [];
|
||||
var data_sessions = [];
|
||||
var dataset_tps = [];
|
||||
var data_tps = [];
|
||||
var dataset_ti = [];
|
||||
var data_ti = [];
|
||||
var dataset_to = [];
|
||||
var data_to = [];
|
||||
var dataset_bio = [];
|
||||
var data_bio = [];
|
||||
|
||||
// Fake DB ID
|
||||
var did = -1;
|
||||
|
||||
var options_line = {
|
||||
parseFloat: false,
|
||||
xaxis: {
|
||||
@ -664,40 +709,85 @@ define('pgadmin.dashboard', [
|
||||
position: 'nw',
|
||||
backgroundColor: '#D2E8FF',
|
||||
},
|
||||
shadowSize: 0,
|
||||
resolution : 5,
|
||||
};
|
||||
|
||||
// Display graphs
|
||||
if(show_graphs) {
|
||||
/* We will use old preferences for selective graph updates on preference change */
|
||||
if(self.preferences) {
|
||||
self.old_preferences = self.preferences;
|
||||
self.preferences = window.top.pgAdmin.Browser.get_preferences_for_module('dashboards');
|
||||
}
|
||||
else {
|
||||
self.preferences = window.top.pgAdmin.Browser.get_preferences_for_module('dashboards');
|
||||
self.old_preferences = self.preferences;
|
||||
}
|
||||
|
||||
if(self.preferences.show_graphs && $('#dashboard-graphs').hasClass('dashboard-hidden')) {
|
||||
$('#dashboard-graphs').removeClass('dashboard-hidden');
|
||||
}
|
||||
else if(!self.preferences.show_graphs) {
|
||||
$('#dashboard-graphs').addClass('dashboard-hidden');
|
||||
self.clearIntervalId();
|
||||
}
|
||||
|
||||
if (self.preferences.show_activity && $('#dashboard-activity').hasClass('dashboard-hidden')) {
|
||||
$('#dashboard-activity').removeClass('dashboard-hidden');
|
||||
}
|
||||
else if(!self.preferences.show_activity) {
|
||||
$('#dashboard-activity').addClass('dashboard-hidden');
|
||||
}
|
||||
|
||||
if(self.preferences.show_graphs) {
|
||||
// Render the graphs
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_sessions, data_sessions, dataset_sessions, sid, did,
|
||||
url_for('dashboard.session_stats'), options_line, false,
|
||||
session_stats_refresh
|
||||
div_sessions, url_for('dashboard.session_stats'), options_line, false,
|
||||
'session_stats', 'session_stats_refresh'
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_tps, data_tps, dataset_tps, sid, did,
|
||||
url_for('dashboard.tps_stats'), options_line, true,
|
||||
tps_stats_refresh
|
||||
div_tps, url_for('dashboard.tps_stats'), options_line, true,
|
||||
'tps_stats','tps_stats_refresh'
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_ti, data_ti, dataset_ti, sid, did,
|
||||
url_for('dashboard.ti_stats'), options_line, true,
|
||||
ti_stats_refresh
|
||||
div_ti, url_for('dashboard.ti_stats'), options_line, true,
|
||||
'ti_stats', 'ti_stats_refresh'
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_to, data_to, dataset_to, sid, did,
|
||||
url_for('dashboard.to_stats'), options_line, true,
|
||||
to_stats_refresh
|
||||
div_to, url_for('dashboard.to_stats'), options_line, true,
|
||||
'to_stats','to_stats_refresh'
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_bio, data_bio, dataset_bio, sid, did,
|
||||
url_for('dashboard.bio_stats'), options_line, true,
|
||||
bio_stats_refresh
|
||||
div_bio, url_for('dashboard.bio_stats'), options_line, true,
|
||||
'bio_stats','bio_stats_refresh'
|
||||
);
|
||||
}
|
||||
|
||||
/* Dashboard specific preferences can be updated in the
|
||||
* appropriate functions
|
||||
*/
|
||||
if(is_server_dashboard) {
|
||||
self.reflectPreferencesServer();
|
||||
}
|
||||
else if(is_database_dashboard) {
|
||||
self.reflectPreferencesDatabase();
|
||||
}
|
||||
|
||||
if(!self.preferences.show_graphs && !self.preferences.show_activity) {
|
||||
$('#dashboard-none-show').removeClass('dashboard-hidden');
|
||||
}
|
||||
else {
|
||||
$('#dashboard-none-show').addClass('dashboard-hidden');
|
||||
}
|
||||
},
|
||||
reflectPreferencesServer: function() {
|
||||
var self = this;
|
||||
var div_server_activity = $('.dashboard-container').find('#server_activity');
|
||||
var div_server_locks = $('.dashboard-container').find('#server_locks');
|
||||
var div_server_prepared = $('.dashboard-container').find('#server_prepared');
|
||||
var div_server_config = $('.dashboard-container').find('#server_config');
|
||||
|
||||
// Display server activity
|
||||
if (show_server_activity) {
|
||||
if (self.preferences.show_activity) {
|
||||
var server_activity_columns = [{
|
||||
name: 'pid',
|
||||
label: gettext('PID'),
|
||||
@ -735,7 +825,7 @@ define('pgadmin.dashboard', [
|
||||
cell: 'string',
|
||||
}];
|
||||
|
||||
if (version < 90600) {
|
||||
if (self.version < 90600) {
|
||||
server_activity_columns = server_activity_columns.concat(
|
||||
[{
|
||||
name: 'waiting',
|
||||
@ -766,7 +856,7 @@ define('pgadmin.dashboard', [
|
||||
|
||||
// Add version to each field
|
||||
_.each(subNodeFieldsModel[0].fields, function(obj) {
|
||||
obj['version'] = version;
|
||||
obj['version'] = self.version;
|
||||
});
|
||||
|
||||
// Add cancel active query button
|
||||
@ -775,7 +865,7 @@ define('pgadmin.dashboard', [
|
||||
label: '',
|
||||
cell: SessionDetailsCell,
|
||||
cell_priority: -1,
|
||||
postgres_version: version,
|
||||
postgres_version: self.version,
|
||||
schema: subNodeFieldsModel,
|
||||
});
|
||||
|
||||
@ -788,7 +878,7 @@ define('pgadmin.dashboard', [
|
||||
editable: false,
|
||||
cell_priority: -1,
|
||||
canDeleteRow: pgAdmin.Dashboard.can_take_action,
|
||||
postgres_version: version,
|
||||
postgres_version: self.version,
|
||||
});
|
||||
|
||||
server_activity_columns.unshift({
|
||||
@ -799,7 +889,7 @@ define('pgadmin.dashboard', [
|
||||
editable: false,
|
||||
cell_priority: -1,
|
||||
canDeleteRow: pgAdmin.Dashboard.can_take_action,
|
||||
postgres_version: version,
|
||||
postgres_version: self.version,
|
||||
});
|
||||
|
||||
var server_locks_columns = [{
|
||||
@ -929,20 +1019,16 @@ define('pgadmin.dashboard', [
|
||||
|
||||
// Render the tabs, but only get data for the activity tab for now
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_server_activity, sid, did,
|
||||
url_for('dashboard.activity'), server_activity_columns
|
||||
div_server_activity, url_for('dashboard.activity'), server_activity_columns
|
||||
);
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_server_locks, sid, did, url_for('dashboard.locks'),
|
||||
server_locks_columns
|
||||
div_server_locks, url_for('dashboard.locks'), server_locks_columns
|
||||
);
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_server_prepared, sid, did, url_for('dashboard.prepared'),
|
||||
server_prepared_columns
|
||||
div_server_prepared, url_for('dashboard.prepared'), server_prepared_columns
|
||||
);
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_server_config, sid, did, url_for('dashboard.config'),
|
||||
server_config_columns
|
||||
div_server_config, url_for('dashboard.config'), server_config_columns
|
||||
);
|
||||
|
||||
pgAdmin.Dashboard.render_grid_data(div_server_activity);
|
||||
@ -969,7 +1055,7 @@ define('pgadmin.dashboard', [
|
||||
});
|
||||
|
||||
// Handle button clicks
|
||||
$('button').on('click',() => {
|
||||
$('button').off('click').on('click',() => {
|
||||
switch (this.id) {
|
||||
case 'btn_server_activity_refresh':
|
||||
pgAdmin.Dashboard.render_grid_data(div_server_activity);
|
||||
@ -990,87 +1076,14 @@ define('pgadmin.dashboard', [
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// Rock n' roll on the database dashboard
|
||||
init_database_dashboard: function(
|
||||
sid,
|
||||
did,
|
||||
version,
|
||||
session_stats_refresh,
|
||||
tps_stats_refresh,
|
||||
ti_stats_refresh,
|
||||
to_stats_refresh,
|
||||
bio_stats_refresh,
|
||||
show_graphs,
|
||||
show_database_activity
|
||||
) {
|
||||
var div_sessions = document.getElementById('graph-sessions');
|
||||
var div_tps = document.getElementById('graph-tps');
|
||||
var div_ti = document.getElementById('graph-ti');
|
||||
var div_to = document.getElementById('graph-to');
|
||||
var div_bio = document.getElementById('graph-bio');
|
||||
reflectPreferencesDatabase: function() {
|
||||
var self = this;
|
||||
var div_database_activity = document.getElementById('database_activity');
|
||||
var div_database_locks = document.getElementById('database_locks');
|
||||
var div_database_prepared = document.getElementById('database_prepared');
|
||||
var dataset_sessions = [];
|
||||
var data_sessions = [];
|
||||
var dataset_tps = [];
|
||||
var data_tps = [];
|
||||
var dataset_ti = [];
|
||||
var data_ti = [];
|
||||
var dataset_to = [];
|
||||
var data_to = [];
|
||||
var dataset_bio = [];
|
||||
var data_bio = [];
|
||||
|
||||
var options_line = {
|
||||
parseFloat: false,
|
||||
xaxis: {
|
||||
min: 100,
|
||||
max: 0,
|
||||
autoscale: 0,
|
||||
},
|
||||
yaxis: {
|
||||
autoscale: 1,
|
||||
},
|
||||
legend: {
|
||||
position: 'nw',
|
||||
backgroundColor: '#D2E8FF',
|
||||
},
|
||||
};
|
||||
|
||||
// Display graphs
|
||||
if(show_graphs) {
|
||||
// Render the graphs
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_sessions, data_sessions, dataset_sessions, sid, did,
|
||||
url_for('dashboard.session_stats'), options_line, false,
|
||||
session_stats_refresh
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_tps, data_tps, dataset_tps, sid, did,
|
||||
url_for('dashboard.tps_stats'), options_line, true,
|
||||
tps_stats_refresh
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_ti, data_ti, dataset_ti, sid, did,
|
||||
url_for('dashboard.ti_stats'), options_line, true,
|
||||
ti_stats_refresh
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_to, data_to, dataset_to, sid, did,
|
||||
url_for('dashboard.to_stats'), options_line, true,
|
||||
to_stats_refresh
|
||||
);
|
||||
pgAdmin.Dashboard.render_chart(
|
||||
div_bio, data_bio, dataset_bio, sid, did,
|
||||
url_for('dashboard.bio_stats'), options_line, true,
|
||||
bio_stats_refresh
|
||||
);
|
||||
}
|
||||
|
||||
// Display server activity
|
||||
if (show_database_activity) {
|
||||
if (self.preferences.show_activity) {
|
||||
var database_activity_columns = [{
|
||||
name: 'pid',
|
||||
label: gettext('PID'),
|
||||
@ -1103,7 +1116,7 @@ define('pgadmin.dashboard', [
|
||||
cell: 'string',
|
||||
}];
|
||||
|
||||
if (version < 90600) {
|
||||
if (self.version < 90600) {
|
||||
database_activity_columns = database_activity_columns.concat(
|
||||
[{
|
||||
name: 'waiting',
|
||||
@ -1134,7 +1147,7 @@ define('pgadmin.dashboard', [
|
||||
|
||||
// Add version to each field
|
||||
_.each(subNodeFieldsModel[0].fields, function(obj) {
|
||||
obj['version'] = version;
|
||||
obj['version'] = self.version;
|
||||
});
|
||||
|
||||
// Add cancel active query button
|
||||
@ -1143,7 +1156,7 @@ define('pgadmin.dashboard', [
|
||||
label: '',
|
||||
cell: SessionDetailsCell,
|
||||
cell_priority: -1,
|
||||
postgres_version: version,
|
||||
postgres_version: self.version,
|
||||
schema: subNodeFieldsModel,
|
||||
});
|
||||
|
||||
@ -1155,7 +1168,7 @@ define('pgadmin.dashboard', [
|
||||
editable: false,
|
||||
cell_priority: -1,
|
||||
canDeleteRow: pgAdmin.Dashboard.can_take_action,
|
||||
postgres_version: version,
|
||||
postgres_version: self.version,
|
||||
});
|
||||
database_activity_columns.unshift({
|
||||
name: 'pg-backform-delete',
|
||||
@ -1165,7 +1178,7 @@ define('pgadmin.dashboard', [
|
||||
editable: false,
|
||||
cell_priority: -1,
|
||||
canDeleteRow: pgAdmin.Dashboard.can_take_action,
|
||||
postgres_version: version,
|
||||
postgres_version: self.version,
|
||||
});
|
||||
|
||||
var database_locks_columns = [{
|
||||
@ -1258,22 +1271,19 @@ define('pgadmin.dashboard', [
|
||||
|
||||
// Render the tabs, but only get data for the activity tab for now
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_database_activity, sid, did, url_for('dashboard.activity'),
|
||||
database_activity_columns
|
||||
div_database_activity, url_for('dashboard.activity'), database_activity_columns
|
||||
);
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_database_locks, sid, did, url_for('dashboard.locks'),
|
||||
database_locks_columns
|
||||
div_database_locks, url_for('dashboard.locks'), database_locks_columns
|
||||
);
|
||||
pgAdmin.Dashboard.render_grid(
|
||||
div_database_prepared, sid, did, url_for('dashboard.prepared'),
|
||||
database_prepared_columns
|
||||
div_database_prepared, url_for('dashboard.prepared'), database_prepared_columns
|
||||
);
|
||||
|
||||
pgAdmin.Dashboard.render_grid_data(div_database_activity);
|
||||
|
||||
// (Re)render the appropriate tab
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
|
||||
$('a[data-toggle="tab"]').off('shown.bs.tab').on('shown.bs.tab', function(e) {
|
||||
switch ($(e.target).attr('aria-controls')) {
|
||||
case 'tab_database_activity':
|
||||
pgAdmin.Dashboard.render_grid_data(div_database_activity);
|
||||
@ -1290,7 +1300,7 @@ define('pgadmin.dashboard', [
|
||||
});
|
||||
|
||||
// Handle button clicks
|
||||
$('button').on('click',() => {
|
||||
$('button').off('click').on('click',() => {
|
||||
switch (this.id) {
|
||||
case 'btn_database_activity_refresh':
|
||||
pgAdmin.Dashboard.render_grid_data(div_database_activity);
|
||||
@ -1308,7 +1318,12 @@ define('pgadmin.dashboard', [
|
||||
}
|
||||
},
|
||||
toggleVisibility: function(flag) {
|
||||
// let self = this;
|
||||
dashboardVisible = flag;
|
||||
|
||||
// if(dashboardVisible) {
|
||||
// self.init_dashboard();
|
||||
// }
|
||||
},
|
||||
can_take_action: function(m) {
|
||||
// We will validate if user is allowed to cancel the active query
|
||||
|
@ -1,135 +1,110 @@
|
||||
<div class="dashboard-container">
|
||||
{% if settings.show_graphs %}
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Database sessions') }}</legend>
|
||||
<div id="dashboard-graphs" class="dashboard-hidden">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Database sessions') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Transactions per second') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Transactions per second') }}</legend>
|
||||
<div class="row dashboard-row">
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-sessions" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-tps" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-sessions" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-tps" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row dashboard-header-spacer">
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples in') }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples in') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples out') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Block I/O') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples out') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Block I/O') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-ti" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-to" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-bio" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if settings.show_activity %}
|
||||
{# If we are displaying graphs then only we need space on top #}
|
||||
{% if settings.show_graphs %}
|
||||
<div class="row dashboard-header-spacer">
|
||||
{% else %}
|
||||
<div class="row">
|
||||
{% endif %}
|
||||
<div class="col-xs-12">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Database activity') }}</legend>
|
||||
<div class="row dashboard-row">
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-ti" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-to" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-bio" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="dashboard-tab-container">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs dashboard-tab-panel" role="tablist">
|
||||
<li role="presentation" class="active dashboard-tab"><a href="#tab_panel_database_activity"
|
||||
aria-controls="tab_database_activity"
|
||||
role="tab" data-toggle="tab">{{ _('Sessions') }}</a>
|
||||
</li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_database_locks"
|
||||
aria-controls="tab_database_locks" role="tab"
|
||||
data-toggle="tab">{{ _('Locks') }}</a></li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_database_prepared"
|
||||
aria-controls="tab_database_prepared" role="tab"
|
||||
data-toggle="tab">{{ _('Prepared Transactions') }}</a></li>
|
||||
</ul>
|
||||
<div id="dashboard-activity" class="dashboard-hidden">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Database activity') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row dashboard-row">
|
||||
<div class="col-xs-12">
|
||||
<div class="dashboard-tab-container">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs dashboard-tab-panel" role="tablist">
|
||||
<li role="presentation" class="active dashboard-tab"><a href="#tab_panel_database_activity"
|
||||
aria-controls="tab_database_activity"
|
||||
role="tab" data-toggle="tab">{{ _('Sessions') }}</a>
|
||||
</li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_database_locks"
|
||||
aria-controls="tab_database_locks" role="tab"
|
||||
data-toggle="tab">{{ _('Locks') }}</a></li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_database_prepared"
|
||||
aria-controls="tab_database_prepared" role="tab"
|
||||
data-toggle="tab">{{ _('Prepared Transactions') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="tab_panel_database_activity">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_database_activity_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="database_activity_filter"></div>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="tab_panel_database_activity">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_database_activity_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="database_activity_filter"></div>
|
||||
</div>
|
||||
<div id="database_activity" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="database_activity" class="grid-container"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_database_locks">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_database_locks_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="database_locks_filter"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_database_locks">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_database_locks_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="database_locks_filter"></div>
|
||||
</div>
|
||||
<div id="database_locks" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="database_locks" class="grid-container"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_database_prepared">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_database_prepared_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="database_prepared_filter"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_database_prepared">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_database_prepared_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="database_prepared_filter"></div>
|
||||
</div>
|
||||
<div id="database_prepared" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="database_prepared" class="grid-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not settings.show_graphs and not settings.show_activity %}
|
||||
<div class="alert alert-info pg-panel-message" role="alert">
|
||||
<div id="dashboard-none-show" class="alert alert-info pg-panel-message dashboard-hidden" role="alert">
|
||||
{{ _('All Dashboard elements are currently disabled.') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Initiate database dashboard
|
||||
pgAdmin.Dashboard.init_database_dashboard(
|
||||
{{ sid }},
|
||||
{{ did }},
|
||||
{{ version }},
|
||||
{{ rates.session_stats_refresh }},
|
||||
{{ rates.tps_stats_refresh }},
|
||||
{{ rates.ti_stats_refresh }},
|
||||
{{ rates.to_stats_refresh }},
|
||||
{{ rates.bio_stats_refresh }},
|
||||
{{ settings.show_graphs|lower }},
|
||||
{{ settings.show_activity|lower }}
|
||||
);
|
||||
</script>
|
||||
|
@ -1,144 +1,120 @@
|
||||
<div class="dashboard-container">
|
||||
{% if settings.show_graphs %}
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Server sessions') }}</legend>
|
||||
<div id="dashboard-graphs" class="dashboard-hidden">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Server sessions') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Transactions per second') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Transactions per second') }}</legend>
|
||||
<div class="row dashboard-row">
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-sessions" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-tps" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-sessions" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div id="graph-tps" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row dashboard-header-spacer">
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples in') }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples in') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples out') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Block I/O') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Tuples out') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Block I/O') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-ti" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-to" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-bio" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if settings.show_activity %}
|
||||
{# If we are displaying graphs then only we need space on top #}
|
||||
{% if settings.show_graphs %}
|
||||
<div class="row dashboard-header-spacer">
|
||||
{% else %}
|
||||
<div class="row">
|
||||
{% endif %}
|
||||
<div class="col-xs-12">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Server activity') }}</legend>
|
||||
<div class="row dashboard-row">
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-ti" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-to" class="graph-container"></div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<div id="graph-bio" class="graph-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="dashboard-tab-container">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs dashboard-tab-panel" role="tablist">
|
||||
<li role="presentation" class="active dashboard-tab"><a href="#tab_panel_server_activity"
|
||||
aria-controls="tab_server_activity"
|
||||
role="tab" data-toggle="tab">{{ _('Sessions') }}</a>
|
||||
</li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_server_locks"
|
||||
aria-controls="tab_server_locks" role="tab"
|
||||
data-toggle="tab">{{ _('Locks') }}</a></li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_server_prepared"
|
||||
aria-controls="tab_server_prepared" role="tab"
|
||||
data-toggle="tab">{{ _('Prepared Transactions') }}</a></li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_server_config"
|
||||
aria-controls="tab_server_config" role="tab"
|
||||
data-toggle="tab">{{ _('Configuration') }}</a></li>
|
||||
</ul>
|
||||
<div id="dashboard-activity" class="dashboard-hidden">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="obj_properties">
|
||||
<legend class="badge">{{ _('Server activity') }}</legend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row dashboard-row">
|
||||
<div class="col-xs-12">
|
||||
<div class="dashboard-tab-container">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs dashboard-tab-panel" role="tablist">
|
||||
<li role="presentation" class="active dashboard-tab"><a href="#tab_panel_server_activity"
|
||||
aria-controls="tab_server_activity"
|
||||
role="tab" data-toggle="tab">{{ _('Sessions') }}</a>
|
||||
</li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_server_locks"
|
||||
aria-controls="tab_server_locks" role="tab"
|
||||
data-toggle="tab">{{ _('Locks') }}</a></li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_server_prepared"
|
||||
aria-controls="tab_server_prepared" role="tab"
|
||||
data-toggle="tab">{{ _('Prepared Transactions') }}</a></li>
|
||||
<li role="presentation" class="dashboard-tab"><a href="#tab_panel_server_config"
|
||||
aria-controls="tab_server_config" role="tab"
|
||||
data-toggle="tab">{{ _('Configuration') }}</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="tab_panel_server_activity">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_activity_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_activity_filter"></div>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="tab_panel_server_activity">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_activity_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_activity_filter"></div>
|
||||
</div>
|
||||
<div id="server_activity" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="server_activity" class="grid-container"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_server_locks">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_locks_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_locks_filter"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_server_locks">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_locks_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_locks_filter"></div>
|
||||
</div>
|
||||
<div id="server_locks" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="server_locks" class="grid-container"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_server_prepared">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_prepared_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_prepared_filter"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_server_prepared">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_prepared_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_prepared_filter"></div>
|
||||
</div>
|
||||
<div id="server_prepared" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="server_prepared" class="grid-container"></div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_server_config">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_config_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_config_filter"></div>
|
||||
<div role="tabpanel" class="tab-pane" id="tab_panel_server_config">
|
||||
<div class="dashboard-tab-btn-group pg-prop-btn-group-above">
|
||||
<button id="btn_server_config_refresh" type="button" class="btn btn-default" title="{{ _('Refresh') }}"> <span class="fa fa-lg fa-refresh"></span></button>
|
||||
<div id="server_config_filter"></div>
|
||||
</div>
|
||||
<div id="server_config" class="grid-container"></div>
|
||||
</div>
|
||||
<div id="server_config" class="grid-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not settings.show_graphs and not settings.show_activity %}
|
||||
<div class="alert alert-info pg-panel-message" role="alert">
|
||||
{{ _('Dashboard has been disabled by user.') }}
|
||||
<div id="dashboard-none-show" class="alert alert-info pg-panel-message dashboard-hidden" role="alert">
|
||||
{{ _('All Dashboard elements are currently disabled.') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Initiate server dashboard
|
||||
pgAdmin.Dashboard.init_server_dashboard(
|
||||
{{ sid }},
|
||||
{{ version }},
|
||||
{{ rates.session_stats_refresh }},
|
||||
{{ rates.tps_stats_refresh }},
|
||||
{{ rates.ti_stats_refresh }},
|
||||
{{ rates.to_stats_refresh }},
|
||||
{{ rates.bio_stats_refresh }},
|
||||
{{ settings.show_graphs|lower }},
|
||||
{{ settings.show_activity|lower }}
|
||||
);
|
||||
</script>
|
||||
|
@ -1,263 +0,0 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import os
|
||||
import sys
|
||||
from flask import Flask, render_template
|
||||
from jinja2 import FileSystemLoader
|
||||
from pgadmin import VersionedTemplateLoader
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
|
||||
if sys.version_info < (3, 3):
|
||||
from mock import MagicMock
|
||||
else:
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# Hard coded dummy input parameters for the templates
|
||||
RATES = {
|
||||
'session_stats_refresh': 1,
|
||||
'tps_stats_refresh': 1,
|
||||
'ti_stats_refresh': 1,
|
||||
'to_stats_refresh': 1,
|
||||
'bio_stats_refresh': 1
|
||||
}
|
||||
|
||||
DISPLAY_DASHBOARD = {
|
||||
'both': {
|
||||
'show_graphs': True,
|
||||
'show_activity': True
|
||||
},
|
||||
|
||||
'only_graphs': {
|
||||
'show_graphs': True,
|
||||
'show_activity': False
|
||||
},
|
||||
|
||||
'only_server_activity': {
|
||||
'show_graphs': False,
|
||||
'show_activity': True
|
||||
},
|
||||
|
||||
'none': {
|
||||
'show_graphs': False,
|
||||
'show_activity': False
|
||||
}
|
||||
}
|
||||
|
||||
VERSION = 95000
|
||||
|
||||
SERVER_ID = 1
|
||||
|
||||
DATABASE_ID = 123
|
||||
|
||||
|
||||
# To moke gettext function used in the template
|
||||
_ = MagicMock(side_effect=lambda x: x)
|
||||
|
||||
|
||||
class TestDashboardTemplates(BaseTestGenerator):
|
||||
scenarios = [
|
||||
# Server dashboard
|
||||
(
|
||||
'Dashboard, when returning the html page with graphs and '
|
||||
'server activity related html elements for server dashboard',
|
||||
dict(
|
||||
template_path='dashboard/server_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=None,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['both'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[
|
||||
'Server sessions',
|
||||
'Server activity'
|
||||
],
|
||||
not_expected_return_value=[]
|
||||
)
|
||||
),
|
||||
(
|
||||
'Dashboard, when returning the html page with only graphs '
|
||||
'related html elements for server dashboard',
|
||||
dict(
|
||||
template_path='dashboard/server_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=None,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['only_graphs'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[
|
||||
'Server sessions'
|
||||
],
|
||||
not_expected_return_value=[
|
||||
'Server activity'
|
||||
]
|
||||
)
|
||||
),
|
||||
(
|
||||
'Dashboard, when returning the html page with only server '
|
||||
'activity related html elements for server dashboard',
|
||||
dict(
|
||||
template_path='dashboard/server_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=None,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['only_server_activity'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[
|
||||
'Server activity'
|
||||
],
|
||||
not_expected_return_value=[
|
||||
'Server sessions'
|
||||
]
|
||||
)
|
||||
),
|
||||
(
|
||||
'Dashboard, when returning the html page with neither '
|
||||
'graphs nor server activity related html elements for server '
|
||||
'dashboard',
|
||||
dict(
|
||||
template_path='dashboard/server_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=None,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['none'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[],
|
||||
not_expected_return_value=[
|
||||
'Server activity',
|
||||
'Server sessions'
|
||||
]
|
||||
)
|
||||
),
|
||||
# Database dashboard
|
||||
(
|
||||
'Dashboard, when returning the html page with graphs and '
|
||||
'database activity related html elements for database dashboard',
|
||||
dict(
|
||||
template_path='dashboard/database_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=DATABASE_ID,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['both'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[
|
||||
'Database sessions',
|
||||
'Database activity'
|
||||
],
|
||||
not_expected_return_value=[]
|
||||
)
|
||||
),
|
||||
(
|
||||
'Dashboard, when returning the html page with only '
|
||||
'graphs related html elements for database dashboard',
|
||||
dict(
|
||||
template_path='dashboard/database_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=DATABASE_ID,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['only_graphs'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[
|
||||
'Database sessions'
|
||||
],
|
||||
not_expected_return_value=[
|
||||
'Database activity'
|
||||
]
|
||||
)
|
||||
),
|
||||
(
|
||||
'Dashboard, when returning the html page with only '
|
||||
'database activity related html elements for database dashboard',
|
||||
dict(
|
||||
template_path='dashboard/database_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=DATABASE_ID,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['only_server_activity'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[
|
||||
'Database activity'
|
||||
],
|
||||
not_expected_return_value=[
|
||||
'Database sessions'
|
||||
]
|
||||
)
|
||||
),
|
||||
(
|
||||
'Dashboard, when returning the html page with neither '
|
||||
'graphs nor database activity related html elements for database '
|
||||
'dashboard',
|
||||
dict(
|
||||
template_path='dashboard/database_dashboard.html',
|
||||
input_parameters=dict(
|
||||
sid=SERVER_ID,
|
||||
did=DATABASE_ID,
|
||||
rates=RATES,
|
||||
version=VERSION,
|
||||
settings=DISPLAY_DASHBOARD['none'],
|
||||
_=_
|
||||
),
|
||||
expected_return_value=[],
|
||||
not_expected_return_value=[
|
||||
'Database sessions',
|
||||
'Database activity'
|
||||
]
|
||||
)
|
||||
),
|
||||
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
self.loader = VersionedTemplateLoader(FakeApp())
|
||||
|
||||
def runTest(self):
|
||||
with FakeApp().app_context():
|
||||
result = render_template(
|
||||
self.template_path, **self.input_parameters
|
||||
)
|
||||
# checks for expected html elements
|
||||
for expected_string in self.expected_return_value:
|
||||
self.assertIn(
|
||||
expected_string, result
|
||||
)
|
||||
|
||||
# checks for not expected html elements
|
||||
for not_expected_string in self.not_expected_return_value:
|
||||
self.assertNotIn(
|
||||
not_expected_string, result
|
||||
)
|
||||
|
||||
|
||||
class FakeApp(Flask):
|
||||
def __init__(self):
|
||||
super(FakeApp, self).__init__("")
|
||||
self.jinja_loader = FileSystemLoader(
|
||||
os.path.dirname(os.path.realpath(__file__)) + "/../templates"
|
||||
)
|
@ -117,13 +117,10 @@ function validateShortcutKeys(user_defined_shortcut, event) {
|
||||
}
|
||||
|
||||
/* Debugger: Keyboard Shortcuts handling */
|
||||
function keyboardShortcutsDebugger($el, event, user_defined_shortcuts) {
|
||||
function keyboardShortcutsDebugger($el, event, preferences) {
|
||||
let panel_id, panel_content, $input;
|
||||
let edit_grid_keys = user_defined_shortcuts.edit_grid_keys,
|
||||
next_panel_keys = user_defined_shortcuts.next_panel_keys,
|
||||
previous_panel_keys = user_defined_shortcuts.previous_panel_keys;
|
||||
|
||||
if(this.validateShortcutKeys(edit_grid_keys, event)) {
|
||||
if(this.validateShortcutKeys(preferences.edit_grid_values, event)) {
|
||||
this._stopEventPropagation(event);
|
||||
panel_content = $el.find(
|
||||
'div.wcPanelTabContent:not(".wcPanelTabContentHidden")'
|
||||
@ -133,10 +130,10 @@ function keyboardShortcutsDebugger($el, event, user_defined_shortcuts) {
|
||||
if($input.length)
|
||||
$input.trigger('click');
|
||||
}
|
||||
} else if(this.validateShortcutKeys(next_panel_keys, event)) {
|
||||
} else if(this.validateShortcutKeys(preferences.move_next, event)) {
|
||||
this._stopEventPropagation(event);
|
||||
panel_id = this.getInnerPanel($el, 'right');
|
||||
} else if(this.validateShortcutKeys(previous_panel_keys, event)) {
|
||||
} else if(this.validateShortcutKeys(preferences.move_previous, event)) {
|
||||
this._stopEventPropagation(event);
|
||||
panel_id = this.getInnerPanel($el, 'left');
|
||||
}
|
||||
|
@ -293,33 +293,6 @@ def update_session_function_transaction(trans_id, data):
|
||||
session['functionData'] = function_data
|
||||
|
||||
|
||||
def get_shortcuts_for_accesskey():
|
||||
"""
|
||||
This function will fetch and return accesskey shortcuts for debugger
|
||||
toolbar buttons
|
||||
|
||||
Returns:
|
||||
Dict of shortcut keys
|
||||
"""
|
||||
# Fetch debugger preferences
|
||||
dp = Preferences.module('debugger')
|
||||
btn_start = dp.preference('btn_start').get()
|
||||
btn_stop = dp.preference('btn_stop').get()
|
||||
btn_step_into = dp.preference('btn_step_into').get()
|
||||
btn_step_over = dp.preference('btn_step_over').get()
|
||||
btn_toggle_breakpoint = dp.preference('btn_toggle_breakpoint').get()
|
||||
btn_clear_breakpoints = dp.preference('btn_clear_breakpoints').get()
|
||||
|
||||
return {
|
||||
'start': btn_start.get('key').get('char'),
|
||||
'stop': btn_stop.get('key').get('char'),
|
||||
'step_into': btn_step_into.get('key').get('char'),
|
||||
'step_over': btn_step_over.get('key').get('char'),
|
||||
'toggle_breakpoint': btn_toggle_breakpoint.get('key').get('char'),
|
||||
'clear_breakpoints': btn_clear_breakpoints.get('key').get('char')
|
||||
}
|
||||
|
||||
|
||||
@blueprint.route(
|
||||
'/init/<node_type>/<int:sid>/<int:did>/<int:scid>/<int:fid>',
|
||||
methods=['GET'], endpoint='init_for_function'
|
||||
@ -589,7 +562,6 @@ def direct_new(trans_id):
|
||||
is_linux=is_linux_platform,
|
||||
client_platform=user_agent.platform,
|
||||
stylesheets=[url_for('debugger.static', filename='css/debugger.css')],
|
||||
accesskey=get_shortcuts_for_accesskey()
|
||||
)
|
||||
|
||||
|
||||
@ -811,12 +783,8 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
|
||||
# is initialized
|
||||
del session['funcData']
|
||||
|
||||
pref = Preferences.module('debugger')
|
||||
new_browser_tab = pref.preference('debugger_new_browser_tab').get()
|
||||
|
||||
return make_json_response(data={'status': status,
|
||||
'debuggerTransId': trans_id,
|
||||
'newBrowserTab': new_browser_tab})
|
||||
'debuggerTransId': trans_id})
|
||||
|
||||
|
||||
@blueprint.route(
|
||||
|
@ -184,6 +184,18 @@ define([
|
||||
});
|
||||
|
||||
this.frame.load(pgBrowser.docker);
|
||||
|
||||
let self = this;
|
||||
let cacheIntervalId = setInterval(function() {
|
||||
try {
|
||||
self.preferences = window.top.pgAdmin.Browser;
|
||||
clearInterval(cacheIntervalId);
|
||||
}
|
||||
catch(err) {
|
||||
clearInterval(cacheIntervalId);
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
},
|
||||
// It will check weather the function is actually debuggable or not with pre-required condition.
|
||||
can_debug: function(itemData, item, data) {
|
||||
@ -313,7 +325,8 @@ define([
|
||||
var t = pgBrowser.tree,
|
||||
i = item || t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
||||
node = d && pgBrowser.Nodes[d._type];
|
||||
node = d && pgBrowser.Nodes[d._type],
|
||||
self = this;
|
||||
|
||||
if (!d)
|
||||
return;
|
||||
@ -384,7 +397,7 @@ define([
|
||||
'trans_id': res.data.debuggerTransId,
|
||||
});
|
||||
|
||||
if (res.data.newBrowserTab) {
|
||||
if (self.preferences.debugger_new_browser_tab) {
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
pgBrowser.Events.once(
|
||||
@ -435,7 +448,8 @@ define([
|
||||
var t = pgBrowser.tree,
|
||||
i = item || t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
||||
node = d && pgBrowser.Nodes[d._type];
|
||||
node = d && pgBrowser.Nodes[d._type],
|
||||
self = this;
|
||||
|
||||
if (!d)
|
||||
return;
|
||||
@ -499,7 +513,7 @@ define([
|
||||
'trans_id': res.data.debuggerTransId,
|
||||
});
|
||||
|
||||
if (res.data.newBrowserTab) {
|
||||
if (self.preferences.debugger_new_browser_tab) {
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
pgBrowser.Events.once(
|
||||
|
@ -1393,7 +1393,7 @@ define([
|
||||
controller about the click and controller will take the action for the specified button click.
|
||||
*/
|
||||
var DebuggerToolbarView = Backbone.View.extend({
|
||||
el: '.dubugger_main_container',
|
||||
el: '.debugger_main_container',
|
||||
initialize: function() {
|
||||
controller.on('pgDebugger:button:state:stop', this.enable_stop, this);
|
||||
controller.on('pgDebugger:button:state:step_over', this.enable_step_over, this);
|
||||
@ -1496,44 +1496,11 @@ define([
|
||||
controller.Step_into(pgTools.DirectDebug.trans_id);
|
||||
},
|
||||
keyAction: function (event) {
|
||||
var $el = this.$el, panel_id, actual_panel;
|
||||
|
||||
// If already fetched earlier then don't do it again
|
||||
if(_.size(pgTools.DirectDebug.debugger_keyboard_shortcuts) == 0) {
|
||||
// Fetch keyboard shortcut keys
|
||||
var edit_grid_shortcut_perf, next_panel_perf, previous_panel_perf;
|
||||
edit_grid_shortcut_perf = window.top.pgAdmin.Browser.get_preference(
|
||||
'debugger', 'edit_grid_values'
|
||||
);
|
||||
next_panel_perf = window.top.pgAdmin.Browser.get_preference(
|
||||
'debugger', 'move_next'
|
||||
);
|
||||
previous_panel_perf = window.top.pgAdmin.Browser.get_preference(
|
||||
'debugger', 'move_previous'
|
||||
);
|
||||
|
||||
// If debugger opened in new Tab then window.top won't be available
|
||||
if(!edit_grid_shortcut_perf || !next_panel_perf || !previous_panel_perf) {
|
||||
edit_grid_shortcut_perf = window.opener.pgAdmin.Browser.get_preference(
|
||||
'debugger', 'edit_grid_values'
|
||||
);
|
||||
next_panel_perf = window.opener.pgAdmin.Browser.get_preference(
|
||||
'debugger', 'move_next'
|
||||
);
|
||||
previous_panel_perf = window.opener.pgAdmin.Browser.get_preference(
|
||||
'debugger', 'move_previous'
|
||||
);
|
||||
}
|
||||
|
||||
pgTools.DirectDebug.debugger_keyboard_shortcuts = {
|
||||
'edit_grid_keys': edit_grid_shortcut_perf.value,
|
||||
'next_panel_keys': next_panel_perf.value,
|
||||
'previous_panel_keys': previous_panel_perf.value,
|
||||
};
|
||||
}
|
||||
var $el = this.$el, panel_id, actual_panel,
|
||||
self = this;
|
||||
|
||||
panel_id = keyboardShortcuts.processEventDebugger(
|
||||
$el, event, pgTools.DirectDebug.debugger_keyboard_shortcuts
|
||||
$el, event, self.preferences
|
||||
);
|
||||
|
||||
// Panel navigation
|
||||
@ -1572,7 +1539,10 @@ define([
|
||||
this.debug_restarted = false;
|
||||
this.is_user_aborted_debugging = false;
|
||||
this.is_polling_required = true; // Flag to stop unwanted ajax calls
|
||||
this.debugger_keyboard_shortcuts = {};
|
||||
|
||||
let browser = window.opener ?
|
||||
window.opener.pgAdmin.Browser : window.top.pgAdmin.Browser;
|
||||
this.preferences = browser.get_preferences_for_module('sqleditor');
|
||||
|
||||
this.docker = new wcDocker(
|
||||
'#container', {
|
||||
@ -1856,6 +1826,35 @@ define([
|
||||
if(self.docker.$container){
|
||||
self.docker.$container.parent().focus();
|
||||
}
|
||||
|
||||
let cacheIntervalId = setInterval(function() {
|
||||
try {
|
||||
let browser = window.opener ? window.opener.pgAdmin.Browser : window.top.pgAdmin.Browser;
|
||||
if(browser.preference_version() > 0) {
|
||||
clearInterval(cacheIntervalId);
|
||||
self.reflectPreferences();
|
||||
|
||||
/* If debugger is in a new tab, event fired is not available
|
||||
* instead, a poller is set up who will check
|
||||
*/
|
||||
if(self.preferences.debugger_new_browser_tab) {
|
||||
let pollIntervalId = setInterval(()=>{
|
||||
if(window.opener && window.opener.pgAdmin) {
|
||||
self.reflectPreferences();
|
||||
}
|
||||
else {
|
||||
clearInterval(pollIntervalId);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
clearInterval(cacheIntervalId);
|
||||
throw err;
|
||||
}
|
||||
},0);
|
||||
|
||||
};
|
||||
|
||||
self.docker.startLoading(gettext('Loading...'));
|
||||
@ -1863,8 +1862,50 @@ define([
|
||||
|
||||
// Create the toolbar view for debugging the function
|
||||
this.toolbarView = new DebuggerToolbarView();
|
||||
},
|
||||
|
||||
/* Cache may take time to load for the first time
|
||||
* Keep trying till available
|
||||
*/
|
||||
|
||||
|
||||
/* Register for preference changed event broadcasted in parent
|
||||
* to reload the shorcuts.
|
||||
*/
|
||||
pgBrowser.onPreferencesChange('debugger', function() {
|
||||
self.reflectPreferences();
|
||||
});
|
||||
},
|
||||
reflectPreferences: function() {
|
||||
let self = this,
|
||||
browser = window.opener ? window.opener.pgAdmin.Browser : window.top.pgAdmin.Browser;
|
||||
self.preferences = browser.get_preferences_for_module('debugger');
|
||||
self.toolbarView.preferences = self.preferences;
|
||||
|
||||
/* Update the shortcuts of the buttons */
|
||||
self.toolbarView.$el.find('#btn-step-into')
|
||||
.attr('title', keyboardShortcuts.shortcut_accesskey_title('Step into',self.preferences.btn_step_into))
|
||||
.attr('accesskey', keyboardShortcuts.shortcut_key(self.preferences.btn_step_into));
|
||||
|
||||
self.toolbarView.$el.find('#btn-step-over')
|
||||
.attr('title', keyboardShortcuts.shortcut_accesskey_title('Step over',self.preferences.btn_step_over))
|
||||
.attr('accesskey', keyboardShortcuts.shortcut_key(self.preferences.btn_step_over));
|
||||
|
||||
self.toolbarView.$el.find('#btn-continue')
|
||||
.attr('title', keyboardShortcuts.shortcut_accesskey_title('Continue/Start',self.preferences.btn_start))
|
||||
.attr('accesskey', keyboardShortcuts.shortcut_key(self.preferences.btn_start));
|
||||
|
||||
self.toolbarView.$el.find('#btn-toggle-breakpoint')
|
||||
.attr('title', keyboardShortcuts.shortcut_accesskey_title('Toggle breakpoint',self.preferences.btn_toggle_breakpoint))
|
||||
.attr('accesskey', keyboardShortcuts.shortcut_key(self.preferences.btn_toggle_breakpoint));
|
||||
|
||||
self.toolbarView.$el.find('#btn-clear-breakpoint')
|
||||
.attr('title', keyboardShortcuts.shortcut_accesskey_title('Clear all breakpoints',self.preferences.btn_clear_breakpoints))
|
||||
.attr('accesskey', keyboardShortcuts.shortcut_key(self.preferences.btn_clear_breakpoints));
|
||||
|
||||
self.toolbarView.$el.find('#btn-stop')
|
||||
.attr('title', keyboardShortcuts.shortcut_accesskey_title('Stop',self.preferences.btn_stop))
|
||||
.attr('accesskey', keyboardShortcuts.shortcut_key(self.preferences.btn_stop));
|
||||
},
|
||||
// Register the panel with new debugger docker instance.
|
||||
registerPanel: function(name, title, width, height, onInit) {
|
||||
var self = this;
|
||||
|
@ -35,47 +35,47 @@ try {
|
||||
.debugger-container .wcLoadingIcon.fa-pulse{-webkit-animation: none;}
|
||||
</style>
|
||||
{% endif %}
|
||||
<div class="dubugger_main_container" tabindex="0">
|
||||
<div class="debugger_main_container" tabindex="0">
|
||||
<nav class="navbar-inverse navbar-fixed-top">
|
||||
<div id="btn-toolbar" class="btn-toolbar pg-prop-btn-group bg-gray-2 border-gray-3" role="toolbar" aria-label="">
|
||||
<div class="btn-group" role="group" aria-label="">
|
||||
<button type="button" class="btn btn-default btn-step-into"
|
||||
title="{{ _('Step into') }}{{ _(' (accesskey+{0})'.format(accesskey.step_into)) }}"
|
||||
accesskey="{{ accesskey.step_into }}"
|
||||
<button type="button" class="btn btn-default btn-step-into" id="btn-step-into"
|
||||
title=""
|
||||
accesskey=""
|
||||
tabindex="0" autofocus="autofocus">
|
||||
<i class="fa fa-indent"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-step-over"
|
||||
title="{{ _('Step over') }}{{ _(' (accesskey+{0})'.format(accesskey.step_over)) }}"
|
||||
accesskey="{{ accesskey.step_over }}"
|
||||
<button type="button" class="btn btn-default btn-step-over" id="btn-step-over"
|
||||
title=""
|
||||
accesskey=""
|
||||
tabindex="0">
|
||||
<i class="fa fa-outdent"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-continue"
|
||||
title="{{ _('Continue/Start') }}{{ _(' (accesskey+{0})'.format(accesskey.start)) }}"
|
||||
accesskey="{{ accesskey.start }}"
|
||||
<button type="button" class="btn btn-default btn-continue" id="btn-continue"
|
||||
title=""
|
||||
accesskey=""
|
||||
tabindex="0">
|
||||
<i class="fa fa-play-circle"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group" role="group" aria-label="">
|
||||
<button type="button" class="btn btn-default btn-toggle-breakpoint"
|
||||
title="{{ _('Toggle breakpoint') }}{{ _(' (accesskey+{0})'.format(accesskey.toggle_breakpoint)) }}"
|
||||
accesskey="{{ accesskey.toggle_breakpoint }}"
|
||||
<button type="button" class="btn btn-default btn-toggle-breakpoint" id="btn-toggle-breakpoint"
|
||||
title=""
|
||||
accesskey=""
|
||||
tabindex="0">
|
||||
<i class="fa fa-circle"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-clear-breakpoint"
|
||||
title="{{ _('Clear all breakpoints') }}{{ _(' (accesskey+{0})'.format(accesskey.clear_breakpoints)) }}"
|
||||
accesskey="{{ accesskey.clear_breakpoints }}"
|
||||
<button type="button" class="btn btn-default btn-clear-breakpoint" id="btn-clear-breakpoint"
|
||||
title=""
|
||||
accesskey=""
|
||||
tabindex="0">
|
||||
<i class="fa fa-ban"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="btn-group" role="group" aria-label="">
|
||||
<button type="button" class="btn btn-default btn-stop"
|
||||
accesskey="{{ accesskey.stop }}"
|
||||
title="{{ _('Stop') }}{{ _(' (accesskey+{0})'.format(accesskey.stop)) }}"
|
||||
<button type="button" class="btn btn-default btn-stop" id="btn-stop"
|
||||
accesskey=""
|
||||
title=""
|
||||
tabindex="0">
|
||||
<i class="fa fa-stop-circle"></i>
|
||||
</button>
|
||||
|
Loading…
Reference in New Issue
Block a user