diff --git a/models/db_database.py b/models/db.py similarity index 100% rename from models/db_database.py rename to models/db.py diff --git a/models/db_defaults.py b/models/defaults.py similarity index 100% rename from models/db_defaults.py rename to models/defaults.py diff --git a/models/plugin_dbui.py b/models/plugin_dbui.py index 8cda8f7d713329c8d711da6176669e1b9e0c0ac9..c3cf7c10b2b7f180ecf51425fd60da220a40e381 100644 --- a/models/plugin_dbui.py +++ b/models/plugin_dbui.py @@ -10,7 +10,7 @@ plugins = PluginManager('dbui', field_modifiers={}, form_modifiers={}, grid_modifiers={}, - viewport_modifiers={}, + viewport_modifiers=Storage(extjs={}), script_path='static/scripts', user_src_path='static/src', user_libmin=None) @@ -28,8 +28,9 @@ directSvc.debug = session.debug # register method available on the client side @directSvc.register -def getConfiguration(tablename, xtype): - return cfgSvc.get_configuration(tablename, xtype) +def getForm(table): + return cfgSvc.get_form(table) + @directSvc.register def getTree(node): diff --git a/models/db_widgets.py b/models/widgets.py similarity index 94% rename from models/db_widgets.py rename to models/widgets.py index 66c5f3b5af7d8ab53b98dd61b04fcaccfa0980dc..24b228544cd78d3913df150ae1c7a480fe59ce4c 100755 --- a/models/db_widgets.py +++ b/models/widgets.py @@ -8,27 +8,6 @@ from datetime import datetime dbui = local_import('plugin_dbui') -# -# The navigation tree embedded in the viewport -# hide some tables depending on the user role -# - -formNode = dbui.NodeDB(T('Forms'), - tables=db.tables, - widget='xform') - -gridNode = dbui.NodeDB(T('Tables'), - tables=db.tables, - widget='xgrid') - -reportNode = dbui.NodeURL(T('Reports'), - leaves=['report_1'], - urls=[URL(c="reports", f="report_1")], - widget='panel') - -viewportModifier = dbui.ViewportModifier() -viewportModifier.add_node(formNode, gridNode, reportNode) - # # add plugin to all grids # @@ -196,3 +175,19 @@ filters = [('year', '==', T('select publication for a given year')), gridModifier.set_filters(*filters, width=300) + + +# +# The navigation tree embedded in the viewport +# hide some tables depending on the user role +# +formNode = dbui.Node(T('Forms'), db.tables, cfgSvc.get_form) +gridNode = dbui.Node(T('Tables'), db.tables, cfgSvc.get_grid) + +reportNode = dbui.Node(T('Reports'), + {'report_1': URL(c="reports", f="report_1")}, + dbui.cfg_url_panel) + +viewportModifier = dbui.ViewportModifier() +viewportModifier.add_node(formNode, gridNode, reportNode) + diff --git a/modules/plugin_dbui/__init__.py b/modules/plugin_dbui/__init__.py index 51090280d1c76b5f9ed171723b0b61f5495d34ff..79d7762288d154b9c30ae23ac39424d66105c3c5 100755 --- a/modules/plugin_dbui/__init__.py +++ b/modules/plugin_dbui/__init__.py @@ -16,5 +16,5 @@ from helper import (get_js_files, get_script_path) from mapper import map_default, map_tabpanel from modifier import Spacer, Widget -from navtree import NodeDB, NodeURL +from navtree import Node, cfg_url_panel from viewportmodifier import ViewportModifier \ No newline at end of file diff --git a/modules/plugin_dbui/cfgsvc.py b/modules/plugin_dbui/cfgsvc.py index 952518b4fde1431e3a82794c61ec723de7dae6cd..af6e00384be3b8c5974249ebd79b0cabfa2178f9 100755 --- a/modules/plugin_dbui/cfgsvc.py +++ b/modules/plugin_dbui/cfgsvc.py @@ -227,26 +227,6 @@ class CfgSvc(BaseSvc): return self._foreign.get_foreign_data(tablename, fieldname) - def _get_form(self, tablename): - """Build the configuration options for the App.form.FormPanel - associated to the database table tablename. - - Return a dictionary. - - """ - T = self.environment['T'] - - cfg = {'items': self._get_form_items(tablename), - 'store': STOREID % tablename, - 'xtype': 'xform'} - - form_modifiers = self.environment['plugins'].dbui.form_modifiers - if tablename in form_modifiers: - cfg.update(form_modifiers[tablename].extjs) - - return cfg - - def _get_form_composite_field(self, tablename, fieldname): """Build the configuration dictionary for a composite field. @@ -392,36 +372,6 @@ class CfgSvc(BaseSvc): return formitems - def _get_grid(self, tablename): - """Build the configuration options for the Ext.grid.GridPanel - widget associated to the database table tablename. - - Return a dictionary - - """ - T = self.environment['T'] - - cfg = {'columns': self._get_columns_model(tablename), - 'frame': False, - 'store': STOREID % tablename, - 'viewConfig': {'forceFit': True}, - 'xtype': 'xgrid'} - - # handle the user configuration option for Ext.grid.GridPanel - grid_modifiers = self.environment['plugins'].dbui.grid_modifiers - if tablename in grid_modifiers: - cfg.update(grid_modifiers[tablename].extjs) - - # grid with filter - filter = self._get_grid_filter(tablename) - if filter: - cfg = {'filterCfg': filter, - 'gridCfg': dict(cfg), - 'xtype': 'xgridwithfilter'} - - return cfg - - def _get_grid_filter(self, tablename): """ Generate configuration object for the grid filter @@ -492,23 +442,54 @@ class CfgSvc(BaseSvc): return self._set.is_set_field(tablename, fieldname) - def get_configuration(self, tablename, xtype): - """Build the configuration for the widget associated to - the database table tablename. - - The widget is defined by the ExtJS xtype parameters. - (see the Ext.Component documentation for more information). + def get_form(self, tablename): + """Build the configuration options for the App.form.FormPanel + associated to the database table tablename. Return a dictionary. - """ - if xtype in ('form', 'xform'): - return self._get_form(tablename) + """ + T = self.environment['T'] + + cfg = {'items': self._get_form_items(tablename), + 'store': STOREID % tablename, + 'xtype': 'xform'} - if xtype in ('grid', 'xgrid', 'xgridwithfilter'): - return self._get_grid(tablename) + form_modifiers = self.environment['plugins'].dbui.form_modifiers + if tablename in form_modifiers: + cfg.update(form_modifiers[tablename].extjs) + + return cfg + + + def get_grid(self, tablename): + """Build the configuration options for the Ext.grid.GridPanel + widget associated to the database table tablename. + + Return a dictionary - return None + """ + T = self.environment['T'] + + cfg = {'columns': self._get_columns_model(tablename), + 'frame': False, + 'store': STOREID % tablename, + 'viewConfig': {'forceFit': True}, + 'xtype': 'xgrid'} + + # handle the user configuration option for Ext.grid.GridPanel + grid_modifiers = self.environment['plugins'].dbui.grid_modifiers + if tablename in grid_modifiers: + cfg.update(grid_modifiers[tablename].extjs) + + # grid with filter + filter = self._get_grid_filter(tablename) + if filter: + cfg = {'filterCfg': filter, + 'gridCfg': dict(cfg), + 'xtype': 'xgridwithfilter'} + + return cfg def get_jsonstore(self, tablename): diff --git a/modules/plugin_dbui/navtree.py b/modules/plugin_dbui/navtree.py index 1a5bc76c205d113004bf879d32d63ad25ea93489..2421756309e64613acc8ab0b5d7d960bdc8cd520 100644 --- a/modules/plugin_dbui/navtree.py +++ b/modules/plugin_dbui/navtree.py @@ -7,134 +7,95 @@ __version__ = "$Revision$" import locale from gluon import current -MSG_TEXT_WIDGET = 'The argument text and widget have to be defined.' - -class NodeBase(object): +def cfg_url_panel(key, url): + """Return the configuration object for an Ext.Panel + which autolad an url. - def __init__(self, text): - """The argument text defines the name of the node. - - """ - self.text = text - self.children= [] + """ + return {'autoLoad': url, 'preventBodyReset': True, 'xtype': 'panel'} + +class Node(object): + """Node associating a leaf to a widget. + + Leaves can be a list of database table or dicitonary + assoicating a key with an url. In the latter case leave name + are the dictionary key. + + Leaf names are translated and sorted by alphabetic order. + Some my be hidden depending on the context. - def add_children(self, text='', widget='', **kwargs): - """ Add a child to the node. + We use a configurator to get the confgiration object of the + target widget. It is a function getting the leave names, its + attributes (dictionary value) and returning a dictionary + + """ + def __init__(self, text, leaves, configurator, hidden=[]): + """Constructor of the node text - the name of the leaf + name of the node appearing in the viewport - widget - the ExtJS widget type associate to the leaf + leaves + list of leaves names + or dictionary where keys define leave names - kwargs - additional attributes of the node - - """ - if not (text and widget): - raise NodeException(MSG_TEXT_WIDGET) - - di = {'leaf': True, - 'text': text, - 'widget': widget} + configurator + Reference to a function accepting either a leave name + or a leave name and the dictionary value. The function + return the configuration dictionary for the ExtJS widget. + The function defines the type of widget. + + hidden + List of leaves to be hidden. It contains leaves names - di.update(**kwargs) - self.children.append(di) - - - def get_node(self): - """Return the configuration dictionary for the node. - """ - return {'text': self.text, 'children': self.children} - - -class NodeException(BaseException): pass - - -class NodeDB(NodeBase): - """Navigation node where each leaf is associate to a database table. - - ExtJS widget can be associated to each table either globally - or individually using widget and widgets arguments respectively. - The widget identifier is its ExtJS type: xform, xgrid, ... - - Some tables my be hidden depending on the context using hidden - argument. - - Tables are sorted by alphabetic order. - Name of the table appearing in the tree are translated. - - """ - - def __init__(self, text, tables=[], widget='', hidden=[], widgets={}): + self.text = text + self.children= [] + # translator T = current.T - NodeBase.__init__(self, text) - - # order table in alphabetic order according to local setting - # the local setting is defined in the model as the time as the language - tablesCvt = {} - for el in tables: - tablesCvt[T(el)] = el + # converter to order leaves in alphabetic order + # according to local setting + cvt = {} + for el in leaves: + cvt[T(el)] = el - translate_tables = tablesCvt.keys() - translate_tables.sort(cmp=locale.strcoll) - + translate_leaves = cvt.keys() + translate_leaves.sort(cmp=locale.strcoll) + # fill the node with its children - for tr_table in translate_tables: - table = tablesCvt[tr_table] - if table in hidden: + for tr_leaf in translate_leaves: + leaf = cvt[tr_leaf] + if leaf in hidden: continue - wdg = widget - if table in widgets: - wdg = widgets[table] - - self.add_children(refName=table, text=tr_table, widget=wdg) + if isinstance(leaves, (list, tuple)): + self.add_children(tr_leaf, configurator(leaf)) + + elif isinstance(leaves, dict): + self.add_children(tr_leaf, configurator(leaf, leaves[leaf])) -class NodeURL(NodeBase): - """Navigation node where each leaf is associated to an url. + def add_children(self, text, cfg): + """ Add a child (leaf) to the node. + + text + the name of the leaf + + cfg + configuration dictionary for the associated + ExtJS widget - ExtJS widget can be associated to each leaf either globally - or individually using widget and widgets arguments respectively. - The widget identifier is its ExtJS type: xform, xgrid, ... - - Some leaf my be hidden depending on the context using hidden - argument. - - Leaves are sorted by alphabetic order. - Name of the leaf appearing in the tree are translated. - - """ - def __init__(self, text, leaves=[], urls=[], widget='', hidden=[], widgets={}): + """ + di = {'cfg': cfg, 'leaf': True, 'text': text} + self.children.append(di) + - T = current.T - - NodeBase.__init__(self, text) - - # order leaf in alphabetic order according to local setting - # the local setting is defined in the model as the time as the language - leavesCvt = {} - for el in leaves: - leavesCvt[T(el)] = leaves.index(el) - - translate_leaves = leavesCvt.keys() - translate_leaves.sort(cmp=locale.strcoll) + def get_node(self): + """Return the configuration dictionary for the node. - # fill the node with its children - for tr_leaf in translate_leaves: - i = leavesCvt[tr_leaf] - leaf = leaves[i] - if leaf in hidden: - continue - - wdg = widget - if leaf in widgets: - wdg = widgets[leaf] - - self.add_children(refName=leaf, text=tr_leaf, url=urls[i], widget=wdg) \ No newline at end of file + """ + return {'text': self.text, 'children': self.children} diff --git a/modules/plugin_dbui/viewportmodifier.py b/modules/plugin_dbui/viewportmodifier.py index ed3da7ee9ceb9443cc40366fbe850abb936b0230..0b708dae2bfca4a7fbef03e300581e5e015466ec 100644 --- a/modules/plugin_dbui/viewportmodifier.py +++ b/modules/plugin_dbui/viewportmodifier.py @@ -7,7 +7,7 @@ __author__ = "R. Le Gac" from gluon.storage import Storage from modifier import Modifier -from navtree import NodeBase +from navtree import Node MSG_INVALID_NODE = 'Node object is not an instance of NodeBase class.' @@ -34,7 +34,7 @@ class ViewportModifier(Modifier): """ for el in args: - if not isinstance(el, NodeBase): + if not isinstance(el, Node): raise ViewportModifierException(MSG_INVALID_NODE) self.data.nodes.extend(args) diff --git a/static/plugin_dbui/src/appgridroweditor.js b/static/plugin_dbui/src/appgridroweditor.js index 94a579d4eb638e192b3c365fbef63a4707932cd4..8d4c7f72436a3c09a99410f709efb2c043e9dfc0 100644 --- a/static/plugin_dbui/src/appgridroweditor.js +++ b/static/plugin_dbui/src/appgridroweditor.js @@ -69,7 +69,7 @@ App.grid.RowEditor = Ext.extend(Ext.Window, { // get the formPanel configuration and instantiate the object table = App.getTableName(this.grid.store); - Dbui.getConfiguration(table, 'xform', this.addFormPanel, this); + Dbui.getForm(table, this.addFormPanel, this); }, /** diff --git a/static/plugin_dbui/src/appviewport.js b/static/plugin_dbui/src/appviewport.js index a924b616f66e0cfa8521e3f5475ddcf33010238d..68f8dcc09c4708ea931f17046ac7d4e61baae2fe 100644 --- a/static/plugin_dbui/src/appviewport.js +++ b/static/plugin_dbui/src/appviewport.js @@ -100,26 +100,18 @@ App.Viewport = Ext.extend(Ext.Viewport, { parent = node.parentNode, panel, tabId, - refName = node.attributes.refName, viewport = this, - wdg, - xtype = node.attributes.widget; + wdgcfg = node.attributes.cfg, + wdgtype = node.attributes.cfg.xtype; - function addWidget(cfg, response) { - if (cfg === null) {return;} - wdg = Ext.ComponentMgr.create(cfg) - panel.add(wdg); - panel.doLayout(); - } - // protection if(!node.isLeaf()){ return; } - - // generate a unique tab identifier - tabId = refName + '/' + xtype; - + + // unique tab identifier + tabId = node.attributes.text + '/' + wdgtype; + // activate an existing tab if (this.tabPanel.getComponent(tabId)) { this.tabPanel.setActiveTab(tabId); @@ -128,26 +120,24 @@ App.Viewport = Ext.extend(Ext.Viewport, { // tab configuration // the title is defined as 'Form tablename', 'Grid tablename', ... - // handle the simple case of panel pointing to an url cfg = { - itemId: tabId, closable: true, + itemId: tabId, title: parent.attributes.text + " " + node.attributes.text }; - - if(xtype === 'panel' && node.attributes.url) { - cfg.autoLoad = node.attributes.url + + // embed single panel in the tab panel + // other widget as children + if( wdgtype === 'panel') { + delete wdgcfg.xtype; + Ext.apply(cfg, wdgcfg); + + } else { + cfg.items = [node.attributes.cfg]; } // create a new tab and activate it panel = this.tabPanel.add(cfg); this.tabPanel.setActiveTab(tabId); - - // for complex object like form and grid request their configuration - // to the server and add the corresponding widget in the newly - // created tab - if (xtype !== 'panel') { - Dbui.getConfiguration(refName, xtype, addWidget); - } } });