Add context-sensitive SQL help.

pull/3/head
Dave Page 2016-04-12 13:35:47 +01:00
parent 9b9126da15
commit 62fcfd928d
25 changed files with 166 additions and 5 deletions

View File

@ -11,6 +11,7 @@ from abc import ABCMeta, abstractmethod, abstractproperty
from pgadmin import current_blueprint
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response
from pgadmin.utils.preferences import Preferences
from pgadmin.settings import get_setting
from flask import current_app, render_template, url_for, make_response, flash
from flask.ext.security import login_required
@ -499,9 +500,22 @@ def error_js():
@blueprint.route("/js/node.js")
@login_required
def node_js():
prefs = Preferences.module('paths')
pg_help_path_pref = prefs.preference('pg_help_path')
pg_help_path = pg_help_path_pref.get()
edbas_help_path_pref = prefs.preference('edbas_help_path')
edbas_help_path = edbas_help_path_pref.get()
return make_response(
render_template('browser/js/node.js', _=gettext),
render_template('browser/js/node.js',
pg_help_path=pg_help_path,
edbas_help_path=edbas_help_path,
_=gettext
),
200, {'Content-Type': 'application/x-javascript'})
@blueprint.route("/js/messages.js")

View File

@ -18,6 +18,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['cast'] = pgAdmin.Browser.Node.extend({
parent_type: 'database',
type: 'cast',
sqlAlterHelp: 'sql-altercast.html',
sqlCreateHelp: 'sql-createcast.html',
canDrop: true,
canDropCascade: true,
label: '{{ _('Cast') }}',

View File

@ -47,6 +47,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['event_trigger'] = pgAdmin.Browser.Node.extend({
parent_type: 'database',
type: 'event_trigger',
sqlAlterHelp: 'sql-altereventtrigger.html',
sqlCreateHelp: 'sql-createeventtrigger.html',
label: '{{ _('Event Trigger') }}',
hasSQL: true,
hasDepends: true,

View File

@ -38,6 +38,8 @@ function($, _, S, pgAdmin, pgBrowser) {
pgAdmin.Browser.Node.extend({
parent_type: 'database',
type: 'extension',
sqlAlterHelp: 'sql-alterextension.html',
sqlCreateHelp: 'sql-createextension.html',
hasSQL: true,
hasDepends: true,
canDrop: true,

View File

@ -51,6 +51,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['foreign_server'] = pgAdmin.Browser.Node.extend({
parent_type: 'foreign_data_wrapper',
type: 'foreign_server',
sqlAlterHelp: 'sql-alterforeignserver.html',
sqlCreateHelp: 'sql-createforeignserver.html',
label: '{{ _('Foreign Server') }}',
hasSQL: true,
hasDepends: true,

View File

@ -50,6 +50,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['user_mapping'] = pgAdmin.Browser.Node.extend({
parent_type: 'foreign_server',
type: 'user_mapping',
sqlAlterHelp: 'sql-alterusermapping.html',
sqlCreateHelp: 'sql-createusermapping.html',
label: '{{ _('User Mapping') }}',
hasSQL: true,
hasDepends: true,

View File

@ -52,6 +52,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['foreign_data_wrapper'] = pgAdmin.Browser.Node.extend({
parent_type: 'database',
type: 'foreign_data_wrapper',
sqlAlterHelp: 'sql-alterforeigndatawrapper.html',
sqlCreateHelp: 'sql-createforeigndatawrapper.html',
label: '{{ _('Foreign Data Wrapper') }}',
hasSQL: true,
hasDepends: true,

View File

@ -55,6 +55,8 @@ define(
pgAdmin.Browser.Nodes['language'] = pgAdmin.Browser.Node.extend({
parent_type: 'database',
type: 'language',
sqlAlterHelp: 'sql-alterlanguage.html',
sqlCreateHelp: 'sql-createlanguage.html',
label: '{{ _('language') }}',
hasSQL: true,
hasDepends: true,

View File

@ -15,6 +15,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['collation']) {
pgAdmin.Browser.Nodes['collation'] = pgBrowser.Node.extend({
type: 'collation',
sqlAlterHelp: 'sql-altercollation.html',
sqlCreateHelp: 'sql-createcollation.html',
label: '{{ _('Collation') }}',
collection_type: 'coll-collation',
hasSQL: true,

View File

@ -18,6 +18,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['domain-constraints']) {
pgAdmin.Browser.Nodes['domain-constraints'] = pgBrowser.Node.extend({
type: 'domain-constraints',
sqlAlterHelp: 'sql-alterdomain.html',
sqlCreateHelp: 'sql-alterdomain.html',
label: '{{ _('Domain Constraints') }}',
collection_type: 'coll-domain-constraints',
hasSQL: true,

View File

@ -109,6 +109,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['domain']) {
pgAdmin.Browser.Nodes['domain'] = pgBrowser.Node.extend({
type: 'domain',
sqlAlterHelp: 'sql-alterdomain.html',
sqlCreateHelp: 'sql-createdomain.html',
label: '{{ _('Domain') }}',
collection_type: 'coll-domain',
hasSQL: true,

View File

@ -19,6 +19,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['fts_parser'] = pgAdmin.Browser.Node.extend({
parent_type: ['schema', 'catalog'],
type: 'fts_parser',
sqlAlterHelp: 'sql-altertsparser.html',
sqlCreateHelp: 'sql-createtsparser.html',
canDrop: true,
canDropCascade: true,
label: '{{ _('FTS Parser') }}',

View File

@ -18,6 +18,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['fts_template'] = pgAdmin.Browser.Node.extend({
parent_type: ['schema', 'catalog'],
type: 'fts_template',
sqlAlterHelp: 'sql-altertstemplate.html',
sqlCreateHelp: 'sql-createtstemplate.html',
canDrop: true,
canDropCascade: true,
label: '{{ _('FTS Template') }}',

View File

@ -102,6 +102,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['function']) {
pgAdmin.Browser.Nodes['function'] = pgBrowser.Node.extend({
type: 'function',
sqlAlterHelp: 'sql-alterfunction.html',
sqlCreateHelp: 'sql-createfunction.html',
label: '{{ _('Function') }}',
collection_type: 'coll-function',
hasSQL: true,

View File

@ -22,6 +22,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Function) {
if (!pgBrowser.Nodes['procedure']) {
pgAdmin.Browser.Nodes['procedure'] = Function.extend({
type: 'procedure',
sqlAlterHelp: 'sql-alterprocedure.html',
sqlCreateHelp: 'sql-createprocedure.html',
label: '{{ _('Procedure') }}',
collection_type: 'coll-procedure',
hasSQL: true,

View File

@ -51,6 +51,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['sequence']) {
pgAdmin.Browser.Nodes['sequence'] = pgBrowser.Node.extend({
type: 'sequence',
sqlAlterHelp: 'sql-altersequence.html',
sqlCreateHelp: 'sql-createsequence.html',
label: '{{ _('Sequence') }}',
collection_type: 'coll-sequence',
hasSQL: true,

View File

@ -51,6 +51,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
pgAdmin.Browser.Nodes['schema'] = pgAdmin.Browser.Node.extend({
parent_type: 'database',
type: 'schema',
sqlAlterHelp: 'sql-alterschema.html',
sqlCreateHelp: 'sql-createschema.html',
label: '{{ _('Schema') }}',
hasSQL: true,
canDrop: true,

View File

@ -206,6 +206,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
if (!pgBrowser.Nodes['type']) {
pgAdmin.Browser.Nodes['type'] = pgBrowser.Node.extend({
type: 'type',
sqlAlterHelp: 'sql-altertype.html',
sqlCreateHelp: 'sql-createtype.html',
label: '{{ _('Type') }}',
collection_type: 'coll-type',
hasSQL: true,

View File

@ -47,6 +47,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
pgAdmin.Browser.Nodes['database'] = pgAdmin.Browser.Node.extend({
parent_type: 'server',
type: 'database',
sqlAlterHelp: 'sql-alterdatabase.html',
sqlCreateHelp: 'sql-createdatabase.html',
hasSQL: true,
hasDepends: true,
canDrop: true,

View File

@ -292,6 +292,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backform) {
var role = pgAdmin.Browser.Nodes['role'] = pgAdmin.Browser.Node.extend({
parent_type: 'server',
type: 'role',
sqlAlterHelp: 'sql-alterrole.html',
sqlCreateHelp: 'sql-createrole.html',
label: '{{ _('Login/Group Role') }}',
hasSQL: true,
canDrop: true,

View File

@ -47,6 +47,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
pgAdmin.Browser.Nodes['tablespace'] = pgAdmin.Browser.Node.extend({
parent_type: 'server',
type: 'tablespace',
sqlAlterHelp: 'sql-altertablespace.html',
sqlCreateHelp: 'sql-createtablespace.html',
label: '{{ _('Tablespace') }}',
hasSQL: true,
canDrop: true,

View File

@ -19,7 +19,7 @@ function(_, pgAdmin) {
showTitle: true,
isClosable: true,
isPrivate: false,
url: 'about:blank',
url: '',
panel: null,
frame: null,
load: function(docker) {
@ -41,7 +41,9 @@ function(_, pgAdmin) {
var frame = new wcIFrame($frameArea, myPanel);
$(myPanel).data('embeddedFrame', frame);
setTimeout(function() { frame.openURL(that.url); }, 500);
if (that.url != '') {
setTimeout(function() { frame.openURL(that.url); }, 500);
}
if (that.events && _.isObject(that.events)) {
_.each(that.events, function(v, k) {

View File

@ -50,6 +50,10 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
type: undefined,
// Label
label: '',
// SQL help pages
sqlAlterHelp: '',
sqlCreateHelp: '',
title: function(d) {
return o.label + (d ? (' - ' + d.label) : '');
},
@ -689,10 +693,72 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
});
}
});
buttons.push({
label: '', type: 'help',
tooltip: '{{ _("Help on the SQL for this object type") }}',
extraClasses: ['btn-default'],
icon: 'fa fa-lg fa-question-circle',
disabled: (that.sqlAlterHelp == '' && that.sqlCreateHelp == '') ? true : false,
register: function(btn) {
btn.click(function() {
onSqlHelp();
});
}
});
createButtons(buttons, 'header', 'pg-prop-btn-group-above');
}
j.append(content);
},
onSqlHelp = function() {
// See if we can find an existing panel, if not, create one
pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
if (pnlSqlHelp == null) {
pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_sql_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
}
// Construct the URL
server = that.getTreeNodeHierarchy(item).server;
url = '{{ pg_help_path }}'
if (server.server_type == 'ppas') {
url = '{{ edbas_help_path }}'
}
major = Math.floor(server.version / 10000)
minor = Math.floor(server.version / 100) - (major * 100)
url = url.replace('$VERSION$', major + '.' + minor)
if (!url.endsWith('/')) {
url = url + '/'
}
if (that.sqlCreateHelp == '' && that.sqlAlterHelp != '') {
url = url + that.sqlAlterHelp
} else if (that.sqlCreateHelp != '' && that.sqlAlterHelp == '') {
url = url + that.sqlCreateHelp
} else {
if (view.model.isNew()) {
url = url + that.sqlCreateHelp
} else {
url = url + that.sqlAlterHelp
}
}
// Update the panel
iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('SQL: ' + that.label);
pnlSqlHelp.icon(
_.isFunction(that['node_image']) ?
(that['node_image']).apply(that, [data, view.model]) :
(that['node_image'] || ('icon-' + that.type))
);
pnlSqlHelp.focus();
iframe.url = url;
iframe.openURL(url);
}
editFunc = function() {
if (action && action == 'properties') {
action = 'edit';
@ -756,6 +822,17 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
// Create proper buttons
createButtons([{
label: '', type: 'help',
tooltip: '{{ _("Help on the SQL for this object type") }}',
extraClasses: ['btn-default'],
icon: 'fa fa-lg fa-question-circle',
disabled: that.sqlCreateHelp == '' ? true : false,
register: function(btn) {
btn.click(function() {
onSqlHelp();
});
}
},{
label: '{{ _("Save") }}', type: 'save',
tooltip: '{{ _("Save this object") }}',
extraClasses: ['btn-primary'],

View File

@ -10,6 +10,7 @@
"""A blueprint module implementing the pgAdmin help system."""
MODULE_NAME = 'help'
from pgadmin.utils.preferences import Preferences
from pgadmin.utils import PgAdminModule
from pgadmin.utils.menu import MenuItem, Panel
from flask.ext.babel import gettext
@ -57,9 +58,36 @@ class HelpModule(PgAdminModule):
Panel(name='pnl_postgresql_website',
priority=300,
title=gettext('PostgreSQL Website'),
content='http://www.postgresql.org/')]
content='http://www.postgresql.org/'),
Panel(name='pnl_sql_help',
priority=400,
isPrivate=True,
title=gettext('SQL Help'))]
def register_preferences(self):
"""
register_preferences
Register preferences for this module.
"""
# Register options for the PG and PPAS help paths
self.help_preference = Preferences('paths', gettext('Paths'))
self.pg_help_path = self.help_preference.register(
'help', 'pg_help_path',
gettext("PostgreSQL Help Path"), 'text',
'http://www.postgresql.org/docs/$VERSION$/static/',
category_label=gettext('Help'),
help_str=gettext('Path to the PostgreSQL documentation. $VERSION$ will be replaced with the major.minor version number.')
)
self.edbas_help_path = self.help_preference.register(
'help', 'edbas_help_path',
gettext("EDB Advanced Server Help Path"), 'text',
'http://www.enterprisedb.com/docs/en/$VERSION$/pg/',
category_label=gettext('Help'),
help_str=gettext('Path to the EDB Advanced Server documentation. $VERSION$ will be replaced with the major.minor version number.')
)
# Initialise the module
blueprint = HelpModule(MODULE_NAME, __name__, static_url_path='/help',

View File

@ -18,7 +18,7 @@ class MenuItem(object):
class Panel(object):
def __init__(self, name, title, content, width=500, height=600, isIframe=True,
def __init__(self, name, title, content='', width=500, height=600, isIframe=True,
showTitle=True, isCloseable=True, isPrivate=False, priority=None,
icon=None, data=None):
self.name = name