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
aca48336
Commit
aca48336
authored
Feb 04, 2015
by
LE GAC Renaud
Browse files
Add the class StoreForYear2DView and first tentative to produce graph.
parent
5766e3d0
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
324 additions
and
8 deletions
+324
-8
controllers/report.py
controllers/report.py
+35
-2
models/vt_graph_selector.py
models/vt_graph_selector.py
+43
-0
models/widgets_viewport.py
models/widgets_viewport.py
+12
-0
modules/reporting_tools.py
modules/reporting_tools.py
+139
-6
views/report/graph.html
views/report/graph.html
+95
-0
No files found.
controllers/report.py
View file @
aca48336
...
...
@@ -16,9 +16,38 @@ from plugin_dbui import Store
from
reporting_tools
import
(
Report
,
StoreForListView
,
StoreForMetric1DView
,
StoreForMetric2DView
)
StoreForMetric2DView
,
StoreForYear2DView
)
def
graph
():
"""Plot 2D metric as a Ext.char.series.Area
"""
metric
=
db
.
metrics
[
request
.
vars
.
id_metrics
]
selector
=
virtdb
.
metric_selector_2D
report
=
Report
(
selector
,
exclude_fields
=
(
'category'
,
'metric'
,
'period_end'
,
'period_start'
,
'year'
))
# configure the Ext.data.Store
if
metric
.
field_vertical
==
'year'
:
store
=
StoreForYear2DView
(
metric
,
report
)
else
:
store
=
StoreForMetric2DView
(
metric
,
report
)
# Extra the stack keys (value for metric.field_vertical)
stack_keys
=
store
.
values_h
# delegate the rendering of the graph to the view
response
.
view
=
'report/graph.html'
return
dict
(
cfg_store
=
store
.
as_json
(),
stack_keys
=
stack_keys
,
view
=
metric
)
def
list
():
"""List renders by an Ext.grid.Panel.
...
...
@@ -146,7 +175,11 @@ def metric2D():
'year'
))
# configure the Ext.data.Store
store
=
StoreForMetric2DView
(
metric
,
report
)
if
metric
.
field_vertical
==
'year'
:
store
=
StoreForYear2DView
(
metric
,
report
)
else
:
store
=
StoreForMetric2DView
(
metric
,
report
)
# customize the standard view (Ext.grid.Panel)
view
=
Storage
(
columns
=
[],
features
=
[],
title
=
metric
.
title
)
...
...
models/vt_graph_selector.py
0 → 100644
View file @
aca48336
# -*- coding: utf-8 -*-
""" graph_selector
"""
virtdb
.
define_table
(
'graph_selector'
,
Field
(
'period_start'
,
'date'
,
default
=
'2012-01-01'
),
Field
(
'period_end'
,
'date'
,
default
=
'%s-12-31'
%
year
),
Field
(
'id_teams'
,
'reference teams'
,
label
=
T
(
'Team'
)),
Field
(
'category'
,
'string'
),
Field
(
'id_people_categories'
,
'reference people_categories'
,
label
=
T
(
"Quality"
)),
Field
(
'id_projects'
,
'reference projects'
,
label
=
T
(
'Project'
)),
Field
(
'metric'
,
'string'
,
default
=
'sum_fte'
))
virtdb
.
graph_selector
.
category
.
requires
=
IS_IN_SET
(
PEOPLE_CATEGORIES
)
virtdb
.
graph_selector
.
id_people_categories
.
requires
=
IS_IN_DB
(
db
,
'people_categories.code'
)
virtdb
.
graph_selector
.
id_projects
.
requires
=
IS_IN_DB
(
db
,
'projects.project'
)
virtdb
.
graph_selector
.
id_teams
.
requires
=
IS_IN_DB
(
db
,
'teams.team'
)
virtdb
.
graph_selector
.
metric
.
requires
=
IS_IN_SET
((
'count'
,
'sum_fte'
))
#-------------------------------------------------------------------------------
#
# FIELDS CONFIGURATiON
#
#-------------------------------------------------------------------------------
fieldsModifier
=
dbui
.
FieldsModifier
(
'graph_selector'
)
fieldsModifier
.
configure_field
(
'period_start'
,
flex
=
1
)
fieldsModifier
.
configure_field
(
'period_end'
,
flex
=
1
)
fieldsModifier
.
merge_fields
(
'period_start'
,
'period_end'
,
fieldLabel
=
T
(
'Period'
))
mytype
=
'xcomboboxuserreset'
text
=
T
(
'select...'
)
fieldsModifier
.
configure_field
(
'id_people_categories'
,
emptyText
=
text
,
xtype
=
mytype
)
fieldsModifier
.
configure_field
(
'id_teams'
,
emptyText
=
text
,
xtype
=
mytype
)
fieldsModifier
.
configure_field
(
'id_projects'
,
emptyText
=
text
,
xtype
=
mytype
)
#-------------------------------------------------------------------------------
#
# FORM CONFIGURATiON
#
#-------------------------------------------------------------------------------
models/widgets_viewport.py
View file @
aca48336
...
...
@@ -124,10 +124,22 @@ for row in db(db.metrics.id > 0).select(orderby=db.metrics.metric):
#-------------------------------------------------------------------------------
#
# GRAPH
# Define by the 2D metrics
#
#-------------------------------------------------------------------------------
graphNode
=
Node
(
T
(
'The graphs'
))
for
row
in
db
(
db
.
metrics
.
id
>
0
).
select
(
orderby
=
db
.
metrics
.
metric
):
if
not
row
.
field_horizontal
:
continue
leaf
=
PanelWithUrlSelector
(
virtdb
.
graph_selector
,
baseUrl
=
URL
(
'report'
,
'graph'
),
baseParams
=
{
'id_metrics'
:
row
.
id
})
graphNode
.
add_child
(
row
.
metric
,
leaf
)
#-------------------------------------------------------------------------------
#
# VIEWPORT
...
...
modules/reporting_tools.py
View file @
aca48336
...
...
@@ -275,6 +275,76 @@ class Report(SelectorActiveItems):
return
data
def
get_metric_per_year
(
self
,
groupby
,
metric
):
"""Compute the metric per year:
- history records follow the selector criteria.
- history record are grouped by year
The metric is:
- the number of items in a group
- the sum of fte for the items in the group
- the average age for the items in the group
@type grouby: str
@param groupby: database field encoded as C{tablename.fieldname}.
@type metric: str
@param metric: the metric to be used either count or sum_fte.
@rtype: list of dictionary
@return: the keys of the dictionary are C{group} and one
entrie per value of the groupby field. The value of the
group key is the year.
"""
db
=
current
.
globalenv
[
'db'
]
# save the period parameters
ref_start
=
self
.
period_start
ref_end
=
self
.
period_end
# the vertical axis, the range of years
years
=
range
(
ref_start
.
year
,
ref_end
.
year
+
1
)
# the horizontal axis, the group by values
tablename
,
fieldname
=
groupby
.
split
(
'.'
)
field
=
db
[
tablename
][
fieldname
]
rows
=
db
().
select
(
field
,
distinct
=
True
)
values_h
=
[
row
[
fieldname
]
for
row
in
rows
]
# prepare a template dictionary for each store row
tpl_row_h
=
dict
.
fromkeys
(
values_h
,
''
)
# scan the database
# data contains a list of dictionary
# the keys are group and one entries per value of the group by field
data
=
[]
for
year
in
years
:
self
.
period_start
=
date
(
year
,
1
,
1
)
self
.
period_end
=
date
(
year
,
12
,
31
)
di
=
dict
(
group
=
year
)
di
.
update
(
tpl_row_h
)
for
el
in
self
.
get_metric
(
groupby
):
if
metric
==
'count'
:
di
[
el
[
'group'
]]
=
el
[
'count'
]
elif
metric
==
'sum_fte'
:
di
[
el
[
'group'
]]
=
el
[
'sum_fte'
]
data
.
append
(
di
)
# restore the period parameters
self
.
perios_start
=
ref_start
self
.
period_end
=
ref_end
return
data
def
query
(
self
,
table
):
"""Supersede the base class method to handle category constraints.
...
...
@@ -335,15 +405,15 @@ class StoreFactory(object):
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/
@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
):
...
...
@@ -636,4 +706,67 @@ class StoreForMetric2DView(StoreFactory):
# build the tmp_di block of the store
for
k
in
tmp_di
.
iterkeys
():
self
.
cfg_store
.
data
.
append
(
tmp_di
[
k
])
class
StoreForYear2DView
(
StoreFactory
):
def
__init__
(
self
,
metric
,
report
):
"""
@type metric: gluon.dal.objects.Row
@param metric: the definition of the metric
@type report: Report
@param report:
"""
db
=
current
.
globalenv
[
'db'
]
StoreFactory
.
__init__
(
self
)
# get value along the horizontal axis
tablename
,
fieldname
=
metric
.
field_horizontal
.
split
(
'.'
)
field
=
db
[
tablename
][
fieldname
]
rows
=
db
().
select
(
field
,
distinct
=
True
)
self
.
values_h
=
[
row
[
fieldname
]
for
row
in
rows
]
self
.
_get_fields
()
self
.
_get_data
(
report
,
metric
.
field_horizontal
,
report
.
metric
)
def
_get_fields
(
self
):
""" Generate the Ext.data.Store.fields property.
The store contains the field group for the year and
one field per value of the horizontal database field.
Data are grouped per the group field values.
"""
self
.
cfg_store
.
fields
=
[
dict
(
name
=
'group'
,
type
=
'string'
)]
for
value
in
self
.
values_h
:
self
.
cfg_store
.
fields
.
append
(
dict
(
name
=
str
(
value
),
type
=
'float'
))
self
.
cfg_store
.
sorters
=
[
'group'
]
def
_get_data
(
self
,
report
,
groupby
,
metric
):
""" Generate the Ext.data.Store.data property.
It is a list of dictionaries. Each of them contains the data
for one row. One key, value pair for each Ext.data.Field.
The key is equal to the Ext.data.Field name.
@type report: Report
@param report:
@type groupby: str
@param groupby: the database field use for horizontal axis
@type metric: str
@param metric: the metric to be used either count or sum_fte.
"""
self
.
cfg_store
.
data
.
extend
(
report
.
get_metric_per_year
(
groupby
,
metric
))
\ No newline at end of file
views/report/graph.html
0 → 100644
View file @
aca48336
{{
#--------------------------------------------------------------------------
#
# The python controller return the variables:
# - cfg_store (string)
# - stack_keys (list)
# - view (Storage)
#
#--------------------------------------------------------------------------
#
# prepare the data
# - build unique DIV identifier
# - Title and DIV block
#
#--------------------------------------------------------------------------
import json
#
# unique identifier for the DIV block associated to the grid
#
divchart = "chart-%s" % id(cfg_store)
response.write(H2(view.title, _class="dbui-h2 dbui-small-cap"))
response.write(DIV(_id=divchart))
#
# Export python variables to the javascript
#
jsvars = ["axes",
"cfgStore = %s" % cfg_store,
"chart",
"divchart = '%s'" % divchart,
"series",
"seriesKeys = %s" % json.dumps(stack_keys)]
jsvars = " var %s;" % ',\n'.join(jsvars)
response.write(SCRIPT(jsvars), escape=False)
}}
<script>
console
.
log
(
1
,
seriesKeys
);
console
.
log
(
2
,
cfgStore
);
// the axes
axes
=
[{
type
:
'
Numeric
'
,
fields
:
seriesKeys
,
grid
:
true
,
minimum
:
0
,
minorTickSteps
:
1
,
position
:
'
left
'
},
{
type
:
'
Category
'
,
fields
:
[
'
group
'
],
grid
:
true
,
label
:
{
rotate
:
{
degrees
:
270
}
},
position
:
'
bottom
'
}];
// how to display the series
series
=
[{
type
:
'
area
'
,
//type: 'column',
style
:
{
opacity
:
0.8
},
xField
:
'
group
'
,
yField
:
seriesKeys
}];
// instantiate the chart
chart
=
Ext
.
create
(
'
Ext.chart.Chart
'
,
{
axes
:
axes
,
legend
:
{
labelFont
:
'
8px Helvetica, sans-serif
'
,
position
:
'
right
'
},
series
:
series
,
store
:
cfgStore
,
width
:
600
,
height
:
400
,
renderTo
:
divchart
});
// inhibit context menu on the rest of the panel
chart
.
getEl
().
up
(
'
.x-panel-body
'
).
on
(
'
contextmenu
'
,
function
(
event
)
{
event
.
stopEvent
();
});
</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