Hi Dave/Ronan,
On Mon, Apr 20, 2015 at 4:10 PM, Dave Page <[email protected]> wrote:
> On Mon, Apr 20, 2015 at 10:52 AM, Ronan Dunklau
> <[email protected]> wrote:
> >> Ronan; can you update the test, help and about modules as well please?
> >
> > Done, please find attached a new patch for that. Ashesh, once you're
> done with
> > what you are doing now, feel free to ask me for any help needed to
> integrate
> > this after the fact.
>
> Thanks.
>
Thanks - It looks good to me.
(And, attached patch is based on that.)
>
> >> > snippets of javsacript generated by the server. I feel like this
> apporach
> >> > is extremely fragile. Even before the patch, most of the tree actions
> >> > were not working properly.
> >>
> >> That's odd - they all worked for me
> >
> > Adding a server is not functional, as well as adding a server group.
>
> Server groups should be fully functional. Adding a server isn't -
> that's what Ashesh is investigating backbone.js for.
>
It is now fully functional as it was earlier with the attached patch.
I am still working on the backbone.js.
I am trying to make it general, so that - we can fit it in both properties
pane, and dialog both together.
In order to achieve, I have made a class NodeView (inherited from flask's
view), just like the MethodView.
Flask's MethodView is good to achieve CRUD functionality.
Browser Tree Node (PostgreSQL object) requires more than just CRUD.
i.e.
- CRUD (Create, Read, Update & Delete)
- Reversed Engineered SQL for the object
- Modified Query in edit mode
i.e. ALTER TABLE ...
- Statistics
- List of dependents
- List of dependencies
- Children node list
This class can be inherited to achieve the different routes for each of the
object types/collections.
OPERATION | URL | Method
---------------+------------------------+--------
List | /obj/[Parent URL]/ | GET
Properties | /obj/[Parent URL]/id | GET
Create | /obj/[Parent URL]/ | POST
Delete | /obj/[Parent URL]/id | DELETE
Update | /obj/[Parent URL]/id | PUT
SQL (Reversed | /sql/[Parent URL]/id | GET
Engineering) |
SQL (Modified | /sql/[Parent URL]/id | POST
Properties) |
Statistics | /stats/[Parent URL]/id | GET
Dependencies | /deps/[Parent URL]/id | GET
Dependents | /deps/[Parent URL]/id | POST
Children Nodes | /nodes/[Parent URL]/id | GET
NOTE:
Parent URL can be seen as the path to identify the particular node.
i.e.
In order to identify the TABLE object, we requires information about
the server -> database -> schema objects.
Hence, the Parent URL for the TABLE object will be something like this
as below:
<int:sid>/<str:database>/<str:schema>
I already did that for ServerGroup, and Server nodes.
Attached patch is still in work in progress, and based on Ranon's latest
patch.
(So - in order to apply my patch, you should apply Ronan's latest patch
first, and then mine.)
--
Thanks & Regards,
Ashesh Vashi
EnterpriseDB INDIA: Enterprise PostgreSQL Company
<http://www.enterprisedb.com>
*http://www.linkedin.com/in/asheshvashi*
<http://www.linkedin.com/in/asheshvashi>
> >> > noticed) feel once again not really robust. All this widget assembly
> is
> >> > done "ad-hoc".
> >>
> >> How would you expect it to be done?
> >
> > In my opinion, it should either be done by using a set of widgets already
> > designed to work together (think of wxwidgets, but for the web), using
> one of
> > the frameworks I mentioned before. Or alternatively, by developing the
> glue
> > between those widgets ourselves, using something like Backbone to wrap
> those
> > libraries into nice views able to play together.
>
> The problem is that I haven't found any OSS frameworks that provide
> anything like the capabilities we have by using ad-hoc components.
> There is nothing at all that comes close to the functionality (and
> look/feel) of wcDocker, CodeMirror, AlertifyJS and aciTree that I've
> found, let alone in a single framework. I've spent a *lot* of time
> researching that, and trying to find components that give us what
> we're going to need.
>
> > +1 for that. As for the extensibility, how is it expected for someone to
> > provide a plugin ? Should he write a module that is supposed to be
> installed
> > in the pgadmin directory directly ? Using the modular approach proposed
> by
> > distutils/setuptools ? Plugins seems to be installed into the pgadmin
> package
> > directly, which is maybe not the most convenient way to manage
> third-party
> > modules.
>
> The current plugin mechanism is documented, but the basic premise is
> that you can add a new module or node by dropping a Python package in
> the right directory, without having to edit any configuration or code.
> That is particularly important for tree nodes where the directory
> structure is used to define the tree structure, to avoid having parent
> nodes needing to have any pre-knowledge of what their children will
> be.
>
> If you have better ideas of how to do that, I'm happy to hear them. I
> do need to avoid long, drawn out discussions and rewrites though; I
> can only justify putting significant EDB resources into the project if
> we continue to move forwards at a reasonable speed.
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
diff --git a/web/pgAdmin4.py b/web/pgAdmin4.py
index 9d2cff2..237cb32 100644
--- a/web/pgAdmin4.py
+++ b/web/pgAdmin4.py
@@ -50,8 +50,8 @@ if not os.path.isfile(config.SQLITE_PATH):
# Create the app!
app = create_app()
-#if config.DEBUG:
-# app.debug = True
+if config.DEBUG:
+ app.debug = True
# 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
diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py
index e340c83..ae42104 100644
--- a/web/pgadmin/browser/__init__.py
+++ b/web/pgadmin/browser/__init__.py
@@ -21,25 +21,23 @@ MODULE_NAME = 'browser'
class BrowserModule(PgAdminModule):
-
def get_own_stylesheets(self):
stylesheets = []
# Add browser stylesheets
for (endpoint, filename) in [
('static', 'css/codemirror/codemirror.css'),
- ('static', 'css/wcDocker/theme.css'),
('static', 'css/jQuery-contextMenu/jquery.contextMenu.css'),
- ('browser.static', 'css/browser.css'),
- ('browser.static', 'css/aciTree/css/aciTree.css')
+ ('static', 'css/wcDocker/wcDockerSkeleton.css' if \
+ current_app.debug else \
+ 'css/wcDocker/wcDockerSkeleton.min.css'),
+ ('static', 'css/wcDocker/theme.css'),
+ ('browser.static', 'css/aciTree/css/aciTree.css'),
]:
stylesheets.append(url_for(endpoint, filename=filename))
stylesheets.append(url_for('browser.browser_css'))
- if current_app.debug:
- stylesheets.append(url_for('static', filename='css/wcDocker/wcDockerSkeleton.css'))
- else:
- stylesheets.append(url_for('static', filename='css/wcDocker/wcDockerSkeleton.min.css'))
return stylesheets
+
def get_own_javascripts(self):
scripts = []
for (endpoint, filename) in [
@@ -74,7 +72,7 @@ class BrowserPluginModule(PgAdminModule):
def __init__(self, import_name, **kwargs):
kwargs.setdefault("url_prefix", self.node_path)
- kwargs.setdefault("static_url_path", '')
+ kwargs.setdefault("static_url_path", 'static')
super(BrowserPluginModule, self).__init__("NODE-%s" % self.node_type,
import_name,
**kwargs)
@@ -95,8 +93,8 @@ class BrowserPluginModule(PgAdminModule):
Returns a snippet of css to include in the page
"""
# TODO: move those methods to BrowserModule subclass ?
- return render_template("browser/css/node.css",
- node_type=self.node_type)
+ return [render_template("browser/css/node.css",
+ node_type=self.node_type)]
@abstractmethod
def get_nodes(self):
@@ -137,11 +135,12 @@ def browser_js():
snippets = []
for submodule in current_blueprint.submodules:
snippets.extend(submodule.jssnippets)
- return make_response(render_template(
- 'browser/js/browser.js',
- layout=layout,
- jssnippets=snippets),
- 200, {'Content-Type': 'application/x-javascript'})
+ return make_response(
+ render_template(
+ 'browser/js/browser.js',
+ layout=layout,
+ jssnippets=snippets),
+ 200, {'Content-Type': 'application/x-javascript'})
@blueprint.route("/browser.css")
@login_required
@@ -150,9 +149,9 @@ def browser_css():
snippets = []
for submodule in current_blueprint.submodules:
snippets.extend(submodule.csssnippets)
- return make_response(render_template('browser/css/browser.css',
- snippets=snippets),
- 200, {'Content-Type': 'text/css'})
+ return make_response(
+ render_template('browser/css/browser.css', snippets=snippets),
+ 200, {'Content-Type': 'text/css'})
@blueprint.route("/nodes/")
diff --git a/web/pgadmin/browser/server_groups/__init__.py b/web/pgadmin/browser/server_groups/__init__.py
index bfcc7f3..b5a4167 100644
--- a/web/pgadmin/browser/server_groups/__init__.py
+++ b/web/pgadmin/browser/server_groups/__init__.py
@@ -18,10 +18,10 @@ from pgadmin.utils.ajax import make_json_response
from pgadmin.browser import BrowserPluginModule
from pgadmin.utils.menu import MenuItem
from pgadmin.settings.settings_model import db, ServerGroup
+from pgadmin.browser.utils import generate_browser_node
import config
-
class ServerGroupModule(BrowserPluginModule):
NODE_TYPE = "server-group"
@@ -65,18 +65,20 @@ class ServerGroupModule(BrowserPluginModule):
# TODO: Move this JSON generation to a Server method
# this code is duplicated somewhere else
for group in groups:
- yield {
- "id": "%s/%d" % (self.node_type, group.id),
- "label": group.name,
- "icon": "icon-%s" % self.node_type,
- "inode": True,
- "_type": self.node_type
- }
+ yield generate_browser_node(
+ "%d" % (group.id),
+ group.name,
+ "icon-%s" % self.node_type,
+ True,
+ self.node_type)
@property
def node_type(self):
return self.NODE_TYPE
+ @property
+ def node_path(self):
+ return '/browser/' + self.node_type
class ServerGroupMenuItem(MenuItem):
@@ -99,109 +101,142 @@ class ServerGroupPluginModule(BrowserPluginModule):
pass
-# Initialise the module
+ @property
+ def node_path(self):
+ return '/browser/' + self.node_type
+
+
blueprint = ServerGroupModule( __name__, static_url_path='')
[email protected]("/<server_group>")
-@login_required
-def get_nodes(server_group):
- """Build a list of treeview nodes from the child nodes."""
- nodes = []
- for module in current_blueprint.submodules:
- nodes.extend(module.get_nodes(server_group=server_group))
- return make_json_response(data=nodes)
-
-
[email protected]('/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 = gettext('No server group name was specified')
-
- if success == 1:
- data['id'] = servergroup.id
- data['name'] = servergroup.name
-
- return make_json_response(success=success,
- errormsg=errormsg,
- info=traceback.format_exc(),
- result=request.form,
- data=data)
-
[email protected]('/delete/', methods=['POST'])
-@login_required
-def delete():
- """Delete a server group node in the settings database"""
- success = 1
- errormsg = ''
-
- if request.form['id'] != '':
+# Initialise the module
+from pgadmin.browser.utils import NodeView
+
+
+class ServerGroupView(NodeView):
+
+ node_type = ServerGroupModule.NODE_TYPE
+ parent_ids = []
+ ids = [{'type':'int', 'id':'gid'}]
+
+
+ def list(self):
+ res = []
+ for g in blueprint.get_nodes():
+ res.append(g)
+ return make_json_response(result=res)
+
+
+ def delete(self, gid):
+ """Delete a server group node in the settings database"""
+
# There can be only one record at most
- servergroup = ServerGroup.query.filter_by(user_id=current_user.id, id=int(request.form['id'])).first()
+ servergroup = ServerGroup.query.filter_by(
+ user_id=current_user.id,
+ id=gid)
if servergroup is None:
- success = 0
- errormsg = gettext('The specified server group could not be found.')
+ return make_json_response(
+ success=0,
+ errormsg=gettext('The specified server group could not be found.'))
else:
try:
db.session.delete(servergroup)
db.session.commit()
except Exception as e:
- success = 0
- errormsg = e.message
+ return make_json_response(success=0, errormsg=e.message)
- else:
- success = 0
- errormsg = gettext('No server group was specified.')
+ return make_json_response(result=request.form)
- return make_json_response(success=success,
- errormsg=errormsg,
- info=traceback.format_exc(),
- result=request.form)
[email protected]('/rename/', methods=['POST'])
-@login_required
-def rename():
- """Rename a server group node in the settings database"""
- success = 1
- errormsg = ''
+ def update(self, gid):
+ """Update the server-group properties"""
- if request.form['id'] != '':
# There can be only one record at most
- servergroup = ServerGroup.query.filter_by(user_id=current_user.id, id=int(request.form['id'])).first()
+ servergroup = ServerGroup.query.filter_by(
+ user_id=current_user.id,
+ id=gid).first()
if servergroup is None:
- success = 0
- errormsg = gettext('The specified server group could not be found.')
+ return make_json_response(
+ success=0,
+ errormsg=gettext('The specified server group could not be found.'))
else:
try:
- servergroup.name = request.form['name']
+ if 'name' in request.form:
+ servergroup.name = request.form['name']
db.session.commit()
except Exception as e:
- success = 0
- errormsg = e.message
+ return make_json_response(success=0, errormsg=e.message)
- else:
- success = 0
- errormsg = gettext('No server group was specified.')
+ return make_json_response(result=request.form)
- return make_json_response(success=success,
- errormsg=errormsg,
- info=traceback.format_exc(),
- result=request.form)
+
+ def properties(self, gid):
+ """Update the server-group properties"""
+
+ # There can be only one record at most
+ sg = ServerGroup.query.filter_by(
+ user_id=current_user.id,
+ id=gid).first()
+ data = {}
+
+ if sg is None:
+ return make_json_response(
+ success=0,
+ errormsg=gettext('The specified server group could not be found.'))
+ else:
+ return make_json_response(data={'id': sg.id, 'name': sg.name})
+
+
+ def create(self):
+ data = []
+ if request.form['name'] != '':
+ servergroup = ServerGroup(
+ user_id=current_user.id,
+ name=request.form['name'])
+ try:
+ db.session.add(servergroup)
+ db.session.commit()
+
+ data['id'] = servergroup.id
+ data['name'] = servergroup.name
+ except Exception as e:
+ return make_json_response(success=0, errormsg=e.message)
+
+ else:
+ return make_json_response(
+ success=0,
+ errormsg=gettext('No server group name was specified'))
+
+ return make_json_response(data=data)
+
+
+ def nodes(self, gid):
+ """Build a list of treeview nodes from the child nodes."""
+ nodes = []
+ for module in blueprint.submodules:
+ nodes.extend(module.get_nodes(server_group=gid))
+ return make_json_response(data=nodes)
+
+
+ def sql(self, gid):
+ return make_json_response(data='')
+
+
+ def modified_sql(self, gid):
+ return make_json_response(data='')
+
+
+ def statistics(self, gid):
+ return make_json_response(data='')
+
+
+ def dependencies(self, gid):
+ return make_json_response(data='')
+
+
+ def dependents(self, gid):
+ return make_json_response(data='')
+
+
+ServerGroupView.register_node_view(blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py
index 855bb19..68e501c 100644
--- a/web/pgadmin/browser/server_groups/servers/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/__init__.py
@@ -9,9 +9,10 @@
from flask import render_template, request
from pgadmin.browser.server_groups import ServerGroupPluginModule
from flask.ext.security import login_required, current_user
-from pgadmin.settings.settings_model import db, Server
+from pgadmin.settings.settings_model import db, Server, ServerGroup
from pgadmin.utils.menu import MenuItem
from pgadmin.utils.ajax import make_json_response
+from pgadmin.browser.utils import generate_browser_node, NodeView
import traceback
from flask.ext.babel import gettext
@@ -30,13 +31,13 @@ class ServerModule(ServerGroupPluginModule):
# TODO: Move this JSON generation to a Server method
for server in servers:
- yield {
- "id": "%s/%d" % (NODE_TYPE, server.id),
- "label": server.name,
- "icon": "icon-%s" % NODE_TYPE,
- "inode": True,
- "_type": NODE_TYPE
- }
+ yield generate_browser_node(
+ "%d" % server.id,
+ server.name,
+ "icon-%s" % self.NODE_TYPE,
+ True,
+ self.NODE_TYPE
+ )
def get_own_menuitems(self):
return {
@@ -49,13 +50,13 @@ class ServerModule(ServerGroupPluginModule):
name="create_server",
label=gettext('Server...'),
priority=50,
- function='create_server')
+ function='create_server(item)')
],
'context_items': [
ServerMenuItem(name='delete_server',
label=gettext('Delete server'),
priority=50,
- onclick='drop_server'),
+ onclick='drop_server(item)'),
ServerMenuItem(name='rename_server',
label=gettext('Rename server...'),
priority=60,
@@ -75,98 +76,224 @@ class ServerMenuItem(MenuItem):
kwargs.setdefault("type", ServerModule.NODE_TYPE)
super(ServerMenuItem, self).__init__(**kwargs)
+
blueprint = ServerModule(__name__)
[email protected]('/add/', methods=['POST'])
-@login_required
-def add():
- """Add a server node to the settings database"""
- success = 1
- errormsg = ''
- data = {}
-
- success = False
- errormsg = ''
- if request.form['name'] != '':
- server = Server(user_id=current_user.id, name=request.form['name'])
- try:
- db.session.add(server)
- db.session.commit()
- success = True
- except Exception as e:
- errormsg = e.message
- else:
- errormsg = gettext('No server name was specified')
-
- if success:
- 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)
-
[email protected]('/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()
+class ServerNode(NodeView):
+
+ node_type = ServerModule.NODE_TYPE
+ parent_ids = [{'type':'int', 'id':'gid'}]
+ ids = [{'type':'int', 'id':'sid'}]
+
+
+ def list(self, gid):
+ res = []
+ """Return a JSON document listing the server groups for the user"""
+ servers = Server.query.filter_by(user_id=current_user.id,
+ servergroup_id=gid)
+
+ for server in servers:
+ res.append(
+ generate_browser_node(
+ "%d/%d" % (gid, server.id),
+ server.name,
+ "icon-%s" % NODE_TYPE,
+ True,
+ NODE_TYPE
+ )
+ )
+ return make_json_response(result=res)
+
+
+ def delete(self, gid, sid):
+ """Delete a server node in the settings database"""
+ server = Server.query.filter_by(user_id=current_user.id, id=sid)
+
+ # TODO:: A server, which is connected, can not be deleted
if server is None:
- success = 0
- errormsg = gettext('The specified server could not be found.')
+ return make_json_response(
+ success=0,
+ errormsg=gettext(
+ 'The specified server could not be found.\n'
+ 'Does the user have permission to access the '
+ 'server?'
+ )
+ )
else:
try:
db.session.delete(server)
db.session.commit()
except Exception as e:
- success = 0
- errormsg = e.message
+ return make_json_response(
+ 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())
- return make_json_response(success=success,
- errormsg=errormsg,
- info=traceback.format_exc(),
- result=request.form)
[email protected]('/rename/', methods=['POST'])
-@login_required
-def rename():
- """Rename a server node in the settings database"""
- success = 1
- errormsg = ''
+ def update(self, gid, sid):
+ """Update the server settings"""
+ server = Server.query.filter_by(user_id=current_user.id, id=sid).first()
- 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:
+ return make_json_response(
+ success=0,
+ errormsg=gettext("Couldn't find the given server.")
+ )
+
+ # TODO::
+ # Not all parameters can be modified, while the server is connected
+ possible_args = {
+ 'name': 'name',
+ 'host': 'host',
+ 'port': 'port',
+ 'db': 'maintenance_db',
+ 'username': 'username',
+ 'sslmode': 'sslmode',
+ 'gid': 'servergroup_id'
+ }
+
+ idx = 0
+ for arg in possible_args:
+ if arg in request.form:
+ server[possible_args[arg]] = request.form[arg]
+ idx += 1
+
+ if idx == 0:
+ return make_json_response(
+ success=0,
+ errormsg=gettext('No parameters were chagned!')
+ )
+
+ try:
+ db.session.commit()
+ except Exception as e:
+ return make_json_response(
+ success=0,
+ errormsg=e.message
+ )
+
+ return make_json_response(
+ success=1,
+ data={
+ 'id': server.id,
+ 'gid': server.servergroup_id
+ }
+ )
+
+
+ def properties(self, gid, sid):
+ """Return list of attributes of a server"""
+ server = Server.query.filter_by(
+ user_id=current_user.id,
+ id=sid).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)
+ return make_json_response(
+ success=0,
+ errormsg=gettext("Couldn't find the given server")
+ )
+
+ sg = ServerGroup.query.filter_by(
+ user_id=current_user.id,
+ id=server.servergroup_id
+ ).first()
+
+ return make_json_response(
+ success=1,
+ data={
+ 'id':server.id,
+ 'name':server.name,
+ 'host':server.host,
+ 'port':server.port,
+ 'db':server.maintenance_db,
+ 'username':server.username,
+ 'gid':server.servergroup_id,
+ 'group-name':sg.name
+ }
+ )
+
+
+ def create(self, gid):
+ """Add a server node to the settings database"""
+ required_args = [
+ 'name',
+ 'host',
+ 'port',
+ 'db',
+ 'username',
+ 'sslmode'
+ ]
+
+ for arg in required_args:
+ if arg not in request.form:
+ return make_json_response(
+ success=0,
+ errormsg=gettext(
+ "Couldn't find the required parameter (%s)." % arg
+ )
+ )
+
+ server = Server(
+ user_id=current_user.id,
+ servergroup_id=gid,
+ name=request.form['name'],
+ host=request.form['host'],
+ port=request.form['port'],
+ maintenance_db=request.form['db'],
+ username=request.form['username'],
+ sslmode=request.form['username']
+ )
+
+ try:
+ db.session.add(server)
+ db.session.commit()
+ except Exception as e:
+ return make_json_response(
+ success=0,
+ errormsg=e.message
+ )
+
+ return make_json_response(success=1,
+ data={
+ 'id': server.id,
+ 'name': server.name,
+ 'gid': gid
+ })
+
+
+ def nodes(self, gid, sid):
+ """Build a list of treeview nodes from the child nodes."""
+ nodes = []
+ # TODO::
+ # We can have nodes for the server object, only when
+ # the server is connected at the moment.
+ for module in blueprint.submodules:
+ nodes.extend(module.get_nodes(server=sid))
+ return make_json_response(data=nodes)
+
+
+ def sql(self, gid, sid):
+ return make_json_response(data='')
+
+
+ def modified_sql(self, gid, sid):
+ return make_json_response(data='')
+
+
+ def statistics(self, gid, sid):
+ return make_json_response(data='')
+
+
+ def dependencies(self, gid, sid):
+ return make_json_response(data='')
+
+
+ def dependents(self, gid, sid):
+ return make_json_response(data='')
+
+ServerNode.register_node_view(blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js b/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js
index 822441d..5361229 100644
--- a/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js
+++ b/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js
@@ -1,11 +1,18 @@
// Add a server
-function create_server() {
+function create_server(item) {
var alert = alertify.prompt(
'{{ _('Create a server') }}',
'{{ _('Enter a name for the new server') }}',
'',
function(evt, value) {
- $.post("{{ url_for('NODE-server.add') }}", { name: value })
+ var d = tree.itemData(item);
+ if (d._type != 'server-group') {
+ d = tree.itemData(tree.parent(item));
+ }
+ $.post(
+ "{{ url_for('browser.index') }}server/obj/" + d.refid + '/',
+ { name: value }
+ )
.done(function(data) {
if (data.success == 0) {
report_error(data.errormsg, data.info);
@@ -38,8 +45,10 @@ function drop_server(item) {
'{{ _('Are you sure you wish to drop the server "{0}"?') }}'.replace('{0}', tree.getLabel(item)),
function() {
var id = tree.getId(item).split('/').pop()
- $.post("{{ url_for('NODE-server.delete') }}", { id: id })
- .done(function(data) {
+ $.ajax({
+ url:"{{ url_for('browser.index') }}" + d._type + "/obj/" + d.refid,
+ type:'DELETE',
+ success: function(data) {
if (data.success == 0) {
report_error(data.errormsg, data.info);
} else {
@@ -53,7 +62,7 @@ function drop_server(item) {
}
}
}
- )
+ })
},
null
)
@@ -66,17 +75,20 @@ function rename_server(item) {
'{{ _('Enter a new name for the server') }}',
tree.getLabel(item),
function(evt, value) {
- var id = tree.getId(item).split('/').pop()
- $.post("{{ url_for('NODE-server.rename') }}", { id: id, name: value })
- .done(function(data) {
+ var d = tree.itemData(item);
+ $.ajax({
+ url:"{{ url_for('browser.index') }}" + d._type + "/obj/" + d.refid,
+ type:'PUT',
+ params: {name: value},
+ success: function(data) {
if (data.success == 0) {
report_error(data.errormsg, data.info);
} else {
tree.setLabel(item, { label: value });
}
}
- )
+ })
},
null
)
-}
\ No newline at end of file
+}
diff --git a/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js b/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js
index f1fa85d..a154012 100644
--- a/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js
+++ b/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js
@@ -5,7 +5,7 @@ function create_server_group() {
'{{ _('Enter a name for the new server group') }}',
'',
function(evt, value) {
- $.post("{{ url_for('NODE-server-group.add') }}", { name: value })
+ $.post("{{ url_for('browser.index') }}server-group/obj/", { name: value })
.done(function(data) {
if (data.success == 0) {
report_error(data.errormsg, data.info);
@@ -37,9 +37,11 @@ function drop_server_group(item) {
'{{ _('Delete server group?') }}',
'{{ _('Are you sure you wish to delete the server group "{0}"?') }}'.replace('{0}', tree.getLabel(item)),
function() {
- var id = tree.getId(item).split('/').pop()
- $.post("{{ url_for('NODE-server-group.delete') }}", { id: id })
- .done(function(data) {
+ var d = tree.itemData(item);
+ $.ajax({
+ url:"{{ url_for('browser.index') }}" + d._type + "/obj/" + d.refid,
+ type:'DELETE',
+ success: function(data) {
if (data.success == 0) {
report_error(data.errormsg, data.info);
} else {
@@ -53,7 +55,7 @@ function drop_server_group(item) {
}
}
}
- )
+ })
},
null
)
@@ -66,16 +68,19 @@ function rename_server_group(item) {
'{{ _('Enter a new name for the server group') }}',
tree.getLabel(item),
function(evt, value) {
- var id = tree.getId(item).split('/').pop()
- $.post("{{ url_for('NODE-server-group.rename') }}", { id: id, name: value })
- .done(function(data) {
+ var d = tree.itemData(item);
+ $.ajax({
+ url:"{{ url_for('browser.index') }}" + d._type + "/obj/" + d.refid,
+ type:'PUT',
+ params: { name: value },
+ success: function(data) {
if (data.success == 0) {
report_error(data.errormsg, data.info);
} else {
tree.setLabel(item, { label: value });
}
}
- )
+ })
},
null
)
diff --git a/web/pgadmin/browser/templates/browser/css/node.css b/web/pgadmin/browser/templates/browser/css/node.css
index 3fea074..da56d69 100644
--- a/web/pgadmin/browser/templates/browser/css/node.css
+++ b/web/pgadmin/browser/templates/browser/css/node.css
@@ -1,3 +1,3 @@
.icon-{{node_type}} {
- background: url('{{ url_for('NODE-%s.static' % node_type, filename='img/%s.png' % node_type )}}') 0 0 no-repeat;
+ background-image: url('{{ url_for('NODE-%s.static' % node_type, filename='img/%s.png' % node_type )}}') !important;
}
diff --git a/web/pgadmin/browser/templates/browser/js/browser.js b/web/pgadmin/browser/templates/browser/js/browser.js
index e1aa05b..dbdf034 100644
--- a/web/pgadmin/browser/templates/browser/js/browser.js
+++ b/web/pgadmin/browser/templates/browser/js/browser.js
@@ -298,6 +298,12 @@ ALTER TABLE tickets_detail \n\
return $.parseJSON(payload).data;
}
}
+ },
+ ajaxHook: function(item, settings) {
+ if (item != null) {
+ var d = this.itemData(item);
+ settings.url = '{{ url_for('browser.index') }}' + d._type + '/nodes/' + d.refid
+ }
}
});
tree = $('#tree').aciTree('api');
diff --git a/web/pgadmin/settings/settings_model.py b/web/pgadmin/settings/settings_model.py
index 731137b..dcd6fb6 100644
--- a/web/pgadmin/settings/settings_model.py
+++ b/web/pgadmin/settings/settings_model.py
@@ -72,13 +72,28 @@ class Server(db.Model):
"""Define a registered Postgres server"""
__tablename__ = 'server'
id = db.Column(db.Integer, primary_key=True)
- user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
- servergroup_id = db.Column(db.Integer, db.ForeignKey('servergroup.id'), nullable=False)
+ user_id = db.Column(
+ db.Integer,
+ db.ForeignKey('user.id'),
+ nullable=False
+ )
+ servergroup_id = db.Column(
+ db.Integer,
+ db.ForeignKey('servergroup.id'),
+ nullable=False
+ )
name = db.Column(db.String(128), nullable=False)
host = db.Column(db.String(128), nullable=False)
- port = db.Column(db.Integer(), db.CheckConstraint('port >= 1024 AND port <= 65534'), nullable=False)
+ port = db.Column(
+ db.Integer(),
+ db.CheckConstraint('port >= 1024 AND port <= 65534'),
+ nullable=False)
maintenance_db = db.Column(db.String(64), nullable=False)
username = db.Column(db.String(64), nullable=False)
- ssl_mode = db.Column(db.String(16), nullable=False)
-
-
+ ssl_mode = db.Column(
+ db.String(16),
+ db.CheckConstraint(
+ "ssl_mode IN ('allow', 'prefer', 'require', 'disable', 'verify-ca', 'verify-full')"
+ ),
+ nullable=False,
+ )
diff --git a/web/pgadmin/templates/base.html b/web/pgadmin/templates/base.html
index 5a36182..300e888 100755
--- a/web/pgadmin/templates/base.html
+++ b/web/pgadmin/templates/base.html
@@ -15,25 +15,25 @@
<meta name="dcterms.dateCopyrighted" content="2014 - 2015">
<!-- Base template stylesheets -->
- {% if config.DEBUG %}<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css') }}" />{% else %}<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}" />{% endif %}
- {% if config.DEBUG %}<link rel="stylesheet" href="{{ url_for('static', filename='css/alertifyjs/alertify.css') }}" />{% else %}<link rel="stylesheet" href="{{ url_for('static', filename='css/alertifyjs/alertify.min.css') }}" />{% endif %}
- {% if config.DEBUG %}<link rel="stylesheet" href="{{ url_for('static', filename='css/alertifyjs/themes/bootstrap.css') }}" />{% else %}<link rel="stylesheet" href="{{ url_for('static', filename='css/alertifyjs/themes/bootstrap.min.css') }}" />{% endif %}
- {% if config.DEBUG %}<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-theme.min.css') }}">{% else %}<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-theme.min.css') }}">{% endif %}
- <link rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css') }}">
+ <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css' if config.DEBUG else 'css/bootstrap.min.css')}}"/>
+ <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/alertifyjs/alertify.css' if config.DEBUG else 'css/alertifyjs/alertify.min.css') }}" />
+ <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/alertifyjs/themes/bootstrap.css' if config.DEBUG else 'css/alertifyjs/themes/bootstrap.min.css') }}" />
+ <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-theme.min.css' if config.DEBUG else 'css/bootstrap-theme.css') }}">
+ <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/overrides.css') }}">
<!-- View specified stylesheets -->
{% for stylesheet in current_app.stylesheets %}
- <link rel="stylesheet" href="{{ stylesheet }}">
+ <link type="text/css" rel="stylesheet" href="{{ stylesheet }}">
{% endfor %}
<!-- Base template scripts -->
- <script src="{{ url_for('static', filename='js/modernizr-2.6.2-respond-1.1.0.min.js') }}"></script>
- {% if config.DEBUG %}<script src="{{ url_for('static', filename='js/jquery-1.11.2.js') }}">{% else %}<script src="{{ url_for('static', filename='js/jquery-1.11.2.min.js') }}">{% endif %}</script>
- {% if config.DEBUG %}<script src="{{ url_for('static', filename='js/bootstrap.js') }}">{% else %}<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}">{% endif %}</script>
- {% if config.DEBUG %}<script src="{{ url_for('static', filename='js/alertifyjs/alertify.js') }}">{% else %}<script src="{{ url_for('static', filename='js/alertifyjs/alertify.min.js') }}">{% endif %}</script>
- <script src="{{ url_for('static', filename='js/alertifyjs/pgadmin.defaults.js') }}"></script>
+ <script type="text/javascript" src="{{ url_for('static', filename='js/modernizr-2.6.2-respond-1.1.0.min.js') }}"></script>
+ <script type="text/javascript" src="{{ url_for('static', filename='js/jquery-1.11.2.js' if config.DEBUG else 'js/jquery-1.11.2.min.js') }}"></script>
+ <script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap.js' if config.DEBUG else 'js/bootstrap.min.js') }}"></script>
+ <script type="text/javascript" src="{{ url_for('static', filename='js/alertifyjs/alertify.js' if config.DEBUG else 'js/alertifyjs/alertify.min.js') }}"></script>
+ <script type="text/javascript" src="{{ url_for('static', filename='js/alertifyjs/pgadmin.defaults.js') }}"></script>
<!-- View specified scripts -->
{% for script in current_app.javascripts %}
- <script src="{{ script }}"></script>
+ <script type="text/javascript" src="{{ script }}"></script>
{% endfor %}
</head>
<body>
diff --git a/web/pgadmin/utils/ajax.py b/web/pgadmin/utils/ajax.py
index 367c356..b5f938c 100644
--- a/web/pgadmin/utils/ajax.py
+++ b/web/pgadmin/utils/ajax.py
@@ -25,4 +25,4 @@ def make_json_response(success=1, errormsg='', info='', result={}, data={}):
response = Response(response=json.dumps(doc),
status=200,
mimetype="text/json")
- return response
\ No newline at end of file
+ return response
diff --git a/web/setup.py b/web/setup.py
index c7398f5..22fbf24 100644
--- a/web/setup.py
+++ b/web/setup.py
@@ -66,6 +66,19 @@ def do_setup():
server_group = ServerGroup(user_id=user.id, name="Servers")
db.session.merge(server_group)
+ # TODO:: Remove this server later
+ # It is here to demo the server listing is workig in
+ # browser tree.
+ server_group = ServerGroup.query.filter_by(name='Servers').first()
+
+ server = Server(
+ user_id=user.id, servergroup_id=server_group.id,
+ name='PostgreSQL 9.3', host='localhost', port=3930,
+ maintenance_db='postgres', username='asheshvashi',
+ ssl_mode='prefer'
+ )
+ db.session.merge(server)
+
# Set the schema version
version = Version(name='ConfigDB', value=config.SETTINGS_SCHEMA_VERSION)
db.session.merge(version)
@@ -138,4 +151,4 @@ if os.path.isfile(config.SQLITE_PATH):
do_upgrade()
else:
print "The configuration database %s does not exist.\nEntering initial setup mode...\n" % config.SQLITE_PATH
- do_setup()
\ No newline at end of file
+ do_setup()
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers