Commit 8c1726e1 authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Merge branch '18-accordion-selector' into 'master'

Resolve "Improve widgets to filter on data in selector"

* Require `plugin_dbui 0.9.7` or higher
* The selector for report uses the accordion layout.
* The form for event uses the card layout.
* Use the `Table` widget to display event data in he grid showing the event table.
* Closes #18

See merge request !23
parents 87ddde6b 83c18ae0
--------------------------------- CHANGELOG ----------------------------------
HEAD
- Require plugin_dbui 0.9.7 or higher
- The selector for report uses the accordion layout.
- The form for event uses the card layout.
0.6.2 (Nov 2016)
- Migrate to ExtJS 6.
......
......@@ -71,6 +71,7 @@
'Created On': 'Created On',
'Data': 'Data',
'Data base scheme': 'Schéma base de donnée',
'Data model': 'Modèle des données',
'Data people': 'Les données des personnes',
'Database field encoded as tablename.fieldname.': 'Champ de la base de donnée encodé tablename.fieldname.',
'database schema': 'schéma de la base de données',
......@@ -111,6 +112,7 @@
'Error...': 'Erreur...',
'Event': 'Evènement',
'Event category': 'Event category',
'Event data': "Donée d'un évènement",
'Events': 'Evènements',
'events': 'évènements',
'Evènement': 'Evènement',
......
......@@ -8,7 +8,11 @@
#
#-------------------------------------------------------------------------------
fieldsModifier = dbui.FieldsModifier('events')
fieldsModifier.configure_field('data', xtype='xuserdata')
fieldsModifier.configure_field('data',
colProperty={'width': 70},
colType={'width': 70},
fieldLabel='',
xtype='xuserdata')
#-------------------------------------------------------------------------------
#
......@@ -16,6 +20,15 @@ fieldsModifier.configure_field('data', xtype='xuserdata')
#
#-------------------------------------------------------------------------------
formModifier = dbui.FormModifier('events')
formModifier.merge_fields('event',
'definition',
title=T('General'))
formModifier.merge_fields('data',
title=T('Data model'))
formModifier.set_mapper(dbui.map_tabpanel)
formModifier.configure(plugins=['pUserDataConsistency'], width=450)
#-------------------------------------------------------------------------------
......@@ -25,6 +38,24 @@ formModifier.configure(plugins=['pUserDataConsistency'], width=450)
#-------------------------------------------------------------------------------
gridModifier = dbui.GridModifier('events')
gridModifier.configure_column('event', width=30)
gridModifier.hide_columns('data')
row_widget = {
'ptype': 'rowwidget',
'widget': {
'xtype': 'xuserdata',
'bind': {
'value': '{record.EventsData}'
},
'defaults': {'anchor': '90%'},
'colProperty': {'width': 80},
'colType': {'width': 80},
'padding': '10 0 12 50',
'readOnly': True
}
}
gridModifier.configure(plugins=[row_widget])
#-------------------------------------------------------------------------------
#
......
......@@ -5,17 +5,17 @@
tp_data = T("The field history.data contains the given value.")
virtdb.define_table('selector',
Field('year_start', 'integer', default=year),
Field('year_end', 'integer'),
Field('id_domains', 'reference domains', label=T('Domain')),
Field('id_teams', 'reference teams', label=T('Team')),
Field('id_projects', 'reference projects', label=T('Project')),
Field('id_fundings', 'reference fundings', label=T('Funding')),
Field('id_people_categories', 'reference alias_people_categories', label= T("People category")),
Field('id_people_code', 'reference people_categories', label= T("People quality")),
Field('id_object_categories', 'reference alias_object_categories', label= T("Object category")),
Field('id_object_code', 'reference object_categories', label= T("Object code")),
Field('data', 'string', comment=tp_data, label= T("Data")))
Field('year_start', 'integer', default=year, label="Start"),
Field('year_end', 'integer', label="End"),
Field('id_domains', 'reference domains', label='Domain'),
Field('id_teams', 'reference teams', label='Team'),
Field('id_projects', 'reference projects', label='Project'),
Field('id_fundings', 'reference fundings', label=''),
Field('id_people_categories', 'reference alias_people_categories', label= 'Category'),
Field('id_people_code', 'reference people_categories', label= 'Quality'),
Field('id_object_categories', 'reference alias_object_categories', label= 'Category'),
Field('id_object_code', 'reference object_categories', label= 'Code'),
Field('data', 'string', comment=tp_data, label= ''))
virtdb.selector.id_object_categories.requires = \
IS_IN_DB(db, 'alias_object_categories.category')
......@@ -34,15 +34,15 @@ virtdb.selector.id_fundings.requires = IS_IN_DB(db, 'fundings.agency')
virtdb.selector.id_projects.requires = IS_IN_DB(db, 'projects.project')
virtdb.selector.id_teams.requires = IS_IN_DB(db, 'teams.team')
#-------------------------------------------------------------------------------
# ............................................................................
#
# FIELDS CONFIGURATiON
#
#-------------------------------------------------------------------------------
fieldsModifier = dbui.FieldsModifier('selector')
fieldsModifier.configure_field('year_start', flex=1)
fieldsModifier.configure_field('year_end', flex=1)
fieldsModifier.merge_fields('year_start', 'year_end', fieldLabel=T('Period'))
# fieldsModifier.configure_field('year_start', flex=1)
# fieldsModifier.configure_field('year_end', flex=1)
# fieldsModifier.merge_fields('year_start', 'year_end', fieldLabel=T('Period'))
mytype = 'xcomboboxuserreset'
text = T('select...')
......@@ -57,8 +57,83 @@ fieldsModifier.configure_field('id_people_code', emptyText=text, xtype=mytype)
fieldsModifier.configure_field('id_teams', emptyText=text, xtype=mytype)
fieldsModifier.configure_field('id_projects', emptyText=text, xtype=mytype)
#-------------------------------------------------------------------------------
fieldsModifier.configure_field(
'data',
header=[T("key"), T("value")],
numColumns=2,
numRows=3,
xtype='xtablefield')
# ............................................................................
#
# FORM CONFIGURATiON
# PANELWITHURLSELECTOR
# - configure it once since it is used many times (lists, metric1D, ...)
# - organise fields within an accordion layout
#
#-------------------------------------------------------------------------------
# map between field name and field configuration
# keys are the field name or field label for merge fields
mapfields = Storage()
for cfgfield in dbui.to_fields(virtdb.selector):
key = (cfgfield.name if cfgfield.name else cfgfield.fieldLabel)
mapfields[key] = cfgfield
# Organise fields within different panels
# and replace field name by their configuration
items = [
{
'title': T('Period'),
'items': ['SelectorYear_start',
'SelectorYear_end']
}, {
'title': T('Metadata'),
'items': ['SelectorId_domains',
'SelectorId_teams',
'SelectorId_projects']
}, {
'title': T('People'),
'collapsed': True,
'items': ['SelectorId_people_categories',
'SelectorId_people_code']
}, {
'title': T('Object'),
'collapsed': True,
'items': ['SelectorId_object_categories',
'SelectorId_object_code']
}, {
'title': T('Event data'),
'collapsed': True,
'layout': 'fit',
'items': ['SelectorData']
}, {
'title': T('Fundings'),
'collapsed': True,
'layout': 'fit',
'items': ['SelectorId_fundings']
}
]
for panel in items:
panelitems = panel["items"]
for i in xrange(len(panelitems)):
panelitems[i] = mapfields[panelitems[i]]
# configure the accordion layout
# several panel can be open at the same time (multi)
layout = dict(
multi=True,
titleCollapse=True,
type="accordion")
# wrap fields within a FieldSet
fieldset = dbui.FieldSet(
defaults=dict(frame=True),
items=items,
layout=layout,
plugins=["pFormToolTip"],
title=T("Select"))
# configure the PanelWithUrlSelector
selector_panel = dbui.PanelWithUrlSelector(
baseUrl=URL('report', 'grid'),
selectorItems=fieldset)
......@@ -10,11 +10,11 @@ Node = dbui.Node
Panel = dbui.Panel
PanelWithUrlSelector = dbui.to_panelWithUrlSelector
#-------------------------------------------------------------------------------
# ............................................................................
#
# CAS
#
#-------------------------------------------------------------------------------
casNode = None
if "auth" in globals():
......@@ -24,11 +24,11 @@ if "auth" in globals():
casNode.add_child(T('groups'), to_grid('auth_group'))
casNode.add_child(T('relation user / groups'), to_grid('auth_membership'))
#-------------------------------------------------------------------------------
# ............................................................................
#
# HELP NODE
#
#-------------------------------------------------------------------------------
loader = dict(autoLoad=True,
renderer='html',
url=URL('plugin_dbui', 'about'))
......@@ -61,22 +61,22 @@ helpNode.add_child(T('documentations'), docLeaf)
helpNode.add_child(T('versions'), versionLeaf)
helpNode.sort_children()
#-------------------------------------------------------------------------------
# ............................................................................
#
# CONFIGURE
#
#-------------------------------------------------------------------------------
cfgNode = Node(T('Configure'))
cfgNode.add_child(T('the lists'), to_grid('lists'))
cfgNode.add_child(T('the metrics 1d'), to_grid('metrics1d'))
cfgNode.add_child(T('the metrics 2d'), to_grid('metrics2d'))
cfgNode.add_child(T('the graphs'), to_grid('graphs'))
#-------------------------------------------------------------------------------
# ............................................................................
#
# META DATA
#
#-------------------------------------------------------------------------------
metaNode = Node(T('Metadata'))
metaNode.add_child(T('domains'), to_grid('domains'))
metaNode.add_child(T('fundings'), to_grid('fundings'))
......@@ -84,11 +84,11 @@ metaNode.add_child(T('teams'), to_grid('teams'))
metaNode.add_child(T('projects'), to_grid('projects'))
metaNode.sort_children()
#-------------------------------------------------------------------------------
# ............................................................................
#
# PEOPLE & OBJECT
#
#-------------------------------------------------------------------------------
objectNode = Node(T('People and objects'))
objectNode.add_child(T('people'), to_grid('people'))
objectNode.add_child(T('people_categories'), to_grid('people_categories'))
......@@ -96,85 +96,85 @@ objectNode.add_child(T('objects'), to_grid('objects'))
objectNode.add_child(T('object_categories'), to_grid('object_categories'))
objectNode.sort_children()
#-------------------------------------------------------------------------------
# ............................................................................
#
# EVENT
#
#-------------------------------------------------------------------------------
eventNode = Node(T('Events'))
eventNode.add_child(T('definitions'), to_grid('events'))
eventNode.add_child(T('history'), to_grid('history'))
#-------------------------------------------------------------------------------
# ............................................................................
#
# LIST
#
#-------------------------------------------------------------------------------
listNode = Node(T('The lists'))
for row in db(db.lists.id > 0).select(orderby=db.lists.name):
leaf = PanelWithUrlSelector(virtdb.selector,
baseUrl=URL('report', 'grid'),
baseParams={'id_lists': row.id})
leaf = selector_panel
leaf.baseUrl = URL('report', 'grid')
leaf.baseParams = {'id_lists': row.id}
listNode.add_child(row.name, leaf)
#-------------------------------------------------------------------------------
# ............................................................................
#
# METRIC 1D
#
#-------------------------------------------------------------------------------
metric1dNode = Node(T('The metrics 1d'))
for row in db(db.metrics1d.id > 0).select(orderby=db.metrics1d.name):
leaf = PanelWithUrlSelector(virtdb.selector,
baseUrl=URL('report', 'grid'),
baseParams={'id_metrics1d': row.id})
leaf = selector_panel
leaf.baseUrl = URL('report', 'grid')
leaf.baseParams = {'id_metrics1d': row.id}
metric1dNode.add_child(row.name, leaf)
metric1dNode.sort_children()
#-------------------------------------------------------------------------------
# ............................................................................
#
# METRIC 2D
#
#-------------------------------------------------------------------------------
metric2dNode = Node(T('The metrics 2d'))
for row in db(db.metrics2d.id > 0).select(orderby=db.metrics2d.name):
leaf = PanelWithUrlSelector(virtdb.selector,
baseUrl=URL('report', 'grid'),
baseParams={'id_metrics2d': row.id})
leaf = selector_panel
leaf.baseUrl = URL('report', 'grid')
leaf.baseParams = {'id_metrics2d': row.id}
metric2dNode.add_child(row.name, leaf)
metric2dNode.sort_children()
#-------------------------------------------------------------------------------
# ............................................................................
#
# GRAPH
# Define by the 2D metrics
#
#-------------------------------------------------------------------------------
graphNode = Node(T('The graphs'))
for row in db(db.graphs.id > 0).select(orderby=db.graphs.name):
leaf = PanelWithUrlSelector(virtdb.selector,
baseUrl=URL('report', 'graph_mpl'),
baseParams={'id_graphs': row.id})
leaf = selector_panel
leaf.baseUrl = URL('report', 'graph_mpl')
leaf.baseParams = {'id_graphs': row.id}
graphNode.add_child(row.name, leaf)
#-------------------------------------------------------------------------------
# ............................................................................
#
# VIEWPORT
#
#-------------------------------------------------------------------------------
nodes = [helpNode,
casNode,
cfgNode,
......
......@@ -2,6 +2,9 @@
"""selector module
"""
import json
from datetime import date, timedelta
from gluon import current
from gluon.dal import Field
......@@ -324,8 +327,33 @@ class MySelector(SelectorActiveItems):
db = table._db
query = SelectorActiveItems.query(self, table)
# history data block contains
query &= db.history.data.contains(self.data)
# history data block
# list of key, value pair: [[None, 'v1'], ['k2', 'v2'], [None, 'v5']]
# apply the like operator: %bla%bla%
data = json.loads(self.data)
if len(data) > 0:
conditions = []
for key, val in data:
if key is None and val is None:
pass
elif key is None:
conditions.append(val)
elif val is None:
conditions.append('"%s":' % key)
elif val in ("true", "false"):
conditions.append('"%s": %s' % (key, val))
elif isinstance(val, (unicode, str)):
conditions.append('"%s": "%s"' % (key, val))
else:
conditions.append('"%s": %s' % (key, val))
conditions = "%%%s%%" % "%".join(conditions)
query &= db.history.data.like(conditions, case_sensitive=False)
# object category and code
id_object_code = self.id_object_code
......
......@@ -17,6 +17,42 @@ Ext.define('TrackEvents.form.field.UserData', {
anchor: '100%'
},
/**
* @cfg {Object}
* Configuration of the column "property".
* Useful to tune the width of the column.
*/
colProperty: {
flex: 0.7
},
/**
* @cfg {Object}
* Configuration of the column "type".
* Useful to tune the width of the column.
*
*/
colType: {
flex: 0.7
},
/**
* @cfg {Object}
* Configuration of the column "value".
* Useful to tune the width of the column.
*
*/
colValue: {
flex: 1
},
/**
* @cfg {Boolean}
* Disable the context menu when readOnly is true
*
*/
readOnly: false,
// private short cuts
grid: null,
menu: null,
......@@ -46,8 +82,8 @@ Ext.define('TrackEvents.form.field.UserData', {
initComponent: function () {
var me = this,
grid,
store;
readOnly = me.readOnly,
columns, grid, store;
// the store used by the grid
store = {
......@@ -65,30 +101,34 @@ Ext.define('TrackEvents.form.field.UserData', {
columns: [{
text: me.textProperty,
dataIndex: 'property',
flex: 1.5,
menuDisabled: true,
sortable: false
}, {
text: me.textType,
dataIndex: 'type',
editor: me.typeEditor(),
flex: 0.7,
editor: (readOnly ? undefined : me.typeEditor()),
menuDisabled: true,
sortable: false
}, {
text: me.textValue,
dataIndex: 'value',
editor: 'textfield',
flex: 1,
editor: (readOnly ? undefined : 'textfield'),
menuDisabled: true,
sortable: false
}],
plugins: [{ptype: 'cellediting', clicksToEdit: 1}],
store: store,
selType: 'cellmodel',
selType: (readOnly ? undefined : 'cellmodel'),
xtype: 'grid'
}];
// Apply user setting for columns (widht, flex, ...)
columns = me.items[0].columns;
Ext.apply(columns[0], me.colProperty);
Ext.apply(columns[1], me.colType);
Ext.apply(columns[2], me.colValue);
// instantiate the base class
me.callParent(arguments);
......@@ -239,6 +279,10 @@ Ext.define('TrackEvents.form.field.UserData', {
event.stopEvent();
if (me.readOnly) {
return;
}
if (cellIndex === 0) {
me.menu.getComponent('destroy').setDisabled(false);
......@@ -284,6 +328,10 @@ Ext.define('TrackEvents.form.field.UserData', {
event.stopEvent();
if (me.readOnly) {
return;
}
// allow to add key if the store is empty
if (me.store.getCount() === 0) {
me.onAddProperty();
......
......@@ -36,8 +36,9 @@ Ext.define('TrackEvents.grid.HistoryFilter', {
// the arcordeon layout
me.layout = {
type: 'accordion',
titleCollapse: true
multi: true,
titleCollapse: true,
type: 'accordion'
};
me.defaults = {
......@@ -86,24 +87,30 @@ Ext.define('TrackEvents.grid.HistoryFilter', {
// create the new item structure by adding sub-panel
me.items = [{
title: me.textMetadata,
collapsed: false,
items: metadata
}, {
title: me.textPeople,
collapsed: true,
items: people
}, {
title: me.textObject,
collapsed: true,
items: object
}, {
title: me.textEventData,
items: eventdata,
layout: 'fit'
collapsed: true,
layout: 'fit',
items: eventdata
}, {
title: me.textPeriod,
collapsed: true,
items: period
}, {
title: me.textFunding,
items: funding,
layout: 'fit'
collapsed: true,
layout: 'fit',
items: funding
}];
// initialise the base class
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment