Re-organise node structure and loading to make things somewhat more
simple. This also adds the ability to display servers on the treeview.pull/3/head
parent
7f68d6fced
commit
fe834d1ed2
|
@ -84,7 +84,7 @@ int main(int argc, char * argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the app server URL
|
// Generate the app server URL
|
||||||
QString appServerUrl = QString("http://localhost:%1/utils/test").arg(port);
|
QString appServerUrl = QString("http://localhost:%1/").arg(port);
|
||||||
|
|
||||||
// Now the server should be up, we'll attempt to connect and get a response.
|
// Now the server should be up, we'll attempt to connect and get a response.
|
||||||
// We'll retry in a loop a few time before aborting if necessary. The browser
|
// We'll retry in a loop a few time before aborting if necessary. The browser
|
||||||
|
@ -128,7 +128,7 @@ bool PingServer(QUrl url)
|
||||||
QNetworkReply *reply;
|
QNetworkReply *reply;
|
||||||
QVariant redirectUrl;
|
QVariant redirectUrl;
|
||||||
|
|
||||||
url.setPath("/utils/ping");
|
url.setPath("/ping");
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,9 @@ import os, sys
|
||||||
|
|
||||||
# We need to include the root directory in sys.path to ensure that we can
|
# We need to include the root directory in sys.path to ensure that we can
|
||||||
# find everything we need when running in the standalone runtime.
|
# find everything we need when running in the standalone runtime.
|
||||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
root = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
if sys.path[0] != root:
|
||||||
|
sys.path.insert(0, root)
|
||||||
|
|
||||||
import config
|
import config
|
||||||
from pgadmin import create_app
|
from pgadmin import create_app
|
||||||
|
@ -47,7 +49,6 @@ if not os.path.isfile(config.SQLITE_PATH):
|
||||||
|
|
||||||
# Create the app!
|
# Create the app!
|
||||||
app = create_app()
|
app = create_app()
|
||||||
app.logger.debug("Python syspath: %s", sys.path)
|
|
||||||
|
|
||||||
# Start the web server. The port number should have already been set by the
|
# Start the web server. The port number should have already been set by the
|
||||||
# runtime if we're running in desktop mode, otherwise we'll just use the
|
# runtime if we're running in desktop mode, otherwise we'll just use the
|
||||||
|
|
|
@ -19,7 +19,7 @@ from flask_mail import Mail
|
||||||
from htmlmin.minify import html_minify
|
from htmlmin.minify import html_minify
|
||||||
from settings.settings_model import db, Role, User
|
from settings.settings_model import db, Role, User
|
||||||
|
|
||||||
import inspect, imp, logging, os
|
import inspect, imp, logging, os, sys
|
||||||
|
|
||||||
# Configuration settings
|
# Configuration settings
|
||||||
import config
|
import config
|
||||||
|
@ -66,6 +66,7 @@ def create_app(app_name=config.APP_NAME):
|
||||||
app.logger.info('################################################################################')
|
app.logger.info('################################################################################')
|
||||||
app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION)
|
app.logger.info('Starting %s v%s...', config.APP_NAME, config.APP_VERSION)
|
||||||
app.logger.info('################################################################################')
|
app.logger.info('################################################################################')
|
||||||
|
app.logger.debug("Python syspath: %s", sys.path)
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Setup i18n
|
# Setup i18n
|
||||||
|
@ -117,6 +118,9 @@ def create_app(app_name=config.APP_NAME):
|
||||||
app.logger.info('Skipping blacklisted module: %s' % f)
|
app.logger.info('Skipping blacklisted module: %s' % f)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Construct the "real" module name
|
||||||
|
f = 'pgadmin.' + f
|
||||||
|
|
||||||
# Looks like a module, so import it, and register the blueprint if present
|
# Looks like a module, so import it, and register the blueprint if present
|
||||||
# We rely on the ordering of syspath to ensure we actually get the right
|
# We rely on the ordering of syspath to ensure we actually get the right
|
||||||
# module here. Note that we also try to load the 'hooks' module for
|
# module here. Note that we also try to load the 'hooks' module for
|
||||||
|
|
|
@ -7,5 +7,6 @@
|
||||||
#
|
#
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# Define the global node list
|
# Define the node lists
|
||||||
nodes = [ ]
|
all_nodes = [ ]
|
||||||
|
sub_nodes = [ ]
|
|
@ -12,40 +12,10 @@
|
||||||
import os, sys
|
import os, sys
|
||||||
import config
|
import config
|
||||||
|
|
||||||
from . import nodes
|
from pgadmin.browser.utils import register_modules
|
||||||
|
from pgadmin.browser import all_nodes
|
||||||
|
from . import sub_nodes
|
||||||
|
|
||||||
def register_submodules(app):
|
def register_submodules(app):
|
||||||
"""Register any child node blueprints"""
|
"""Register any child node blueprints"""
|
||||||
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'nodes')
|
register_modules(app, __file__, all_nodes, sub_nodes, 'pgadmin.browser')
|
||||||
sys.path.insert(0, path)
|
|
||||||
files = os.listdir(path)
|
|
||||||
|
|
||||||
for f in files:
|
|
||||||
d = os.path.join(path, f)
|
|
||||||
if os.path.isdir(d) and os.path.isfile(os.path.join(d, '__init__.py')):
|
|
||||||
|
|
||||||
if f in config.NODE_BLACKLIST:
|
|
||||||
app.logger.info('Skipping blacklisted node: %s' % f)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Looks like a node, so import it, and register the blueprint if present
|
|
||||||
# We rely on the ordering of syspath to ensure we actually get the right
|
|
||||||
# module here.
|
|
||||||
app.logger.info('Examining potential node: %s' % d)
|
|
||||||
node = __import__(f, globals(), locals(), ['hooks', 'views'], -1)
|
|
||||||
|
|
||||||
# Add the node to the global module list
|
|
||||||
nodes.append(node)
|
|
||||||
|
|
||||||
# Register the blueprint if present
|
|
||||||
if 'views' in dir(node) and 'blueprint' in dir(node.views):
|
|
||||||
app.logger.info('Registering blueprint node: %s' % f)
|
|
||||||
app.register_blueprint(node.views.blueprint)
|
|
||||||
app.logger.debug(' - root_path: %s' % node.views.blueprint.root_path)
|
|
||||||
app.logger.debug(' - static_folder: %s' % node.views.blueprint.static_folder)
|
|
||||||
app.logger.debug(' - template_folder: %s' % node.views.blueprint.template_folder)
|
|
||||||
|
|
||||||
# Register any sub-modules
|
|
||||||
if 'hooks' in dir(node) and 'register_submodules' in dir(node.hooks):
|
|
||||||
app.logger.info('Registering sub-modules in %s' % f)
|
|
||||||
node.hooks.register_submodules(app)
|
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
#
|
#
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
"""Base class for Collection Nodes on the browser treeview"""
|
# Node meta data
|
||||||
|
NODE_TYPE = 'server-group'
|
||||||
|
NODE_PATH = '/browser/nodes/' + NODE_TYPE
|
||||||
|
|
||||||
def get_name():
|
# Define the child node list
|
||||||
"""Returns the display name of the collection"""
|
sub_nodes = [ ]
|
||||||
return ""
|
|
|
@ -13,15 +13,23 @@ from flask import render_template, url_for
|
||||||
from flask.ext.babel import gettext
|
from flask.ext.babel import gettext
|
||||||
from flask.ext.security import current_user
|
from flask.ext.security import current_user
|
||||||
|
|
||||||
|
from pgadmin.browser.utils import register_modules
|
||||||
from pgadmin.settings.settings_model import db, ServerGroup
|
from pgadmin.settings.settings_model import db, ServerGroup
|
||||||
|
|
||||||
|
from pgadmin.browser import all_nodes
|
||||||
|
from . import NODE_TYPE, sub_nodes
|
||||||
|
|
||||||
|
def register_submodules(app):
|
||||||
|
"""Register any child node blueprints"""
|
||||||
|
register_modules(app, __file__, all_nodes, sub_nodes, 'pgadmin.browser.server_groups')
|
||||||
|
|
||||||
def get_nodes():
|
def get_nodes():
|
||||||
"""Return a JSON document listing the server groups for the user"""
|
"""Return a JSON document listing the server groups for the user"""
|
||||||
groups = ServerGroup.query.filter_by(user_id=current_user.id)
|
groups = ServerGroup.query.filter_by(user_id=current_user.id)
|
||||||
|
|
||||||
value = ''
|
value = ''
|
||||||
for group in groups:
|
for group in groups:
|
||||||
value += '{"id":%d,"label":"%s","icon":"icon-server-group","inode":true},' % (group.id, group.name)
|
value += '{"id":"%s/%d","label":"%s","icon":"icon-%s","inode":true,"_type":"%s"},' % (NODE_TYPE, group.id, group.name, NODE_TYPE, NODE_TYPE)
|
||||||
value = value[:-1]
|
value = value[:-1]
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
@ -38,10 +46,10 @@ def get_file_menu_items():
|
||||||
|
|
||||||
|
|
||||||
def get_context_menu_items():
|
def get_context_menu_items():
|
||||||
"""Return a (set) of dicts of content menu items with name, label, priority and JS"""
|
"""Return a (set) of dicts of content menu items with name, node type, label, priority and JS"""
|
||||||
return [
|
return [
|
||||||
{'name': 'delete', 'label': gettext('Delete server group'), 'priority': 100, 'onclick': 'delete_server_group(item);'},
|
{'name': 'delete_server_group', 'type': NODE_TYPE, 'label': gettext('Delete server group'), 'priority': 10, 'onclick': 'delete_server_group(item);'},
|
||||||
{'name': 'rename', 'label': gettext('Rename server group...'), 'priority': 200, 'onclick': 'rename_server_group(item);'}
|
{'name': 'rename_server_group', 'type': NODE_TYPE, 'label': gettext('Rename server group...'), 'priority': 20, 'onclick': 'rename_server_group(item);'}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +62,7 @@ def get_css_snippets():
|
||||||
"""Return the CSS needed to display the treeview node image."""
|
"""Return the CSS needed to display the treeview node image."""
|
||||||
css = ".icon-server-group {\n"
|
css = ".icon-server-group {\n"
|
||||||
css += " background: url('%s') 0 0 no-repeat !important;\n" % \
|
css += " background: url('%s') 0 0 no-repeat !important;\n" % \
|
||||||
url_for('NODE-server-group.static', filename='img/server-group.png')
|
url_for('NODE-%s.static' % NODE_TYPE, filename='img/server-group.png')
|
||||||
css += "{"
|
css += "}\n"
|
||||||
|
|
||||||
return css
|
return css
|
|
@ -7,9 +7,10 @@
|
||||||
#
|
#
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
"""Base class for Object Nodes on the browser treeview"""
|
# Node meta data
|
||||||
|
NODE_TYPE = 'server'
|
||||||
|
NODE_PATH = '/browser/nodes/' + NODE_TYPE
|
||||||
|
|
||||||
def get_name():
|
# Define the child node list
|
||||||
"""Returns the object's name"""
|
sub_nodes = [ ]
|
||||||
return ""
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2015, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Integration hooks for servers."""
|
||||||
|
|
||||||
|
from flask import render_template, url_for
|
||||||
|
from flask.ext.babel import gettext
|
||||||
|
from flask.ext.security import current_user
|
||||||
|
|
||||||
|
from pgadmin.settings.settings_model import db, Server
|
||||||
|
from . import NODE_TYPE
|
||||||
|
|
||||||
|
def get_nodes(server_group):
|
||||||
|
"""Return a JSON document listing the server groups for the user"""
|
||||||
|
servers = Server.query.filter_by(user_id=current_user.id, servergroup_id=server_group)
|
||||||
|
|
||||||
|
value = ''
|
||||||
|
for server in servers:
|
||||||
|
value += '{"id":"%s/%d","label":"%s","icon":"icon-%s","inode":true,"_type":"%s"},' % (NODE_TYPE, server.id, server.name, NODE_TYPE, NODE_TYPE)
|
||||||
|
value = value[:-1]
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_menu_items():
|
||||||
|
"""Return a (set) of dicts of file menu items, with name, priority, URL,
|
||||||
|
target and onclick code."""
|
||||||
|
return [
|
||||||
|
{'name': 'mnu_add_server', 'label': gettext('Add a server...'), 'priority': 50, 'url': '#', 'onclick': 'add_server()'},
|
||||||
|
{'name': 'mnu_delete_server', 'label': gettext('Delete server'), 'priority': 60, 'url': '#', 'onclick': 'delete_server()'},
|
||||||
|
{'name': 'mnu_rename_server', 'label': gettext('Rename server...'), 'priority': 70, 'url': '#', 'onclick': 'rename_server()'}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_context_menu_items():
|
||||||
|
"""Return a (set) of dicts of content menu items with name, node type, label, priority and JS"""
|
||||||
|
return [
|
||||||
|
{'name': 'delete_server', 'type': NODE_TYPE, 'label': gettext('Delete server'), 'priority': 50, 'onclick': 'delete_server(item);'},
|
||||||
|
{'name': 'rename_server', 'type': NODE_TYPE, 'label': gettext('Rename server...'), 'priority': 60, 'onclick': 'rename_server(item);'}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_script_snippets():
|
||||||
|
"""Return the script snippets needed to handle treeview node operations."""
|
||||||
|
return render_template('servers/servers.js')
|
||||||
|
|
||||||
|
|
||||||
|
def get_css_snippets():
|
||||||
|
"""Return the CSS needed to display the treeview node image."""
|
||||||
|
css = ".icon-server {\n"
|
||||||
|
css += " background: url('%s') 0 0 no-repeat !important;\n" % \
|
||||||
|
url_for('NODE-%s.static' % NODE_TYPE, filename='img/server.png')
|
||||||
|
css += "}\n"
|
||||||
|
|
||||||
|
return css
|
Binary file not shown.
After Width: | Height: | Size: 553 B |
|
@ -0,0 +1,82 @@
|
||||||
|
// Add a server
|
||||||
|
function add_server() {
|
||||||
|
var alert = alertify.prompt(
|
||||||
|
'{{ _('Add a server') }}',
|
||||||
|
'{{ _('Enter a name for the new server') }}',
|
||||||
|
'',
|
||||||
|
function(evt, value) {
|
||||||
|
$.post("{{ url_for('NODE-server.add') }}", { name: value })
|
||||||
|
.done(function(data) {
|
||||||
|
if (data.success == 0) {
|
||||||
|
report_error(data.errormsg, data.info);
|
||||||
|
} else {
|
||||||
|
var item = {
|
||||||
|
id: data.data.id,
|
||||||
|
label: data.data.name,
|
||||||
|
inode: true,
|
||||||
|
open: false,
|
||||||
|
icon: 'icon-server'
|
||||||
|
}
|
||||||
|
|
||||||
|
tree.append(null, {
|
||||||
|
itemData: item
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
null
|
||||||
|
);
|
||||||
|
alert.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a server
|
||||||
|
function delete_server(item) {
|
||||||
|
alertify.confirm(
|
||||||
|
'{{ _('Delete server?') }}',
|
||||||
|
'{{ _('Are you sure you wish to delete the server "{0}"?') }}'.replace('{0}', tree.getLabel(item)),
|
||||||
|
function() {
|
||||||
|
var id = tree.getId(item)
|
||||||
|
$.post("{{ url_for('NODE-server.delete') }}", { id: id })
|
||||||
|
.done(function(data) {
|
||||||
|
if (data.success == 0) {
|
||||||
|
report_error(data.errormsg, data.info);
|
||||||
|
} else {
|
||||||
|
var next = tree.next(item);
|
||||||
|
var prev = tree.prev(item);
|
||||||
|
tree.remove(item);
|
||||||
|
if (next.length) {
|
||||||
|
tree.select(next);
|
||||||
|
} else if (prev.length) {
|
||||||
|
tree.select(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename a server
|
||||||
|
function rename_server(item) {
|
||||||
|
alertify.prompt(
|
||||||
|
'{{ _('Rename server') }}',
|
||||||
|
'{{ _('Enter a new name for the server') }}',
|
||||||
|
tree.getLabel(item),
|
||||||
|
function(evt, value) {
|
||||||
|
var id = tree.getId(item)
|
||||||
|
$.post("{{ url_for('NODE-server.rename') }}", { id: id, name: value })
|
||||||
|
.done(function(data) {
|
||||||
|
if (data.success == 0) {
|
||||||
|
report_error(data.errormsg, data.info);
|
||||||
|
} else {
|
||||||
|
tree.setLabel(item, { label: value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2015, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Defines views for management of servers"""
|
||||||
|
|
||||||
|
from flask import Blueprint, Response, current_app, request
|
||||||
|
from flask.ext.babel import gettext
|
||||||
|
from flask.ext.security import current_user, login_required
|
||||||
|
|
||||||
|
from . import NODE_TYPE, NODE_PATH
|
||||||
|
from pgadmin.utils.ajax import make_json_response
|
||||||
|
from pgadmin.settings.settings_model import db, ServerGroup
|
||||||
|
import config
|
||||||
|
|
||||||
|
# Initialise the module
|
||||||
|
blueprint = Blueprint("NODE-" + NODE_TYPE, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix=NODE_PATH)
|
||||||
|
|
||||||
|
@blueprint.route('/add/', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def add():
|
||||||
|
"""Add a server node to the settings database"""
|
||||||
|
success = 1
|
||||||
|
errormsg = ''
|
||||||
|
data = { }
|
||||||
|
|
||||||
|
if request.form['name'] != '':
|
||||||
|
server = Server(user_id=current_user.id, name=request.form['name'])
|
||||||
|
|
||||||
|
try:
|
||||||
|
db.session.add(server)
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
success = 0
|
||||||
|
errormsg = e.message
|
||||||
|
|
||||||
|
else:
|
||||||
|
success = 0
|
||||||
|
errormsg = gettext('No server name was specified')
|
||||||
|
|
||||||
|
if success == 1:
|
||||||
|
data['id'] = server.id
|
||||||
|
data['name'] = server.name
|
||||||
|
|
||||||
|
return make_json_response(success=success,
|
||||||
|
errormsg=errormsg,
|
||||||
|
info=traceback.format_exc(),
|
||||||
|
result=request.form,
|
||||||
|
data=data)
|
||||||
|
|
||||||
|
@blueprint.route('/delete/', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def delete():
|
||||||
|
"""Delete a server node in the settings database"""
|
||||||
|
success = 1
|
||||||
|
errormsg = ''
|
||||||
|
|
||||||
|
if request.form['id'] != '':
|
||||||
|
# There can be only one record at most
|
||||||
|
servergroup = Server.query.filter_by(user_id=current_user.id, id=int(request.form['id'])).first()
|
||||||
|
|
||||||
|
if server is None:
|
||||||
|
success = 0
|
||||||
|
errormsg = gettext('The specified server could not be found.')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
db.session.delete(server)
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
success = 0
|
||||||
|
errormsg = e.message
|
||||||
|
|
||||||
|
else:
|
||||||
|
success = 0
|
||||||
|
errormsg = gettext('No server was specified.')
|
||||||
|
|
||||||
|
return make_json_response(success=success,
|
||||||
|
errormsg=errormsg,
|
||||||
|
info=traceback.format_exc(),
|
||||||
|
result=request.form)
|
||||||
|
|
||||||
|
@blueprint.route('/rename/', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def rename():
|
||||||
|
"""Rename a server node in the settings database"""
|
||||||
|
success = 1
|
||||||
|
errormsg = ''
|
||||||
|
|
||||||
|
if request.form['id'] != '':
|
||||||
|
# There can be only one record at most
|
||||||
|
servergroup = Server.query.filter_by(user_id=current_user.id, id=int(request.form['id'])).first()
|
||||||
|
|
||||||
|
if server is None:
|
||||||
|
success = 0
|
||||||
|
errormsg = gettext('The specified server could not be found.')
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
server.name = request.form['name']
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
success = 0
|
||||||
|
errormsg = e.message
|
||||||
|
|
||||||
|
else:
|
||||||
|
success = 0
|
||||||
|
errormsg = gettext('No server was specified.')
|
||||||
|
|
||||||
|
return make_json_response(success=success,
|
||||||
|
errormsg=errormsg,
|
||||||
|
info=traceback.format_exc(),
|
||||||
|
result=request.form)
|
||||||
|
|
Before Width: | Height: | Size: 504 B After Width: | Height: | Size: 504 B |
|
@ -9,21 +9,39 @@
|
||||||
|
|
||||||
"""Defines views for management of server groups"""
|
"""Defines views for management of server groups"""
|
||||||
|
|
||||||
NODE_NAME = 'server-group'
|
|
||||||
|
|
||||||
NODE_PATH = '/browser/' + NODE_NAME
|
|
||||||
|
|
||||||
import traceback
|
|
||||||
from flask import Blueprint, Response, current_app, request
|
from flask import Blueprint, Response, current_app, request
|
||||||
from flask.ext.babel import gettext
|
from flask.ext.babel import gettext
|
||||||
from flask.ext.security import current_user, login_required
|
from flask.ext.security import current_user, login_required
|
||||||
|
|
||||||
from utils.ajax import make_json_response
|
from . import NODE_TYPE, NODE_PATH, sub_nodes
|
||||||
|
from pgadmin.utils.ajax import make_json_response
|
||||||
from pgadmin.settings.settings_model import db, ServerGroup
|
from pgadmin.settings.settings_model import db, ServerGroup
|
||||||
import config
|
import config
|
||||||
|
|
||||||
# Initialise the module
|
# Initialise the module
|
||||||
blueprint = Blueprint("NODE-" + NODE_NAME, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix=NODE_PATH)
|
blueprint = Blueprint("NODE-" + NODE_TYPE, __name__, static_folder='static', static_url_path='', template_folder='templates', url_prefix=NODE_PATH)
|
||||||
|
|
||||||
|
@blueprint.route("/<server_group>")
|
||||||
|
@login_required
|
||||||
|
def get_nodes(server_group):
|
||||||
|
"""Build a list of treeview nodes from the child nodes."""
|
||||||
|
value = '['
|
||||||
|
|
||||||
|
for node in sub_nodes:
|
||||||
|
if 'hooks' in dir(node) and 'get_nodes' in dir(node.hooks):
|
||||||
|
value += node.hooks.get_nodes(server_group) + ','
|
||||||
|
|
||||||
|
if value[-1:] == ',':
|
||||||
|
value = value[:-1]
|
||||||
|
|
||||||
|
value += ']'
|
||||||
|
|
||||||
|
resp = Response(response=value,
|
||||||
|
status=200,
|
||||||
|
mimetype="text/json")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/add/', methods=['POST'])
|
@blueprint.route('/add/', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
|
@ -170,10 +170,12 @@ ALTER TABLE tickets_detail \n\
|
||||||
};
|
};
|
||||||
{% if context_items is defined %}
|
{% if context_items is defined %}
|
||||||
{% for context_item in context_items %}
|
{% for context_item in context_items %}
|
||||||
menu['{{ context_item.name }}'] = {
|
if (tree.itemData(item)._type == '{{ context_item.type }}') {
|
||||||
name: '{{ context_item.label }}',
|
menu['{{ context_item.name }}'] = {
|
||||||
callback: function() { {{ context_item.onclick }} }
|
name: '{{ context_item.label }}',
|
||||||
};
|
callback: function() { {{ context_item.onclick }} }
|
||||||
|
};
|
||||||
|
}
|
||||||
{% endfor %}{% endif %}
|
{% endfor %}{% endif %}
|
||||||
return {
|
return {
|
||||||
autoHide: true,
|
autoHide: true,
|
||||||
|
@ -184,6 +186,7 @@ ALTER TABLE tickets_detail \n\
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function report_error(message, info) {
|
function report_error(message, info) {
|
||||||
|
|
||||||
text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
|
text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2015, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Browser helper utilities"""
|
||||||
|
|
||||||
|
import os, sys
|
||||||
|
import config
|
||||||
|
|
||||||
|
def register_modules(app, file, all_nodes, sub_nodes, prefix):
|
||||||
|
"""Register any child node blueprints for the specified file"""
|
||||||
|
path = os.path.dirname(os.path.realpath(file))
|
||||||
|
files = os.listdir(path)
|
||||||
|
|
||||||
|
for f in files:
|
||||||
|
d = os.path.join(path, f)
|
||||||
|
if os.path.isdir(d) and os.path.isfile(os.path.join(d, '__init__.py')):
|
||||||
|
|
||||||
|
if f in config.NODE_BLACKLIST:
|
||||||
|
app.logger.info('Skipping blacklisted node: %s' % f)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Construct the 'real' module name
|
||||||
|
if prefix != '':
|
||||||
|
f = prefix + '.' + f
|
||||||
|
|
||||||
|
# Looks like a node, so import it, and register the blueprint if present
|
||||||
|
# We rely on the ordering of syspath to ensure we actually get the right
|
||||||
|
# module here.
|
||||||
|
app.logger.info('Examining potential node: %s' % d)
|
||||||
|
node = __import__(f, globals(), locals(), ['hooks', 'views'], -1)
|
||||||
|
|
||||||
|
# Add the node to the node lists
|
||||||
|
all_nodes.append(node)
|
||||||
|
sub_nodes.append(node)
|
||||||
|
|
||||||
|
# Register the blueprint if present
|
||||||
|
if 'views' in dir(node) and 'blueprint' in dir(node.views):
|
||||||
|
app.logger.info('Registering blueprint node: %s' % f)
|
||||||
|
app.register_blueprint(node.views.blueprint)
|
||||||
|
app.logger.debug(' - root_path: %s' % node.views.blueprint.root_path)
|
||||||
|
app.logger.debug(' - static_folder: %s' % node.views.blueprint.static_folder)
|
||||||
|
app.logger.debug(' - template_folder: %s' % node.views.blueprint.template_folder)
|
||||||
|
|
||||||
|
# Register any sub-modules
|
||||||
|
if 'hooks' in dir(node) and 'register_submodules' in dir(node.hooks):
|
||||||
|
app.logger.info('Registering sub-modules in %s' % f)
|
||||||
|
node.hooks.register_submodules(app)
|
|
@ -16,10 +16,12 @@ from flask.ext.security import login_required
|
||||||
from flask.ext.login import current_user
|
from flask.ext.login import current_user
|
||||||
from inspect import getmoduleinfo, getmembers
|
from inspect import getmoduleinfo, getmembers
|
||||||
|
|
||||||
from . import nodes
|
from . import sub_nodes
|
||||||
|
from pgadmin.browser import all_nodes
|
||||||
from pgadmin import modules
|
from pgadmin import modules
|
||||||
from pgadmin.settings import get_setting
|
from pgadmin.settings import get_setting
|
||||||
|
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
|
||||||
# Initialise the module
|
# Initialise the module
|
||||||
|
@ -47,7 +49,7 @@ def index():
|
||||||
stylesheets = [ ]
|
stylesheets = [ ]
|
||||||
scripts = [ ]
|
scripts = [ ]
|
||||||
|
|
||||||
modules_and_nodes = modules + nodes
|
modules_and_nodes = modules + all_nodes
|
||||||
|
|
||||||
# Add browser stylesheets
|
# Add browser stylesheets
|
||||||
stylesheets.append(url_for('static', filename='css/codemirror/codemirror.css'))
|
stylesheets.append(url_for('static', filename='css/codemirror/codemirror.css'))
|
||||||
|
@ -129,7 +131,7 @@ def index():
|
||||||
def browser_js():
|
def browser_js():
|
||||||
"""Render and return JS snippets from the nodes and modules."""
|
"""Render and return JS snippets from the nodes and modules."""
|
||||||
snippets = ''
|
snippets = ''
|
||||||
modules_and_nodes = modules + nodes
|
modules_and_nodes = modules + all_nodes
|
||||||
|
|
||||||
# Load the core browser code first
|
# Load the core browser code first
|
||||||
|
|
||||||
|
@ -137,8 +139,6 @@ def browser_js():
|
||||||
context_items = [ ]
|
context_items = [ ]
|
||||||
panel_items = [ ]
|
panel_items = [ ]
|
||||||
|
|
||||||
modules_and_nodes = modules + nodes
|
|
||||||
|
|
||||||
for module in modules_and_nodes:
|
for module in modules_and_nodes:
|
||||||
# Get any context menu items
|
# Get any context menu items
|
||||||
if 'hooks' in dir(module) and 'get_context_menu_items' in dir(module.hooks):
|
if 'hooks' in dir(module) and 'get_context_menu_items' in dir(module.hooks):
|
||||||
|
@ -174,7 +174,7 @@ def browser_js():
|
||||||
def browser_css():
|
def browser_css():
|
||||||
"""Render and return CSS snippets from the nodes and modules."""
|
"""Render and return CSS snippets from the nodes and modules."""
|
||||||
snippets = ''
|
snippets = ''
|
||||||
modules_and_nodes = modules + nodes
|
modules_and_nodes = modules + all_nodes
|
||||||
|
|
||||||
for module in modules_and_nodes:
|
for module in modules_and_nodes:
|
||||||
if 'hooks' in dir(module) and 'get_css_snippets' in dir(module.hooks):
|
if 'hooks' in dir(module) and 'get_css_snippets' in dir(module.hooks):
|
||||||
|
@ -187,13 +187,13 @@ def browser_css():
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/root-nodes.json")
|
@blueprint.route("/nodes/")
|
||||||
@login_required
|
@login_required
|
||||||
def get_nodes():
|
def get_nodes():
|
||||||
"""Build a list of treeview nodes from the child modules."""
|
"""Build a list of treeview nodes from the child nodes."""
|
||||||
value = '['
|
value = '['
|
||||||
|
|
||||||
for node in nodes:
|
for node in sub_nodes:
|
||||||
if 'hooks' in dir(node) and 'get_nodes' in dir(node.hooks):
|
if 'hooks' in dir(node) and 'get_nodes' in dir(node.hooks):
|
||||||
value += node.hooks.get_nodes() + ','
|
value += node.hooks.get_nodes() + ','
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
"""A blueprint module providing utility functions for the application."""
|
"""A blueprint module providing utility functions for the application."""
|
||||||
MODULE_NAME = 'utils'
|
MODULE_NAME = 'misc'
|
||||||
|
|
||||||
import config
|
import config
|
||||||
from flask import Blueprint, render_template
|
from flask import Blueprint, render_template
|
||||||
from flask.ext.security import login_required
|
from flask.ext.security import login_required
|
||||||
|
|
||||||
# Initialise the module
|
# Initialise the module
|
||||||
blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', template_folder='templates', url_prefix='/' + MODULE_NAME)
|
blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', template_folder='templates', url_prefix='')
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# A special URL used to "ping" the server
|
# A special URL used to "ping" the server
|
|
@ -15,7 +15,7 @@ from flask import Blueprint, Response, abort, request, render_template
|
||||||
from flask.ext.security import login_required
|
from flask.ext.security import login_required
|
||||||
|
|
||||||
import config
|
import config
|
||||||
from utils.ajax import make_json_response
|
from pgadmin.utils.ajax import make_json_response
|
||||||
from . import get_setting, store_setting
|
from . import get_setting, store_setting
|
||||||
|
|
||||||
# Initialise the module
|
# Initialise the module
|
||||||
|
|
Loading…
Reference in New Issue