-
LE GAC Renaud authoredLE GAC Renaud authored
plugin_dbui.py 11.88 KiB
""" plugin_dbui.py
Controllers expose by the plugin:
index
database
configuration
Author: R. Le Gac
"""
import json
import os
API = """
App.csvUrl = '/%s/plugin_dbui/csv';
App.config = %s;
App.debug = %s;
App.name = '%s';
App.REMOTE_API = {
'url': '/%s/plugin_dbui/call',
'type': 'remoting',
'actions': %s
};"""
def about():
fn = os.path.join("applications",
request.application,
"static",
"ABOUT.html")
return open(fn, 'rb').read()
def call():
"""Action to handle the Ext.Direct protocol.
"""
return directSvc()
def csv():
"""Action returning the content of a table as a CSV file.
Foreign keys are replaced by the parent column.
"""
from gluon.contenttype import contenttype
from plugin_dbui import (get_foreign_field,
get_where_query,
is_foreign_field,
is_table_with_foreign_fields)
tablename = request.vars['tableName']
response.headers['Content-Type'] = contenttype('.csv')
response.headers['Content-Disposition'] = 'attachment; filename=%s.csv;' % tablename
table = db[tablename]
query = table.id > 0
# replace foreign key by parent fields
# and build the query to resolve foreign keys
if is_table_with_foreign_fields(table):
fields = []
query = ((query) & (get_where_query(table)))
for field in table:
if is_foreign_field(field):
k_table, k_field, k_key = get_foreign_field(field)
fields.append(db[k_table][k_field])
else:
fields.append(field)
else:
fields = [table.ALL]
# interrogate the database
rows = db(query).select(*fields)
return str(rows)
def dbui_conf():
"""Action returning the javascript script configuring
the plugin dbui: application name, store definition,...
"""
from gluon.contrib import simplejson as json
from plugin_dbui import (DBUI,
get_all_tables,
to_jsonstore,
to_model,
to_treeNodes,
to_viewport)
di = {}
# build the dictionary required by Ext.direct
# containing the definition of the remote procedure
for (k, f) in directSvc.procedures.iteritems():
action, method = k.split('.')
if action == DBUI:
nargs = f.func_code.co_argcount
else:
nargs = f.__func__.func_code.co_argcount - 1
if action not in di:
di[action] = []
di[action].append({'name': method, 'len': nargs})
# the definition of the models
config = {'models': {},
'stores': {},
'treeNodes': [],
'viewport': None}
for table in get_all_tables(db):
config['models'][table._tablename] = to_model(table)
# the stores configuration (static, for each table,...)
# NOTE: the interface require a store for all tables including alias.
# The only way to extract them is to scan the attributes list of
# the DAL since the method db.tables() or any variant return
# tables but not the alias one
config['stores'].update(plugins.dbui.static_stores)
for table in get_all_tables(db):
cfg = to_jsonstore(table)
config['stores'][cfg['storeId']] = cfg
# the tree nodes configuration for the TreeStore
config['treeNodes'] = to_treeNodes()
# the viewport configuration
config['viewport'] = to_viewport()
# debug mode
debug = 'false'
if 'debug' in request.vars:
debug = 'true'
# fill the javascript template
app = request.application
script = API % (app,
json.dumps(config),
debug,
app,
app,
json.dumps(di))
# return the response as a javascript
response.headers['Content-Type'] = 'text/javascript'
return script
def debug():
"""Action to run the plugin in debug mode.
Load dynamically the javascript source code for all libraries.
Active the debug mode on the server and client side.
EXAMPLES
http://localhost:8000/myapp/plugin_dbui/debug
http://localhost:8000/myapp/plugin_dbui/debug?script=foo
URL OPTIONS
script
run the javascript foo in the framework defined by the plugin.
The scripts are stored in the directory defined by the plugin
configuration app_script_dir.
"""
from plugin_dbui import get_file_paths, get_script_path
plugin = plugins.dbui
# css files
response.files.extend(get_file_paths(plugin.extjs_css, ext='.css'))
response.files.extend(get_file_paths(plugin.dbui_css, ext='.css'))
response.files.extend(get_file_paths(plugin.ace_css, ext='.css'))
response.files.extend(get_file_paths(plugin.app_css, ext='.css'))
# debug version of the javascript libraries
response.files.extend(get_file_paths(plugin.ace_libmin, ext='.js'))
response.files.extend(get_file_paths(plugin.mathjax_libmin, ext='.js'))
response.files.extend(get_file_paths(plugin.extjs_debug, ext='.js'))
response.files.extend(get_file_paths(plugin.dbui_debug, ext='.js'))
response.files.extend(get_file_paths(plugin.app_debug, ext='.js'))
# language files
response.files.extend(get_file_paths(plugin.extjs_lg, ext='.js'))
response.files.extend(get_file_paths(plugin.dbui_lg, ext='.js'))
response.files.extend(get_file_paths(plugin.app_lg, ext='.js'))
# URL for the dbui configuration activating the debug
# mode on the client side
response.files.append(plugin.dbui_conf_debug)
# main script which can be defined in many different ways
pscript = get_script_path(plugin)
response.files.append(pscript)
# switch ON the debug mode on the server side
session.debug = True
# select the view
response.view = 'plugin_dbui/index.html'
# return the plugin configuration parameter as well as the response
return dict(plugin=plugin)
def documentations():
"""Return the Ext.data.Array configuration for the documentation
and for the source code.
"""
from plugin_dbui import get_reference_paths
# alias
a = '<a href="%s" target="_blank">%s</a>'
trDev = T("Documentation for developers")
trJS = T("Javascript API")
trPy = T("Python API")
# documentation of the application
apath, lpath = get_reference_paths()
userdoc = ""
if os.path.exists(os.path.join(apath, 'static/docs/database.png')):
userdoc = a % (URL('static', 'docs/database.png'), T("Data base scheme"))
pydoc = ""
if os.path.exists(os.path.join(apath, 'static/docs/epydoc/index.html')):
pydoc = a % (URL('static', 'docs/epydoc/index.html'), trPy)
jsdoc = ""
if os.path.exists(os.path.join(apath, 'static/docs/jsduck/index.html')):
jsdoc = a % (URL('static', 'docs/jsduck/index.html'), trJS)
# configuration of the Ext.data.Array for the documentation
cfg = dict()
cfg['fields'] = [{'name': 'code', 'type': 'string'},
{'name': 'developer', 'type': 'string'},
{'name': 'python', 'type': 'string'},
{'name': 'javascript', 'type': 'string'}]
r1 = (request.application, userdoc, pydoc, jsdoc)
r2 = (a % ("https://marprod.in2p3.fr/plugin_dbui_book", "plugin_dbui"),
a % ("https://marprod.in2p3.fr/plugin_dbui_book/default/chapter/29", trDev),
a % (URL('static', 'plugin_dbui/docs/epydoc/index.html'), trPy),
a % (URL('static', 'plugin_dbui/docs/jsduck/index.html'), trJS))
r3 = (a % ("http://web2py.com/", "Web2py"),
a % ("http://web2py.com/book", trDev),
a % ("http://www.web2py.com/examples/static/epydoc/index.html", trPy),
"")
r4 = (a % ("http://www.sencha.com/products/extjs/", "Ext JS"),
"",
"",
a % ("http://docs.sencha.com/extjs/4.2.1/", trJS))
r5 = (a % ("http://www.mathjax.org/", "MathJax"),
"",
"",
a % ("http://docs.mathjax.org/", trJS))
r6 = (a % ("http://ace.c9.io/#nav=about", "Ace"),
"",
"",
a % ("http://ace.c9.io/#nav=api", trJS))
cfg['data'] = [r1, r2, r3, r4, r5, r6]
cfg_doc = json.dumps(cfg)
# configuration of the Ext.data.Array for the source code
cfg = dict()
cfg['fields'] = [{'name': 'code', 'type': 'string'},
{'name': 'source', 'type': 'string'}]
r1 = (request.application, "<em>git clone http://marwww.in2p3.fr/~legac/wap/git/%s.git</em>" % request.application)
r2 = ("plugin_dbui", "<em>git clone http://marwww.in2p3.fr/~legac/wap/git/web2py_plugin_dbui.git</em>")
r3 = ("Web2py", "<em>git clone git://github.com/web2py/web2py.git</em>")
r4 = ("Ext JS",
"<em>Download from the Ext JS web site.</em><br>"
"<em>In the local directory: %s/static/plugin_extjs/src</em>" % request.application)
r5 = ("MathJax", "<em>git clone http://github.com/mathjax/MathJax</em>")
r6 = ("Ace", "<em>git clone git://github.com/ajaxorg/ace.git</em>")
cfg['data'] = [r1, r2, r3, r4, r5, r6]
cfg_src = json.dumps(cfg)
return dict(cfg_doc=cfg_doc, cfg_src=cfg_src)
def index():
"""Default Action to run the plugin
Load compressed version of all libraries.
EXAMPLES
http://localhost:8000/myapp/plugin_dbui
http://localhost:8000/myapp/plugin_dbui?script=foo
URL OPTIONS
script
run the javascript foo in the framework defined by the plugin.
The scripts are stored in the directory defined by the plugin
configuration app_script_dir.
"""
from plugin_dbui import get_file_paths, get_script_path
plugin = plugins.dbui
# css files
response.files.extend(get_file_paths(plugin.extjs_css, ext='.css'))
response.files.extend(get_file_paths(plugin.dbui_css, ext='.css'))
response.files.extend(get_file_paths(plugin.ace_css, ext='.css'))
response.files.extend(get_file_paths(plugin.app_css, ext='.css'))
# compressed version of the javascript libraries
response.files.extend(get_file_paths(plugin.ace_libmin, ext='.js'))
response.files.extend(get_file_paths(plugin.mathjax_libmin, ext='.js'))
response.files.extend(get_file_paths(plugin.extjs_libmin, ext='.js'))
response.files.extend(get_file_paths(plugin.dbui_libmin, ext='.js'))
response.files.extend(get_file_paths(plugin.app_libmin, ext='.js'))
# language files
response.files.extend(get_file_paths(plugin.extjs_lg, ext='.js'))
response.files.extend(get_file_paths(plugin.dbui_lg, ext='.js'))
response.files.extend(get_file_paths(plugin.app_lg, ext='.js'))
# URL for dbui configuration script
response.files.append(plugin.dbui_conf)
# main script which can be defined in many different ways
pscript = get_script_path(plugin)
response.files.append(pscript)
# switch off the debug mode on the server side
session.debug = False
# return the plugin configuration parameter as well as the response
return dict(plugin=plugin)
def status():
return dict(request=request, response=response, session=session)
def versions():
"""Return the versions of the different part of the code.
"""
from plugin_dbui import get_versions
# the configuration for the Ext.data.ArrayStore
cfg = dict()
cfg['fields'] = [{'name': 'code', 'type': 'string'},
{'name': 'version', 'type': 'string'}]
cfg['data'] = get_versions()
return dict(cfg_store=json.dumps(cfg))