mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
This is a big one campers; Add initial support for treeview nodes.
This commit adds the following: - Storage of server groups in the configuration database - Creation of a default server group on in the database - A mechanism for plugging in treeview node types - A node type for server groups with: - Treeview display - Custom per-node javascript implementing a menu option/dialogue to add new groups - Custom per-node CSS to style the treeview node - JSON formatted data in response to AJAX requests, including: - Success/failure indication - Error message - Extra info (e.g. stack trace) - The original request data - Additional return data, e.g. node ID and label etc.
This commit is contained in:
parent
e2832351ed
commit
89cc11fb80
@ -39,6 +39,10 @@ APP_VERSION = '%s.%s.%s-%s' % (APP_MAJOR, APP_MINOR, APP_REVISION, APP_SUFFIX)
|
|||||||
# List of modules to skip when dynamically loading
|
# List of modules to skip when dynamically loading
|
||||||
MODULE_BLACKLIST = [ 'test' ]
|
MODULE_BLACKLIST = [ 'test' ]
|
||||||
|
|
||||||
|
# DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING!
|
||||||
|
# List of treeview browser nodes to skip when dynamically loading
|
||||||
|
NODE_BLACKLIST = [ ]
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Log settings
|
# Log settings
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
@ -103,10 +103,10 @@ def create_app(app_name=config.APP_NAME):
|
|||||||
|
|
||||||
# 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 'browser' module for
|
# module here. Note that we also try to load the 'hooks' module for
|
||||||
# the browser integration hooks.
|
# the browser integration hooks and other similar functions.
|
||||||
app.logger.info('Examining potential module: %s' % d)
|
app.logger.info('Examining potential module: %s' % d)
|
||||||
module = __import__(f, globals(), locals(), ['browser', 'views'], -1)
|
module = __import__(f, globals(), locals(), ['hooks', 'views'], -1)
|
||||||
|
|
||||||
# Add the module to the global module list
|
# Add the module to the global module list
|
||||||
modules.append(module)
|
modules.append(module)
|
||||||
@ -118,6 +118,11 @@ def create_app(app_name=config.APP_NAME):
|
|||||||
app.logger.debug(' - root_path: %s' % module.views.blueprint.root_path)
|
app.logger.debug(' - root_path: %s' % module.views.blueprint.root_path)
|
||||||
app.logger.debug(' - static_folder: %s' % module.views.blueprint.static_folder)
|
app.logger.debug(' - static_folder: %s' % module.views.blueprint.static_folder)
|
||||||
app.logger.debug(' - template_folder: %s' % module.views.blueprint.template_folder)
|
app.logger.debug(' - template_folder: %s' % module.views.blueprint.template_folder)
|
||||||
|
|
||||||
|
# Register any sub-modules
|
||||||
|
if 'hooks' in dir(module) and 'register_submodules' in dir(module.hooks):
|
||||||
|
app.logger.info('Registering sub-modules in %s' % f)
|
||||||
|
module.hooks.register_submodules(app)
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Handle the desktop login
|
# Handle the desktop login
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
# Define the global node list
|
||||||
|
nodes = [ ]
|
51
web/pgadmin/browser/hooks.py
Normal file
51
web/pgadmin/browser/hooks.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Browser application hooks"""
|
||||||
|
|
||||||
|
import os, sys
|
||||||
|
import config
|
||||||
|
|
||||||
|
from . import nodes
|
||||||
|
|
||||||
|
def register_submodules(app):
|
||||||
|
"""Register any child node blueprints"""
|
||||||
|
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'nodes')
|
||||||
|
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)
|
0
web/pgadmin/browser/nodes/__init__.py
Normal file
0
web/pgadmin/browser/nodes/__init__.py
Normal file
0
web/pgadmin/browser/nodes/server_groups/__init__.py
Normal file
0
web/pgadmin/browser/nodes/server_groups/__init__.py
Normal file
75
web/pgadmin/browser/nodes/server_groups/hooks.py
Normal file
75
web/pgadmin/browser/nodes/server_groups/hooks.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Integration hooks for server groups."""
|
||||||
|
|
||||||
|
from flask import url_for
|
||||||
|
from flask.ext.security import current_user
|
||||||
|
|
||||||
|
from pgadmin.settings.settings_model import db, ServerGroup
|
||||||
|
|
||||||
|
def get_nodes():
|
||||||
|
"""Return a JSON document listing the server groups for the user"""
|
||||||
|
groups = ServerGroup.query.filter_by(user_id=current_user.id)
|
||||||
|
|
||||||
|
value = ''
|
||||||
|
for group in groups:
|
||||||
|
value += '{"id":%d,"label":"%s","icon":"icon-server-group","inode":true},' % (group.id, group.name)
|
||||||
|
value = value[:-1]
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_file_menu_items():
|
||||||
|
"""Return a (set) of dicts of file menu items, with name, priority and URL."""
|
||||||
|
return [
|
||||||
|
{'name': 'Add a server group...', 'priority': 10, 'url': '#', 'onclick': 'add_server_group()'}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_script_snippets():
|
||||||
|
"""Return the script snippets needed to handle treeview node operations."""
|
||||||
|
script = """function add_server_group() {
|
||||||
|
var alert = alertify.prompt(
|
||||||
|
'Add a server group',
|
||||||
|
'Enter a name for the new server group',
|
||||||
|
'',
|
||||||
|
function(evt, value) { $.post("%s", { 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-group'
|
||||||
|
}
|
||||||
|
|
||||||
|
treeApi.append(null, {
|
||||||
|
itemData: item
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
function(evt, value) { }
|
||||||
|
);
|
||||||
|
alert.show();
|
||||||
|
}
|
||||||
|
""" % url_for('NODE-server-group.add')
|
||||||
|
return script
|
||||||
|
|
||||||
|
def get_css_snippets():
|
||||||
|
"""Return the CSS needed to display the treeview node image."""
|
||||||
|
css = ".icon-server-group {\n"
|
||||||
|
css += " background: url('%s') 0 0 no-repeat !important;\n" % \
|
||||||
|
url_for('NODE-server-group.static', filename='img/server-group.png')
|
||||||
|
css += "{"
|
||||||
|
|
||||||
|
return css
|
Binary file not shown.
After Width: | Height: | Size: 504 B |
64
web/pgadmin/browser/nodes/server_groups/views.py
Normal file
64
web/pgadmin/browser/nodes/server_groups/views.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# 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 server groups"""
|
||||||
|
|
||||||
|
NODE_NAME = 'server-group'
|
||||||
|
|
||||||
|
NODE_PATH = '/browser/' + NODE_NAME
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
from flask import Blueprint, Response, current_app, request
|
||||||
|
from flask.ext.security import current_user, login_required
|
||||||
|
|
||||||
|
from utils.ajax import make_json_result
|
||||||
|
from pgadmin.settings.settings_model import db, ServerGroup
|
||||||
|
import config
|
||||||
|
|
||||||
|
# Initialise the module
|
||||||
|
blueprint = Blueprint("NODE-" + NODE_NAME, __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 group node to the settings database"""
|
||||||
|
success = 1
|
||||||
|
errormsg = ''
|
||||||
|
data = { }
|
||||||
|
|
||||||
|
if request.form['name'] != '':
|
||||||
|
servergroup = ServerGroup(user_id=current_user.id, name=request.form['name'])
|
||||||
|
|
||||||
|
try:
|
||||||
|
db.session.add(servergroup)
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
success = 0
|
||||||
|
errormsg = e.message
|
||||||
|
|
||||||
|
else:
|
||||||
|
success = 0
|
||||||
|
errormsg = "No server group name was specified"
|
||||||
|
|
||||||
|
if success == 1:
|
||||||
|
data['id'] = servergroup.id
|
||||||
|
data['name'] = servergroup.name
|
||||||
|
|
||||||
|
value = make_json_result(success=success,
|
||||||
|
errormsg=errormsg,
|
||||||
|
info=traceback.format_exc(),
|
||||||
|
result=request.form,
|
||||||
|
data=data)
|
||||||
|
|
||||||
|
resp = Response(response=value,
|
||||||
|
status=200,
|
||||||
|
mimetype="text/json")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
39
web/pgadmin/browser/static/js/utils.js
Normal file
39
web/pgadmin/browser/static/js/utils.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
function report_error(message, info) {
|
||||||
|
|
||||||
|
text = '<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">\
|
||||||
|
<div class="panel panel-default">\
|
||||||
|
<div class="panel-heading" role="tab" id="headingOne">\
|
||||||
|
<h4 class="panel-title">\
|
||||||
|
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">\
|
||||||
|
Error message\
|
||||||
|
</a>\
|
||||||
|
</h4>\
|
||||||
|
</div>\
|
||||||
|
<div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">\
|
||||||
|
<div class="panel-body" style="overflow: scroll;">' + message + '</div>\
|
||||||
|
</div>\
|
||||||
|
</div>'
|
||||||
|
|
||||||
|
if (info != '') {
|
||||||
|
text += '<div class="panel panel-default">\
|
||||||
|
<div class="panel-heading" role="tab" id="headingTwo">\
|
||||||
|
<h4 class="panel-title">\
|
||||||
|
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">\
|
||||||
|
Additional info\
|
||||||
|
</a>\
|
||||||
|
</h4>\
|
||||||
|
</div>\
|
||||||
|
<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">\
|
||||||
|
<div class="panel-body" style="overflow: scroll;">' + info + '</div>\
|
||||||
|
</div>\
|
||||||
|
</div>\
|
||||||
|
</div>'
|
||||||
|
}
|
||||||
|
|
||||||
|
text += '</div>'
|
||||||
|
|
||||||
|
alertify.alert(
|
||||||
|
'An error has occurred',
|
||||||
|
text
|
||||||
|
)
|
||||||
|
}
|
@ -153,17 +153,18 @@ $('#dependents a').click(function (e) {
|
|||||||
|
|
||||||
// Syntax highlight the SQL Pane
|
// Syntax highlight the SQL Pane
|
||||||
var editor = CodeMirror.fromTextArea(document.getElementById("sql-textarea"), {
|
var editor = CodeMirror.fromTextArea(document.getElementById("sql-textarea"), {
|
||||||
lineNumbers: true,
|
lineNumbers: true,
|
||||||
mode: "text/x-sql",
|
mode: "text/x-sql",
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialise the treeview
|
// Initialise the treeview
|
||||||
$('#tree').aciTree({
|
$('#tree').aciTree({
|
||||||
ajax: {
|
ajax: {
|
||||||
url: '/static/tree.json'
|
url: '{{ url_for('browser.get_nodes') }}'
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
var treeApi = $('#tree').aciTree('api');
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -66,8 +66,4 @@
|
|||||||
{% include 'browser/body.html' %}
|
{% include 'browser/body.html' %}
|
||||||
{% include 'browser/messages.html' %}
|
{% include 'browser/messages.html' %}
|
||||||
|
|
||||||
<script>
|
|
||||||
{{ js_code|safe }}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
"""A blueprint module implementing the core pgAdmin browser."""
|
"""A blueprint module implementing the core pgAdmin browser."""
|
||||||
MODULE_NAME = 'browser'
|
MODULE_NAME = 'browser'
|
||||||
|
|
||||||
from flask import Blueprint, current_app, render_template, url_for
|
from flask import Blueprint, Response, current_app, render_template, url_for
|
||||||
from flaskext.gravatar import Gravatar
|
from flaskext.gravatar import Gravatar
|
||||||
from flask.ext.security import login_required
|
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 pgadmin import modules
|
from pgadmin import modules
|
||||||
from pgadmin.settings import get_setting
|
from pgadmin.settings import get_setting
|
||||||
|
|
||||||
@ -24,9 +25,6 @@ import config
|
|||||||
# 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='/' + MODULE_NAME)
|
||||||
|
|
||||||
##########################################################################
|
|
||||||
# A test page
|
|
||||||
##########################################################################
|
|
||||||
@blueprint.route("/")
|
@blueprint.route("/")
|
||||||
@login_required
|
@login_required
|
||||||
def index():
|
def index():
|
||||||
@ -47,42 +45,48 @@ def index():
|
|||||||
help_items = [ ]
|
help_items = [ ]
|
||||||
stylesheets = [ ]
|
stylesheets = [ ]
|
||||||
scripts = [ ]
|
scripts = [ ]
|
||||||
|
|
||||||
|
modules_and_nodes = modules + 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'))
|
||||||
stylesheets.append(url_for('browser.static', filename='css/browser.css'))
|
stylesheets.append(url_for('browser.static', filename='css/browser.css'))
|
||||||
stylesheets.append(url_for('browser.static', filename='css/aciTree/css/aciTree.css'))
|
stylesheets.append(url_for('browser.static', filename='css/aciTree/css/aciTree.css'))
|
||||||
|
stylesheets.append(url_for('browser.browser_css'))
|
||||||
|
|
||||||
# Add browser scripts
|
# Add browser scripts
|
||||||
scripts.append(url_for('static', filename='js/codemirror/codemirror.js'))
|
scripts.append(url_for('static', filename='js/codemirror/codemirror.js'))
|
||||||
scripts.append(url_for('static', filename='js/codemirror/mode/sql.js'))
|
scripts.append(url_for('static', filename='js/codemirror/mode/sql.js'))
|
||||||
|
scripts.append(url_for('browser.static', filename='js/utils.js'))
|
||||||
scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciPlugin.min.js'))
|
scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciPlugin.min.js'))
|
||||||
|
scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciTree.dom.js'))
|
||||||
scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciTree.min.js'))
|
scripts.append(url_for('browser.static', filename='js/aciTree/jquery.aciTree.min.js'))
|
||||||
|
scripts.append(url_for('browser.browser_js'))
|
||||||
|
|
||||||
for module in modules:
|
for module in modules_and_nodes:
|
||||||
# Get the edit menu items
|
# Get the edit menu items
|
||||||
if 'browser' in dir(module) and 'get_file_menu_items' in dir(module.browser):
|
if 'hooks' in dir(module) and 'get_file_menu_items' in dir(module.hooks):
|
||||||
file_items.extend(module.browser.get_file_menu_items())
|
file_items.extend(module.hooks.get_file_menu_items())
|
||||||
|
|
||||||
# Get the edit menu items
|
# Get the edit menu items
|
||||||
if 'browser' in dir(module) and 'get_edit_menu_items' in dir(module.browser):
|
if 'hooks' in dir(module) and 'get_edit_menu_items' in dir(module.hooks):
|
||||||
edit_items.extend(module.browser.get_edit_menu_items())
|
edit_items.extend(module.hooks.get_edit_menu_items())
|
||||||
|
|
||||||
# Get the tools menu items
|
# Get the tools menu items
|
||||||
if 'browser' in dir(module) and 'get_tools_menu_items' in dir(module.browser):
|
if 'hooks' in dir(module) and 'get_tools_menu_items' in dir(module.hooks):
|
||||||
tools_items.extend(module.browser.get_tools_menu_items())
|
tools_items.extend(module.hooks.get_tools_menu_items())
|
||||||
|
|
||||||
# Get the help menu items
|
# Get the help menu items
|
||||||
if 'browser' in dir(module) and 'get_help_menu_items' in dir(module.browser):
|
if 'hooks' in dir(module) and 'get_help_menu_items' in dir(module.hooks):
|
||||||
help_items.extend(module.browser.get_help_menu_items())
|
help_items.extend(module.hooks.get_help_menu_items())
|
||||||
|
|
||||||
# Get any stylesheets
|
# Get any stylesheets
|
||||||
if 'browser' in dir(module) and 'get_stylesheets' in dir(module.browser):
|
if 'hooks' in dir(module) and 'get_stylesheets' in dir(module.hooks):
|
||||||
stylesheets += module.browser.get_stylesheets()
|
stylesheets += module.hooks.get_stylesheets()
|
||||||
|
|
||||||
# Get any scripts
|
# Get any scripts
|
||||||
if 'browser' in dir(module) and 'get_scripts' in dir(module.browser):
|
if 'hooks' in dir(module) and 'get_scripts' in dir(module.hooks):
|
||||||
scripts += module.browser.get_scripts()
|
scripts += module.hooks.get_scripts()
|
||||||
|
|
||||||
file_items = sorted(file_items, key=lambda k: k['priority'])
|
file_items = sorted(file_items, key=lambda k: k['priority'])
|
||||||
edit_items = sorted(edit_items, key=lambda k: k['priority'])
|
edit_items = sorted(edit_items, key=lambda k: k['priority'])
|
||||||
@ -105,3 +109,61 @@ def index():
|
|||||||
stylesheets = stylesheets,
|
stylesheets = stylesheets,
|
||||||
scripts = scripts,
|
scripts = scripts,
|
||||||
layout_settings = layout_settings)
|
layout_settings = layout_settings)
|
||||||
|
|
||||||
|
@blueprint.route("/browser.js")
|
||||||
|
@login_required
|
||||||
|
def browser_js():
|
||||||
|
"""Render and return JS snippets from the nodes and modules."""
|
||||||
|
snippets = ''
|
||||||
|
modules_and_nodes = modules + nodes
|
||||||
|
|
||||||
|
for module in modules_and_nodes:
|
||||||
|
if 'hooks' in dir(module) and 'get_script_snippets' in dir(module.hooks):
|
||||||
|
snippets += module.hooks.get_script_snippets()
|
||||||
|
|
||||||
|
resp = Response(response=snippets,
|
||||||
|
status=200,
|
||||||
|
mimetype="application/javascript")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
@blueprint.route("/browser.css")
|
||||||
|
@login_required
|
||||||
|
def browser_css():
|
||||||
|
"""Render and return CSS snippets from the nodes and modules."""
|
||||||
|
snippets = ''
|
||||||
|
modules_and_nodes = modules + nodes
|
||||||
|
|
||||||
|
for module in modules_and_nodes:
|
||||||
|
if 'hooks' in dir(module) and 'get_css_snippets' in dir(module.hooks):
|
||||||
|
snippets += module.hooks.get_css_snippets()
|
||||||
|
|
||||||
|
resp = Response(response=snippets,
|
||||||
|
status=200,
|
||||||
|
mimetype="text/css")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
@blueprint.route("/root-nodes.json")
|
||||||
|
@login_required
|
||||||
|
def get_nodes():
|
||||||
|
"""Build a list of treeview nodes from the child modules."""
|
||||||
|
value = '['
|
||||||
|
|
||||||
|
for node in nodes:
|
||||||
|
if 'hooks' in dir(node) and 'get_nodes' in dir(node.hooks):
|
||||||
|
value += node.hooks.get_nodes() + ','
|
||||||
|
|
||||||
|
if value[-1:] == ',':
|
||||||
|
value = value[:-1]
|
||||||
|
|
||||||
|
value += ']'
|
||||||
|
|
||||||
|
resp = Response(response=value,
|
||||||
|
status=200,
|
||||||
|
mimetype="text/json")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -10,10 +10,12 @@
|
|||||||
"""Views for setting and storing configuration options."""
|
"""Views for setting and storing configuration options."""
|
||||||
MODULE_NAME = 'settings'
|
MODULE_NAME = 'settings'
|
||||||
|
|
||||||
import config
|
import traceback
|
||||||
from flask import Blueprint, Response, abort, request, render_template
|
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
|
||||||
|
from utils.ajax import make_json_result
|
||||||
from . import get_setting, store_setting
|
from . import get_setting, store_setting
|
||||||
|
|
||||||
# Initialise the module
|
# Initialise the module
|
||||||
@ -33,16 +35,30 @@ def script():
|
|||||||
def store(setting=None, value=None):
|
def store(setting=None, value=None):
|
||||||
"""Store a configuration setting, or if this is a POST request and a
|
"""Store a configuration setting, or if this is a POST request and a
|
||||||
count value is present, store multiple settings at once."""
|
count value is present, store multiple settings at once."""
|
||||||
if request.method == 'POST':
|
success = 1
|
||||||
if 'count' in request.form:
|
errorcode = 0
|
||||||
for x in range(int(request.form['count'])):
|
errormsg = ''
|
||||||
store_setting(request.form['setting%d' % (x+1)], request.form['value%d' % (x+1)])
|
|
||||||
else:
|
|
||||||
store_setting(request.form['setting'], request.form['value'])
|
|
||||||
else:
|
|
||||||
store_setting(setting, value)
|
|
||||||
|
|
||||||
return ''
|
try:
|
||||||
|
if request.method == 'POST':
|
||||||
|
if 'count' in request.form:
|
||||||
|
for x in range(int(request.form['count'])):
|
||||||
|
store_setting(request.form['setting%d' % (x+1)], request.form['value%d' % (x+1)])
|
||||||
|
else:
|
||||||
|
store_setting(request.form['setting'], request.form['value'])
|
||||||
|
else:
|
||||||
|
store_setting(setting, value)
|
||||||
|
except Exception as e:
|
||||||
|
success = 0
|
||||||
|
errormsg = e.message
|
||||||
|
|
||||||
|
value = make_json_result(success=success, errormsg=errormsg, info=traceback.format_exc(), result=request.form)
|
||||||
|
|
||||||
|
resp = Response(response=value,
|
||||||
|
status=200,
|
||||||
|
mimetype="text/json")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
@blueprint.route("/get", methods=['POST'])
|
@blueprint.route("/get", methods=['POST'])
|
||||||
@blueprint.route("/get/<setting>", methods=['GET'])
|
@blueprint.route("/get/<setting>", methods=['GET'])
|
||||||
@ -53,14 +69,21 @@ def get(setting=None, default=None):
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
setting = request.form['setting']
|
setting = request.form['setting']
|
||||||
default = request.form['default']
|
default = request.form['default']
|
||||||
|
|
||||||
|
success = 1
|
||||||
|
errorcode = 0
|
||||||
|
errormsg = ''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = get_setting(setting, default)
|
value = get_setting(setting, default)
|
||||||
except:
|
except Exception as e:
|
||||||
return ''
|
success = 0
|
||||||
|
errormsg = e.message
|
||||||
|
|
||||||
|
value = make_json_result(success=success, errormsg=errormsg, info=traceback.format_exc(), result=request.form)
|
||||||
|
|
||||||
resp = Response(response=value,
|
resp = Response(response=value,
|
||||||
status=200,
|
status=200,
|
||||||
mimetype="text/plain")
|
mimetype="text/json")
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alertify .ajs-content {
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* iFrames should have no border */
|
/* iFrames should have no border */
|
||||||
iframe {
|
iframe {
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
@ -30,6 +35,13 @@ iframe {
|
|||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-servers {
|
/* Alert info panel */
|
||||||
background: url('/static/servers.png') 0 0 no-repeat !important;
|
.alert-info-panel {
|
||||||
}
|
border: 2px solid #a1a1a1;
|
||||||
|
margin-top: 2em;
|
||||||
|
padding: 5px 5px;
|
||||||
|
background: #dddddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
height: 8em;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
0
web/utils/__init__.py
Normal file
0
web/utils/__init__.py
Normal file
24
web/utils/ajax.py
Normal file
24
web/utils/ajax.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2015, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Utility functions for dealing with AJAX."""
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
def make_json_result(success=1, errormsg='', info='', result={}, data={}):
|
||||||
|
"""Create a JSON response document describing the results of a request and
|
||||||
|
containing the data."""
|
||||||
|
doc = { }
|
||||||
|
doc['success'] = success
|
||||||
|
doc['errormsg'] = errormsg
|
||||||
|
doc['info'] = info
|
||||||
|
doc['result'] = result
|
||||||
|
doc['data'] = data
|
||||||
|
|
||||||
|
return json.dumps(doc)
|
Loading…
Reference in New Issue
Block a user