Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
tev
plugin_event
Commits
963cc543
Commit
963cc543
authored
Feb 04, 2015
by
LE GAC Renaud
Browse files
Add the StorageFactory and StorageForList class.
parent
4430ad94
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
201 additions
and
117 deletions
+201
-117
controllers/report.py
controllers/report.py
+14
-46
modules/reporting_tools.py
modules/reporting_tools.py
+181
-66
views/report/grid.html
views/report/grid.html
+6
-5
No files found.
controllers/report.py
View file @
963cc543
...
...
@@ -6,12 +6,14 @@
- the content of the report is defined in the database
"""
import
json
import
re
from
datetime
import
date
,
timedelta
from
gluon.dal
import
smart_query
from
gluon.storage
import
Storage
from
reporting_tools
import
Report
,
repr_duration
,
to_dataFields
from
plugin_dbui
import
Store
from
reporting_tools
import
Report
,
repr_duration
,
StoreForListView
def
list
():
...
...
@@ -27,64 +29,30 @@ def list():
"""
# alias
now
=
date
.
today
()
list
=
db
.
lists
[
request
.
vars
.
id_lists
]
report
=
Report
(
virtdb
.
list_selector
,
exclude_fields
=
(
'category'
,
'period_end'
,
'period_start'
,
'year'
))
# apply
filter
condition
from the list
# apply
the list
condition
if
list
.
conditions
:
q_conditions
=
smart_query
(
db
.
history
,
list
.
conditions
)
report
.
append_query
(
q_conditions
)
# configure the Ext.data.ArrayStore
cfg
=
dict
()
cfg
[
'data'
]
=
[]
cfg
[
'fields'
]
=
to_dataFields
(
list
.
columns
)
if
list
.
group_field
:
cfg
[
'groupField'
]
=
list
.
group_field
# build the configuration for the Ext.data.Store
store
=
StoreForListView
(
list
,
report
.
select
(
db
.
history
))
if
list
.
sorters
:
cfg
[
'sorters'
]
=
list
.
sorters
# encode the Ext.grid.column.dataIndex to match the Ext.data.Field name
s
=
list
.
columns
.
replace
(
"
\n
"
,
""
).
replace
(
" "
,
""
)
s
=
re
.
sub
(
"dataIndex:'(\w+)\.(\w+)'"
,
"dataIndex:'
\\
1
\\
2'"
,
s
)
s
=
re
.
sub
(
"dataIndex:'(\w+)\.(\w+)\.(\w+)'"
,
"dataIndex:'
\\
1
\\
2
\\
3'"
,
s
)
list
.
columns
=
s
# fill the data block
# It is mandatory to preserve the data fields order
for
row
in
report
.
select
(
db
.
history
):
li
=
[]
for
field
in
cfg
[
'fields'
]:
# standard database type
if
field
[
'name'
].
count
(
'.'
)
==
1
:
value
=
row
[
field
[
'name'
]]
# json database type
elif
field
[
'name'
].
count
(
'.'
)
==
2
:
i
=
field
[
'name'
].
rindex
(
"."
)
fieldname
=
field
[
'name'
][:
i
]
key
=
field
[
'name'
][
i
+
1
:]
if
key
in
row
[
fieldname
]:
value
=
row
[
fieldname
][
key
]
else
:
value
=
""
if
isinstance
(
value
,
date
):
value
=
value
.
strftime
(
"%Y-%m-%d"
)
elif
isinstance
(
value
,
timedelta
):
value
=
value
.
total_seconds
()
li
.
append
(
value
)
cfg
[
'data'
].
append
(
li
)
# delegate the grid rendering to the view
response
.
view
=
'report/grid.html'
return
dict
(
cfg_store
=
cfg
,
view
=
list
)
return
dict
(
cfg_store
=
store
.
as_json
()
,
view
=
list
)
def
metric1D
():
...
...
modules/reporting_tools.py
View file @
963cc543
...
...
@@ -8,7 +8,8 @@ import re
from
datetime
import
date
,
timedelta
from
gluon
import
current
from
gluon.dal
import
Field
from
plugin_dbui
import
Selector
from
gluon.storage
import
Storage
from
plugin_dbui
import
Selector
,
Store
def
repr_duration
(
value
):
...
...
@@ -35,71 +36,6 @@ def repr_duration(value):
return
''
def
to_dataFields
(
cfg_columns
):
"""Convert the cfg_columns configuration for and Ext.grid.Panel
into a fields configuration for an Ext.data.ArrayStore.
@type cfg_columns: str
@param cfg_columns: a list of Ext.grid.column.Column configuration
encoded into a string.
@rtype: list of dictionary
@return: a list of Ext.data.Field configuration
"""
li
=
[]
db
=
current
.
globalenv
[
'db'
]
# extract the list of database field names from the column configuration
columns
=
re
.
findall
(
"dataIndex *: *'([a-z_\.]+)'"
,
cfg_columns
)
# convert the database field into and Ext.data.Field
for
column
in
columns
:
cfg
=
dict
()
cfg
[
'name'
]
=
column
# standard field
if
column
.
count
(
"."
)
==
1
:
tablename
,
fieldname
=
column
.
split
(
'.'
)
field
=
db
[
tablename
][
fieldname
]
# json type
elif
column
.
count
(
"."
)
==
2
:
i
=
column
.
rindex
(
"."
)
tablename
,
fieldname
=
column
[:
i
].
split
(
'.'
)
field
=
db
[
tablename
][
fieldname
]
cfg
[
'type'
]
=
field
.
type
if
field
.
type
in
(
'string'
,
'text'
,
'json'
):
cfg
[
'type'
]
=
'string'
elif
field
.
type
==
'date'
:
cfg
[
'type'
]
=
'date'
cfg
[
'dateFormat'
]
=
'Y-m-d'
elif
field
.
type
==
'datetime'
:
cfg
[
'type'
]
=
'date'
cfg
[
'dateFormat'
]
=
'Y-m-d H:i:s'
elif
field
.
type
==
'double'
:
cfg
[
'type'
]
=
'float'
elif
field
.
type
==
'integer'
:
cfg
[
'type'
]
=
'int'
elif
field
.
type
==
'time'
:
cfg
[
'type'
]
=
'date'
cfg
[
'dateFormat'
]
=
'H:i:s'
else
:
cfg
[
'type'
]
=
field
.
type
li
.
append
(
cfg
)
return
li
class
SelectorActiveItems
(
Selector
):
"""Selector to get records active during a given period of time.
...
...
@@ -389,3 +325,182 @@ class Report(SelectorActiveItems):
def
reset_extra_queries
(
self
):
self
.
_extra_queries
=
[]
class
StoreFactory
(
object
):
"""Base factory to generate the Ext.data.Store configuration for
the list, metrics and graphs view.
"""
def
__init__
(
self
):
self
.
cfg_store
=
Store
(
data
=
[],
fields
=
[])
def
as_dict
(
self
):
"""Get the store configuration as a dict.
@rtype: dict
@return: the Ext.data.Store configuration.
"""
return
dict
(
self
.
cfg_store
)
def
as_json
(
self
):
"""Get the store configuration as a JSON string.
@rtype: str
@return: the Ext.data.Store configuration as a JSON string.
"""
return
json
.
dumps
(
self
.
cfg_store
)
class
StoreFactoryException
(
BaseException
):
pass
class
StoreForListView
(
StoreFactory
):
"""Generate the Ext.data.Store configuration for the list view.
@note: The name of the Ext.data.Field is extract from the column
definition of the list where it is equal to table.dbfield or
table.dbfield.key. The dot is remove in the Ext.data.Field name.
Therefore the dataIndex used in the grid column configuration
has to be modified accordingly/
"""
def
__init__
(
self
,
list
,
rows
):
"""
@type list: gluon.dal.Row
@param list: parameters defining the list.
@type rows: gluon.dal.Rows
@param rows: data to be loaded on the store.
"""
StoreFactory
.
__init__
(
self
)
self
.
_map
=
dict
()
self
.
_get_fields
(
list
)
self
.
_get_data
(
rows
)
def
_get_fields
(
self
,
list
):
""" Generate the Ext.data.Store.fields property.
@type list: gluon.dal.Row
@param list: parameters defining the list.
@note: The name of the Ext.data.Field is extract from the column
definition of the list. It is encoded as table.dbfield or
table.dbfield.key. the latter is for JSON type dbfield. It can not be
used as is and has to be converted as table.dbfield[key].
@note: The name of the store Ext.data.dbfield can not contains dot.
Therefore, the name of the database dbfield is converted by
removing dots.
@rtype: list of Ext.data.Field configuration
@return: list of dictionaries configuring Ext.data.Field.
"""
db
=
current
.
globalenv
[
'db'
]
# extract the list of database dbfield names from the list definition
columns
=
re
.
findall
(
"dataIndex *: *'([a-z_\.]+)'"
,
list
.
columns
)
# convert the database dbfield into and Ext.data.Field
for
column
in
columns
:
name_items
=
column
.
split
(
'.'
)
name
=
''
.
join
(
name_items
)
# get the database dbfield link to the column.
# keep a map between the column in the store and the
# database dbfield for a later use when retrieving the data.
if
len
(
name_items
)
==
2
:
tablename
,
fieldname
=
name_items
keyname
=
None
elif
len
(
name_items
)
==
3
:
tablename
,
fieldname
,
keyname
=
name_items
else
:
raise
StoreFactoryException
(
"Can't decode column name."
)
dbfield
=
db
[
tablename
][
fieldname
]
self
.
_map
[
name
]
=
(
tablename
,
fieldname
,
keyname
)
# build the configuration for the Ext.data.Field
cfg
=
Storage
()
cfg
.
name
=
name
cfg
.
type
=
dbfield
.
type
if
dbfield
.
type
in
(
'string'
,
'text'
,
'json'
):
cfg
.
type
=
'string'
elif
dbfield
.
type
==
'date'
:
cfg
.
type
=
'date'
cfg
.
dateFormat
=
'Y-m-d'
elif
dbfield
.
type
==
'datetime'
:
cfg
.
type
=
'date'
cfg
.
dateFormat
=
'Y-m-d H:i:s'
elif
dbfield
.
type
==
'double'
:
cfg
.
type
=
'float'
elif
dbfield
.
type
==
'integer'
:
cfg
.
type
=
'int'
elif
dbfield
.
type
==
'time'
:
cfg
.
type
=
'date'
cfg
.
dateFormat
=
'H:i:s'
self
.
cfg_store
.
fields
.
append
(
cfg
)
def
_get_data
(
self
,
rows
):
""" Generate the Ext.data.Store.data property.
@type rows: gluon.dal.Rows
@param rows: data block to be loaded on the store.
@rtype: list of dictionary
@return: each dictionary contains the data for a row.
One key, value pair for each Ext.data.Field. The key is
equal to the Ext.data.Field name.
"""
for
row
in
rows
:
di
=
dict
()
for
field
in
self
.
cfg_store
.
fields
:
tablename
,
fieldname
,
keyname
=
self
.
_map
[
field
.
name
]
# get the value for a standard database field
if
keyname
==
None
:
value
=
row
[
tablename
][
fieldname
]
# get the value for a JSON database field
else
:
if
keyname
in
row
[
tablename
][
fieldname
]:
value
=
row
[
tablename
][
fieldname
][
keyname
]
else
:
value
=
""
# encode date
if
isinstance
(
value
,
date
):
value
=
value
.
strftime
(
"%Y-%m-%d"
)
# encode time delta
elif
isinstance
(
value
,
timedelta
):
value
=
value
.
total_seconds
()
di
[
field
.
name
]
=
value
self
.
cfg_store
.
data
.
append
(
di
)
views/report/grid.html
View file @
963cc543
...
...
@@ -16,16 +16,17 @@
#
# The title and the DIV block
#
divgrid = id(cfg_store)
divgrid =
"grid-%s" %
id(cfg_store)
response.write(H2(view.title, _class="dbui-h2 dbui-small-cap"))
response.write(DIV(_id=
"grid-%s" %
divgrid))
response.write(DIV(_id=divgrid))
#
# Export python variables to the javascript
#
jsvars = ["cfgStore = %s" %
json.dumps(
cfg_store
)
,
jsvars = ["cfgStore = %s" % cfg_store,
"columns = %s" % view.columns,
"divgrid = '%s'" % divgrid,
"features = %s" % view.features]
jsvars = " var %s;" % ',\n'.join(jsvars)
...
...
@@ -41,12 +42,12 @@
//
grid
=
Ext
.
create
(
'
App.grid.Panel
'
,
{
plugins
:
[
'
pGridExport
'
],
store
:
Ext
.
create
(
'
Ext.data.ArrayStore
'
,
cfgStore
)
,
store
:
cfgStore
,
columns
:
columns
,
features
:
features
,
forceFit
:
true
,
padding
:
"
10 40 20 30
"
,
renderTo
:
'
grid-{{=
divgrid
}}
'
renderTo
:
divgrid
});
</script>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment