Introduced a event manager for the browser, which will generate certain

known events, when any activity happens on the browser layout.

The following types of events will be triggered through the browser
event manager.
- pgadmin-browser:frame:* [1]
- pgadmin-browser:frame-<name>:* [1]
- pgadmin-browser:panel:* [1]
- pgadmin-browser:panel-<name>:* [1]
- pgadmin-browser:panel
- pgadmin-browser:frame
- pgadmin-browser:tree
- pgadmin-browser:tree:* [2]

[1] The '*' denotes some of the events generated by the wcDocker, which
    can be useful to do some operations.
	These events are:
	+ wcDocker.EVENT.UPDATED
	+ wcDocker.EVENT.VISIBILITY_CHANGED
	+ wcDocker.EVENT.BEGIN_DOCK
    + wcDocker.EVENT.END_DOCK
	+ wcDocker.EVENT.GAIN_FOCUS,
	+ wcDocker.EVENT.LOST_FOCUS
	+ wcDocker.EVENT.CLOSED
	+ wcDocker.EVENT.BUTTON
	+ wcDocker.EVENT.ATTACHED
	+ wcDocker.EVENT.DETACHED
	+ wcDocker.EVENT.MOVE_STARTED
	+ wcDocker.EVENT.MOVE_ENDED
	+ wcDocker.EVENT.MOVED
	+ wcDocker.EVENT.RESIZE_STARTED
	+ wcDocker.EVENT.RESIZE_ENDED
	+ wcDocker.EVENT.RESIZED
	+ wcDocker.EVENT.SCROLLED

[2] The '*' denotes all the events generated by the Browser Tree
    (aciTree).

The extension modules can utilize these events to do some operations on
nodes, and panels.

This patch includes showing 'Reversed Engineered Query' for the selected
node (if allowed) using the above approch.

The ShowNodeSQL module looks for two events.
1. SQL Panel Visibility change.
   - Based on the visibility of that panel, we start/stop listening the
	 node selection event.
2. Node Selection in Browser tree
   - Based on the selected node type, it will look for 'hasSQL'
	 parameter of the node, and fetch the Query from the server, and
	 show it in the SQL editor.
This commit is contained in:
Ashesh Vashi 2016-01-19 18:01:14 +05:30
parent 0cea682e88
commit 8120b380bb
7 changed files with 222 additions and 53 deletions

View File

@ -884,7 +884,9 @@ function(_, pgAdmin, $, Backbone) {
return true;
}
})
});
pgBrowser.Events = _.extend({}, Backbone.Events);
return pgBrowser;
});

View File

@ -2,7 +2,8 @@ define(
['underscore', 'pgadmin', 'wcdocker'],
function(_, pgAdmin) {
pgAdmin.Browser = pgAdmin.Browser || {};
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
pgAdmin.Browser.Frame = function(options) {
var defaults = [
'name', 'title', 'width', 'height', 'showTitle', 'isCloseable',
@ -25,23 +26,61 @@ function(_, pgAdmin) {
var that = this;
if (!that.panel) {
docker.registerPanelType(this.name, {
title: that.title,
isPrivate: that.isPrivate,
onCreate: function(myPanel) {
myPanel.initSize(that.width, that.height);
if (myPanel.showTitle == false)
myPanle.title(false);
myPanel.closeable(!!that.isCloseable);
title: that.title,
isPrivate: that.isPrivate,
onCreate: function(myPanel) {
$(myPanel).data('pgAdminName', that.name);
myPanel.initSize(that.width, that.height);
if (myPanel.showTitle == false)
myPanle.title(false);
myPanel.closeable(!!that.isCloseable);
var $frameArea = $('<div style="width:100%;height:100%;position:relative;display:table">');
myPanel.layout().addItem($frameArea);
that.panel = myPanel;
that.frame = new wcIFrame($frameArea, myPanel);
var $frameArea = $('<div style="width:100%;height:100%;position:relative;display:table">');
myPanel.layout().addItem($frameArea);
that.panel = myPanel;
var frame = new wcIFrame($frameArea, myPanel);
$(myPanel).data('embededFrame', that.frame);
setTimeout(function() { that.frame.openURL(that.url); }, 500);
setTimeout(function() { frame.openURL(that.url); }, 500);
if (that.events && _.isObject(that.events)) {
_.each(that.events, function(v, k) {
if (v && _.isFunction(v)) {
myPanel.on(k, v);
}
});
}
_.each([
wcDocker.EVENT.UPDATED, wcDocker.EVENT.VISIBILITY_CHANGED,
wcDocker.EVENT.BEGIN_DOCK, wcDocker.EVENT.END_DOCK,
wcDocker.EVENT.GAIN_FOCUS, wcDocker.EVENT.LOST_FOCUS,
wcDocker.EVENT.CLOSED, wcDocker.EVENT.BUTTON,
wcDocker.EVENT.ATTACHED, wcDocker.EVENT.DETACHED,
wcDocker.EVENT.MOVE_STARTED, wcDocker.EVENT.MOVE_ENDED,
wcDocker.EVENT.MOVED, wcDocker.EVENT.RESIZE_STARTED,
wcDocker.EVENT.RESIZE_ENDED, wcDocker.EVENT.RESIZED,
wcDocker.EVENT.SCROLLED], function(ev) {
myPanel.on(ev, that.eventFunc.bind(myPanel, ev));
});
}
});
}
},
eventFunc: function(eventName) {
var name = $(this).data('pgAdminName');
try {
pgBrowser.Events.trigger('pgadmin-browser:frame', eventName, this, arguments);
pgBrowser.Events.trigger('pgadmin-browser:frame:' + eventName, this, arguments);
if (name) {
pgBrowser.Events.trigger('pgadmin-browser:frame-' + name, eventName, this, arguments);
pgBrowser.Events.trigger('pgadmin-browser:frame-' + name + ':' + eventName, this, arguments);
}
} catch (e) {
console.log(e);
}
}
});

View File

@ -1,7 +1,9 @@
define(
['underscore', 'pgadmin', 'wcdocker'],
function(_, pgAdmin) {
pgAdmin.Browser = pgAdmin.Browser || {};
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
pgAdmin.Browser.Panel = function(options) {
var defaults = [
'name', 'title', 'width', 'height', 'showTitle', 'isCloseable',
@ -26,6 +28,7 @@ function(_, pgAdmin) {
title: that.title,
isPrivate: that.isPrivate,
onCreate: function(myPanel) {
$(myPanel).data('pgAdminName', that.name);
myPanel.initSize(that.width, that.height);
if (!that.showTitle)
myPanel.title(false);
@ -46,9 +49,36 @@ function(_, pgAdmin) {
}
});
}
_.each([
wcDocker.EVENT.UPDATED, wcDocker.EVENT.VISIBILITY_CHANGED,
wcDocker.EVENT.BEGIN_DOCK, wcDocker.EVENT.END_DOCK,
wcDocker.EVENT.GAIN_FOCUS, wcDocker.EVENT.LOST_FOCUS,
wcDocker.EVENT.CLOSED, wcDocker.EVENT.BUTTON,
wcDocker.EVENT.ATTACHED, wcDocker.EVENT.DETACHED,
wcDocker.EVENT.MOVE_STARTED, wcDocker.EVENT.MOVE_ENDED,
wcDocker.EVENT.MOVED, wcDocker.EVENT.RESIZE_STARTED,
wcDocker.EVENT.RESIZE_ENDED, wcDocker.EVENT.RESIZED,
wcDocker.EVENT.SCROLLED], function(ev) {
myPanel.on(ev, that.eventFunc.bind(myPanel, ev));
});
}
});
}
},
eventFunc: function(eventName) {
var name = $(this).data('pgAdminName');
try {
pgBrowser.Events.trigger('pgadmin-browser:panel', eventName, this, arguments);
pgBrowser.Events.trigger('pgadmin-browser:panel:' + eventName, this, arguments);
if (name) {
pgBrowser.Events.trigger('pgadmin-browser:panel-' + name, eventName, this, arguments);
pgBrowser.Events.trigger('pgadmin-browser:panel-' + name + ':' + eventName, this, arguments);
}
} catch (e) {
console.log(e);
}
}
});

View File

@ -16,34 +16,8 @@ function(require, $, _, S, Bootstrap, pgAdmin, alertify, CodeMirror) {
pgAdmin.Browser = pgAdmin.Browser || {};
// TODO:: Remove dmeo SQL (once completed)
var demoSql = '-- DROP TABLE tickets_detail; \n\
\n\
CREATE TABLE tickets_detail \n\
( \n\
id serial NOT NULL, \n\
ticket_id integer NOT NULL, \n\
logger_id integer NOT NULL, \n\
added timestamp with time zone NOT NULL, \n\
detail text NOT NULL, \n\
msgid character varying(100), \n\
CONSTRAINT tickets_detail_pkey PRIMARY KEY (id), \n\
CONSTRAINT ticket_id_refs_id_6b8dc130 FOREIGN KEY (ticket_id) \n\
REFERENCES tickets_ticket (id) MATCH SIMPLE \n\
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED, \n\
CONSTRAINT tickets_detail_logger_id_fkey FOREIGN KEY (logger_id) \n\
REFERENCES auth_user (id) MATCH SIMPLE \n\
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED \n\
) \n\
WITH ( \n\
OIDS=FALSE \n\
); \n\
ALTER TABLE tickets_detail \n\
OWNER TO helpdesk;\n';
var panelEvents = {};
panelEvents[wcDocker.EVENT.VISIBILITY_CHANGED] = function() {
if (this.isVisible()) {
var obj = pgAdmin.Browser,
i = obj.tree ? obj.tree.selected() : undefined,
@ -57,13 +31,6 @@ OWNER TO helpdesk;\n';
}
};
var sqlPanelEvents = {};
sqlPanelEvents[wcDocker.EVENT.VISIBILITY_CHANGED] = function() {
/* Update the SQL editor to show the latest value all the time */
if (this.isVisible()) {
pgAdmin.Browser.editor.setValue($('#sql-textarea').val());
}
};
// Extend the browser class attributes
_.extend(pgAdmin.Browser, {
// The base url for browser
@ -118,8 +85,7 @@ OWNER TO helpdesk;\n';
width: 500,
isCloseable: false,
isPrivate: true,
content: '<textarea id="sql-textarea" name="sql-textarea"></textarea>',
events: sqlPanelEvents
content: '<textarea id="sql-textarea" name="sql-textarea"></textarea>'
}),
// Dependencies of the object
'dependencies': new pgAdmin.Browser.Panel({
@ -282,6 +248,11 @@ OWNER TO helpdesk;\n';
init: function() {
var obj=this;
if (obj.initialized) {
return;
}
obj.initialized = true;
// Store the main browser layout
$(window).bind('unload', function() {
if(obj.docker) {
@ -340,8 +311,6 @@ OWNER TO helpdesk;\n';
mode: "text/x-sql",
readOnly: true
});
// TODO:: Revove demoSql later
$('#sql-textarea').val(demoSql);
// Initialise the treeview
$('#tree').aciTree({
@ -485,8 +454,10 @@ OWNER TO helpdesk;\n';
break;
}
var node;
if (d && obj.Nodes[d._type]) {
var node = obj.Nodes[d._type];
node = obj.Nodes[d._type];
/* If the node specific callback returns false, we will also return
* false for further processing.
@ -507,6 +478,17 @@ OWNER TO helpdesk;\n';
console.log(e);
}
}
try {
obj.Events.trigger(
'pgadmin-browser:tree', eventName, item, d
);
obj.Events.trigger(
'pgadmin-browser:tree:' + eventName, item, d, node
);
} catch (e) {
console.log(e);
}
return true;
});

View File

@ -542,6 +542,8 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
// tab is active.)
}
}
return true;
},
refresh: function(i) {
var self = this,

View File

@ -0,0 +1,29 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""A blueprint module providing utility functions for the application."""
import datetime
from flask import session, current_app, url_for
from pgadmin.utils import PgAdminModule
import pgadmin.utils.driver as driver
MODULE_NAME = 'sql'
class SQLModule(PgAdminModule):
def get_own_javascripts(self):
return [{
'name': 'pgadmin.browser.object_sql',
'path': url_for('sql.static', filename='js/sql'),
'when': None
}]
# Initialise the module
blueprint = SQLModule(MODULE_NAME, __name__, url_prefix='/misc/sql')

View File

@ -0,0 +1,85 @@
define(
['underscore', 'jquery', 'pgadmin.browser'],
function(_, $, pgBrowser) {
pgBrowser.ShowNodeSQL = pgBrowser.ShowNodeSQL || {};
if (pgBrowser.ShowNodeSQL.initialized) {
return pgBrowser.ShowNodeSQL;
}
_.extend(pgBrowser.ShowNodeSQL, {
init: function() {
if (this.initialized) {
return;
}
this.initialized = true;
_.bindAll(this, 'showSQL', 'sqlPanelVisibilityChanged');
var sqlPanels = pgBrowser.docker.findPanels('sql');
// We will listend to the visibility change of the SQL panel
pgBrowser.Events.on('pgadmin-browser:panel-sql:' + wcDocker.EVENT.VISIBILITY_CHANGED, this.sqlPanelVisibilityChanged);
// Hmm.. Did we find the SQL panel, and is it visible (openned)?
// If that is the case - we need to listen the browser tree selection
// events.
if ((sqlPanels.length == 1 && sqlPanels[0].isVisible()) || sqlPanels.length != 1) {
pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showSQL);
}
},
showSQL: function(item, data, node) {
/**
* We can't start fetching the SQL immediately, it is possible - the user
* is just using keyboards to select the node, and just traversing
* through. We will wait for some time before fetching the Reversed
* Engineering SQL.
**/
if (this.timeout) {
clearTimeout(this.timeout);
}
this.timeout = setTimeout(
function() {
var sql = '-- No object selected!';
if (node) {
sql = '-- No SQL generated for the selected object.';
if (node.hasSQL) {
sql = '-- Please wait while we fetch the SQL from the server.';
var url = node.generate_url(item, 'sql', data, true);
$.ajax({
url: url,
type:'GET',
success: function(res) {
pgAdmin.Browser.editor.setValue(res);
},
error: function() {
// TODO:: Report this
}
});
}
}
pgAdmin.Browser.editor.setValue(sql);
}, 400);
},
sqlPanelVisibilityChanged: 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.ShowNodeSQL.showSQL.apply(pgBrowser.ShowNodeSQL, [i, d, n]);
// We will start listening the tree selection event.
pgBrowser.Events.on('pgadmin-browser:tree:selected', pgBrowser.ShowNodeSQL.showSQL);
} else {
// We don't need to listen the tree item selection event.
pgBrowser.Events.off('pgadmin-browser:tree:selected', pgBrowser.ShowNodeSQL.showSQL);
}
}
});
return pgBrowser.ShowNodeSQL;
});