2013-11-08 15:41:14 +00:00
2013-11-12 08:38:27 +00:00
/* jshint undef: false */
2014-01-14 12:51:42 +00:00
( function ( ) {
2013-11-13 10:50:59 +00:00
'use strict' ;
2014-01-14 12:51:42 +00:00
var QWeb = openerp . web . qweb ;
2014-01-28 11:10:22 +00:00
var _lt = openerp . web . _lt ;
var _t = openerp . web . _t ;
2014-01-14 13:01:41 +00:00
nv . dev = false ; // sets nvd3 library in production mode
2011-06-17 13:25:50 +00:00
2014-01-21 14:30:34 +00:00
openerp . web _graph . Graph = openerp . web . Widget . extend ( {
2013-12-24 11:22:24 +00:00
template : 'GraphWidget' ,
2013-12-18 13:40:40 +00:00
2014-01-15 09:37:49 +00:00
// ----------------------------------------------------------------------
// Init stuff
// ----------------------------------------------------------------------
2014-01-10 11:35:57 +00:00
init : function ( parent , model , domain , options ) {
2013-12-18 13:40:40 +00:00
this . _super ( parent ) ;
this . model = model ;
2014-01-10 11:35:57 +00:00
this . domain = domain ;
2014-01-16 14:00:58 +00:00
this . mode = options . mode || 'pivot' ; // pivot, bar, pie, line
this . heatmap _mode = options . heatmap _mode || 'none' ;
2014-01-10 11:35:57 +00:00
this . visible _ui = options . visible _ui || true ;
2014-01-13 15:23:16 +00:00
this . bar _ui = options . bar _ui || 'group' ;
2014-01-21 14:30:34 +00:00
this . graph _view = options . graph _view || null ;
2014-01-10 11:35:57 +00:00
this . pivot _options = options ;
2014-02-05 13:14:06 +00:00
this . title = options . title || 'Data' ;
2013-12-18 15:07:56 +00:00
} ,
2013-11-08 15:20:48 +00:00
2013-12-18 13:40:40 +00:00
start : function ( ) {
var self = this ;
2014-01-24 15:16:35 +00:00
this . table = $ ( '<table>' ) ;
2013-12-18 13:40:40 +00:00
this . $ ( '.graph_main_content' ) . append ( this . table ) ;
2014-01-16 14:00:58 +00:00
2014-01-24 15:16:35 +00:00
var indexes = { 'pivot' : 0 , 'bar' : 1 , 'line' : 2 , 'chart' : 3 } ;
this . $ ( '.graph_mode_selection label' ) . eq ( indexes [ this . mode ] ) . addClass ( 'active' ) ;
2014-01-16 14:00:58 +00:00
if ( this . mode !== 'pivot' ) {
this . $ ( '.graph_heatmap label' ) . addClass ( 'disabled' ) ;
2014-02-26 14:39:19 +00:00
this . $ ( '.graph_main_content' ) . addClass ( 'graph_chart_mode' ) ;
2014-02-26 11:17:10 +00:00
} else {
2014-02-26 14:39:19 +00:00
this . $ ( '.graph_main_content' ) . addClass ( 'graph_pivot_mode' ) ;
2014-01-16 14:00:58 +00:00
}
2014-04-30 08:49:27 +00:00
// get search view
var parent = this . getParent ( ) ;
while ( ! ( parent instanceof openerp . web . ViewManager ) ) {
parent = parent . getParent ( ) ;
}
this . search _view = parent . searchview ;
2014-02-03 11:33:32 +00:00
openerp . session . rpc ( '/web_graph/check_xlwt' ) . then ( function ( result ) {
2014-04-22 14:59:18 +00:00
self . $ ( '.graph_options_selection label' ) . last ( ) . toggle ( result ) ;
2014-02-03 11:33:32 +00:00
} ) ;
2014-11-27 15:03:14 +00:00
return this . model . call ( 'fields_get' , {
context : this . graph _view . dataset . context
} ) . then ( function ( f ) {
2014-01-10 11:35:57 +00:00
self . fields = f ;
2014-10-21 12:57:52 +00:00
self . fields . _ _count = { field : '__count' , type : 'integer' , string : _t ( 'Count' ) } ;
2014-07-25 12:35:42 +00:00
self . groupby _fields = self . get _groupby _fields ( ) ;
2014-01-10 11:35:57 +00:00
self . measure _list = self . get _measures ( ) ;
self . add _measures _to _options ( ) ;
2014-01-21 14:30:34 +00:00
self . pivot _options . row _groupby = self . create _field _values ( self . pivot _options . row _groupby || [ ] ) ;
self . pivot _options . col _groupby = self . create _field _values ( self . pivot _options . col _groupby || [ ] ) ;
2014-10-21 12:57:52 +00:00
self . pivot _options . measures = self . create _field _values ( self . pivot _options . measures || [ { field : '__count' , type : 'integer' , string : 'Count' } ] ) ;
2014-01-10 11:35:57 +00:00
self . pivot = new openerp . web _graph . PivotTable ( self . model , self . domain , self . fields , self . pivot _options ) ;
2014-01-21 14:30:34 +00:00
self . pivot . update _data ( ) . then ( function ( ) {
self . display _data ( ) ;
if ( self . graph _view ) {
self . graph _view . register _groupby ( self . pivot . rows . groupby , self . pivot . cols . groupby ) ;
}
} ) ;
2014-05-09 09:09:35 +00:00
openerp . web . bus . on ( 'click' , self , function ( event ) {
2014-01-10 11:35:57 +00:00
if ( self . dropdown ) {
2014-05-09 09:09:35 +00:00
self . $row _clicked = $ ( event . target ) . closest ( 'tr' ) ;
2014-01-10 11:35:57 +00:00
self . dropdown . remove ( ) ;
self . dropdown = null ;
}
2013-12-11 13:11:48 +00:00
} ) ;
2014-01-17 14:43:03 +00:00
self . put _measure _checkmarks ( ) ;
2014-01-10 11:35:57 +00:00
} ) ;
} ,
2014-07-25 12:35:42 +00:00
get _groupby _fields : function ( ) {
var search _fields = this . get _search _fields ( ) ,
search _field _names = _ . pluck ( search _fields , 'field' ) ,
other _fields = [ ] ,
groupable _types = [ 'many2one' , 'char' , 'boolean' , 'selection' , 'date' , 'datetime' ] ;
_ . each ( this . fields , function ( val , key ) {
if ( ! _ . contains ( search _field _names , key ) &&
_ . contains ( groupable _types , val . type ) &&
val . store === true ) {
other _fields . push ( {
field : key ,
string : val . string ,
} ) ;
}
} ) ;
return search _fields . concat ( other _fields ) ;
} ,
2014-01-15 09:37:49 +00:00
// this method gets the fields that appear in the search view, under the
// 'Groupby' heading
2014-01-10 11:35:57 +00:00
get _search _fields : function ( ) {
2014-04-30 08:49:27 +00:00
var self = this ;
2014-01-10 11:35:57 +00:00
2014-05-20 14:18:03 +00:00
var groupbygroups = _ ( this . search _view . drawer . inputs ) . select ( function ( g ) {
2014-01-21 14:30:34 +00:00
return g instanceof openerp . web . search . GroupbyGroup ;
} ) ;
2014-01-27 15:23:24 +00:00
var filters = _ . flatten ( _ . pluck ( groupbygroups , 'filters' ) , true ) ,
groupbys = _ . flatten ( _ . map ( filters , function ( filter ) {
var groupby = py . eval ( filter . attrs . context ) . group _by ;
if ( ! ( groupby instanceof Array ) ) { groupby = [ groupby ] ; }
2014-02-04 11:31:35 +00:00
return _ . map ( groupby , function ( g ) {
return { field : g , filter : filter } ;
2014-01-27 15:23:24 +00:00
} ) ;
} ) ) ;
2014-01-21 14:30:34 +00:00
2014-01-27 15:23:24 +00:00
return _ . uniq ( _ . map ( groupbys , function ( groupby ) {
var field = groupby . field ,
filter = groupby . filter ,
2014-01-24 12:59:44 +00:00
raw _field = field . split ( ':' ) [ 0 ] ,
2014-01-24 15:16:35 +00:00
string = ( field === raw _field ) ? filter . attrs . string : self . fields [ raw _field ] . string ;
filter = ( field === raw _field ) ? filter : undefined ;
2014-01-24 12:59:44 +00:00
return { field : raw _field , string : string , filter : filter } ;
} ) , false , function ( filter ) { return filter . field ; } ) ;
2014-01-10 11:35:57 +00:00
} ,
2013-12-11 13:11:48 +00:00
2014-01-15 09:37:49 +00:00
// Extracts the integer/float fields which are not 'id'
2014-01-17 14:43:03 +00:00
get _measures : function ( ) {
2014-01-24 15:16:35 +00:00
return _ . compact ( _ . map ( this . fields , function ( f , id ) {
2014-06-13 11:32:24 +00:00
if ( ( ( f . type === 'integer' ) || ( f . type === 'float' ) ) &&
( id !== 'id' ) &&
( f . store !== false ) ) {
2014-01-24 15:16:35 +00:00
return { field : id , type : f . type , string : f . string } ;
2013-12-18 13:40:40 +00:00
}
2014-01-24 15:16:35 +00:00
} ) ) ;
2012-05-07 08:19:08 +00:00
} ,
2013-11-08 15:20:48 +00:00
2014-01-15 09:37:49 +00:00
add _measures _to _options : function ( ) {
2014-01-24 15:16:35 +00:00
this . $ ( '.graph_measure_selection' ) . append (
_ . map ( this . measure _list , function ( measure ) {
return $ ( '<li>' ) . append ( $ ( '<a>' ) . attr ( 'data-choice' , measure . field )
2014-01-15 09:37:49 +00:00
. attr ( 'href' , '#' )
2014-01-24 15:16:35 +00:00
. text ( measure . string ) ) ;
} ) ) ;
2014-01-15 09:37:49 +00:00
} ,
2014-01-10 11:35:57 +00:00
2014-01-15 09:37:49 +00:00
// ----------------------------------------------------------------------
// Configuration methods
// ----------------------------------------------------------------------
2014-08-21 07:03:12 +00:00
set : function ( domain , row _groupby , col _groupby , measures _groupby ) {
2014-01-21 14:30:34 +00:00
if ( ! this . pivot ) {
2014-01-10 14:08:37 +00:00
this . pivot _options . domain = domain ;
this . pivot _options . row _groupby = row _groupby ;
this . pivot _options . col _groupby = col _groupby ;
2014-08-21 07:03:12 +00:00
this . pivot _options . measures _groupby = measures _groupby ;
2014-01-21 14:30:34 +00:00
return ;
}
var row _gbs = this . create _field _values ( row _groupby ) ,
col _gbs = this . create _field _values ( col _groupby ) ,
2014-08-21 07:03:12 +00:00
measures _gbs = this . create _field _values ( measures _groupby ) ,
2014-01-21 14:30:34 +00:00
dom _changed = ! _ . isEqual ( this . pivot . domain , domain ) ,
2014-01-22 16:07:07 +00:00
row _gb _changed = ! _ . isEqual ( row _gbs , this . pivot . rows . groupby ) ,
col _gb _changed = ! _ . isEqual ( col _gbs , this . pivot . cols . groupby ) ,
2014-08-21 07:03:12 +00:00
measures _gb _changed = ! _ . isEqual ( measures _gbs , this . pivot . measures ) ,
2014-01-21 14:30:34 +00:00
row _reduced = is _strict _beginning _of ( row _gbs , this . pivot . rows . groupby ) ,
2014-08-21 07:03:12 +00:00
col _reduced = is _strict _beginning _of ( col _gbs , this . pivot . cols . groupby ) ,
measures _reduced = is _strict _beginning _of ( measures _gbs , this . pivot . measures ) ;
2014-01-21 14:30:34 +00:00
2014-08-21 07:03:12 +00:00
if ( ! dom _changed && row _reduced && ! col _gb _changed && ! measures _gb _changed ) {
2014-01-21 14:30:34 +00:00
this . pivot . fold _with _depth ( this . pivot . rows , row _gbs . length ) ;
this . display _data ( ) ;
return ;
}
2014-08-21 07:03:12 +00:00
if ( ! dom _changed && col _reduced && ! row _gb _changed && ! measures _gb _changed ) {
2014-01-21 14:30:34 +00:00
this . pivot . fold _with _depth ( this . pivot . cols , col _gbs . length ) ;
this . display _data ( ) ;
return ;
}
2014-08-21 07:03:12 +00:00
if ( ! dom _changed && col _reduced && row _reduced && ! measures _gb _changed ) {
2014-02-25 10:42:33 +00:00
this . pivot . fold _with _depth ( this . pivot . rows , row _gbs . length ) ;
this . pivot . fold _with _depth ( this . pivot . cols , col _gbs . length ) ;
this . display _data ( ) ;
return ;
}
2014-08-21 07:03:12 +00:00
if ( dom _changed || row _gb _changed || col _gb _changed || measures _gb _changed ) {
this . pivot . set ( domain , row _gbs , col _gbs , measures _gbs ) . then ( this . proxy ( 'display_data' ) ) ;
}
if ( measures _gb _changed ) {
this . put _measure _checkmarks ( ) ;
2014-01-10 11:35:57 +00:00
}
} ,
set _mode : function ( mode ) {
2014-01-10 14:08:37 +00:00
this . mode = mode ;
2014-01-16 14:00:58 +00:00
if ( mode === 'pivot' ) {
this . $ ( '.graph_heatmap label' ) . removeClass ( 'disabled' ) ;
2014-02-26 14:39:19 +00:00
this . $ ( '.graph_main_content' ) . removeClass ( 'graph_chart_mode' ) . addClass ( 'graph_pivot_mode' ) ;
2014-01-16 14:00:58 +00:00
} else {
this . $ ( '.graph_heatmap label' ) . addClass ( 'disabled' ) ;
2014-02-26 14:39:19 +00:00
this . $ ( '.graph_main_content' ) . removeClass ( 'graph_pivot_mode' ) . addClass ( 'graph_chart_mode' ) ;
2014-01-17 14:43:03 +00:00
}
2014-01-16 14:00:58 +00:00
this . display _data ( ) ;
} ,
set _heatmap _mode : function ( mode ) { // none, row, col, all
this . heatmap _mode = mode ;
if ( mode === 'none' ) {
this . $ ( '.graph_heatmap label' ) . removeClass ( 'disabled' ) ;
this . $ ( '.graph_heatmap label' ) . removeClass ( 'active' ) ;
}
2014-01-10 14:08:37 +00:00
this . display _data ( ) ;
2014-01-10 11:35:57 +00:00
} ,
2014-01-21 14:30:34 +00:00
create _field _value : function ( f ) {
2014-01-22 16:07:07 +00:00
var field = ( _ . contains ( f , ':' ) ) ? f . split ( ':' ) [ 0 ] : f ,
2014-07-25 12:35:42 +00:00
groupby _field = _ . findWhere ( this . groupby _fields , { field : field } ) ,
2014-01-22 16:07:07 +00:00
string = groupby _field ? groupby _field . string : this . fields [ field ] . string ,
2015-01-07 08:52:14 +00:00
result = { field : f , string : string , type : this . fields [ field ] . type , digits : this . fields [ field ] . digits } ;
2014-01-21 14:30:34 +00:00
2014-01-22 16:07:07 +00:00
if ( groupby _field ) {
result . filter = groupby _field . filter ;
2014-01-22 13:34:52 +00:00
}
2014-01-22 16:07:07 +00:00
2014-01-21 14:30:34 +00:00
return result ;
2014-01-10 11:35:57 +00:00
} ,
2014-01-21 14:30:34 +00:00
create _field _values : function ( field _ids ) {
2014-01-22 16:07:07 +00:00
return _ . map ( field _ids , this . proxy ( 'create_field_value' ) ) ;
2014-01-21 14:30:34 +00:00
} ,
2014-01-22 16:07:07 +00:00
get _col _groupbys : function ( ) {
return _ . pluck ( this . pivot . cols . groupby , 'field' ) ;
} ,
2014-08-21 07:03:12 +00:00
get _current _measures : function ( ) {
return _ . pluck ( this . pivot . measures , 'field' ) ;
} ,
2014-01-15 09:37:49 +00:00
// ----------------------------------------------------------------------
// UI code
// ----------------------------------------------------------------------
events : {
2014-01-16 14:00:58 +00:00
'click .graph_mode_selection label' : 'mode_selection' ,
2014-01-15 09:37:49 +00:00
'click .graph_measure_selection li' : 'measure_selection' ,
2014-01-16 14:00:58 +00:00
'click .graph_options_selection label' : 'option_selection' ,
'click .graph_heatmap label' : 'heatmap_mode_selection' ,
2014-01-15 09:37:49 +00:00
'click .web_graph_click' : 'header_cell_clicked' ,
'click a.field-selection' : 'field_selection' ,
2013-11-22 13:59:27 +00:00
} ,
2013-12-05 10:07:10 +00:00
mode _selection : function ( event ) {
event . preventDefault ( ) ;
2014-01-24 15:16:35 +00:00
var mode = event . currentTarget . getAttribute ( 'data-mode' ) ;
2014-01-10 14:08:37 +00:00
this . set _mode ( mode ) ;
2013-12-05 10:07:10 +00:00
} ,
measure _selection : function ( event ) {
event . preventDefault ( ) ;
2014-01-17 15:24:13 +00:00
event . stopPropagation ( ) ;
2014-01-24 15:16:35 +00:00
var measure _field = event . target . getAttribute ( 'data-choice' ) ;
2015-01-07 08:52:14 +00:00
var measure = this . create _field _value ( measure _field ) ;
2014-01-21 14:30:34 +00:00
this . pivot . toggle _measure ( measure ) . then ( this . proxy ( 'display_data' ) ) ;
2014-01-17 14:43:03 +00:00
this . put _measure _checkmarks ( ) ;
} ,
put _measure _checkmarks : function ( ) {
var self = this ,
measures _li = this . $ ( '.graph_measure_selection a' ) ;
measures _li . removeClass ( 'oe_selected' ) ;
_ . each ( this . measure _list , function ( measure , index ) {
if ( _ . findWhere ( self . pivot . measures , measure ) ) {
measures _li . eq ( index ) . addClass ( 'oe_selected' ) ;
}
} ) ;
2013-12-05 10:07:10 +00:00
} ,
2013-12-12 10:55:33 +00:00
option _selection : function ( event ) {
2013-12-05 10:07:10 +00:00
event . preventDefault ( ) ;
2014-01-24 15:16:35 +00:00
switch ( event . currentTarget . getAttribute ( 'data-choice' ) ) {
2013-12-12 10:55:33 +00:00
case 'swap_axis' :
2014-01-21 14:30:34 +00:00
this . swap _axis ( ) ;
2013-12-05 10:07:10 +00:00
break ;
2014-04-28 09:02:21 +00:00
case 'expand_all' :
this . pivot . expand _all ( ) . then ( this . proxy ( 'display_data' ) ) ;
break ;
2013-12-05 10:07:10 +00:00
case 'update_values' :
2014-01-21 14:30:34 +00:00
this . pivot . update _data ( ) . then ( this . proxy ( 'display_data' ) ) ;
2013-12-05 10:07:10 +00:00
break ;
2014-02-03 11:33:32 +00:00
case 'export_data' :
this . export _xls ( ) ;
break ;
2013-12-05 10:07:10 +00:00
}
} ,
2014-01-16 14:00:58 +00:00
heatmap _mode _selection : function ( event ) {
event . preventDefault ( ) ;
2014-01-24 15:16:35 +00:00
var mode = event . currentTarget . getAttribute ( 'data-mode' ) ;
2014-01-16 14:00:58 +00:00
if ( this . heatmap _mode === mode ) {
event . stopPropagation ( ) ;
this . set _heatmap _mode ( 'none' ) ;
} else {
this . set _heatmap _mode ( mode ) ;
}
} ,
2013-12-18 13:40:40 +00:00
header _cell _clicked : function ( event ) {
2013-12-05 10:07:10 +00:00
event . preventDefault ( ) ;
event . stopPropagation ( ) ;
2014-01-24 15:16:35 +00:00
var id = event . target . getAttribute ( 'data-id' ) ,
2013-12-18 13:40:40 +00:00
header = this . pivot . get _header ( id ) ,
2013-12-24 11:22:24 +00:00
self = this ;
2013-12-18 13:40:40 +00:00
2014-01-10 11:35:57 +00:00
if ( header . expanded ) {
2014-05-08 12:40:02 +00:00
if ( header . root === this . pivot . rows ) {
this . fold _row ( header , event ) ;
} else {
this . fold _col ( header ) ;
}
2014-02-10 09:17:16 +00:00
return ;
2014-04-22 15:02:09 +00:00
}
2014-02-10 09:17:16 +00:00
if ( header . path . length < header . root . groupby . length ) {
2014-05-09 09:09:35 +00:00
this . $row _clicked = $ ( event . target ) . closest ( 'tr' ) ;
2014-02-10 09:17:16 +00:00
this . expand ( id ) ;
return ;
2014-04-22 15:02:09 +00:00
}
2014-07-25 12:35:42 +00:00
if ( ! this . groupby _fields . length ) {
2014-02-10 09:17:16 +00:00
return ;
}
2014-01-24 12:59:44 +00:00
2014-07-25 12:35:42 +00:00
var fields = _ . map ( this . groupby _fields , function ( field ) {
2014-02-10 09:17:16 +00:00
return { id : field . field , value : field . string , type : self . fields [ field . field . split ( ':' ) [ 0 ] ] . type } ;
} ) ;
if ( this . dropdown ) {
this . dropdown . remove ( ) ;
2013-12-18 13:40:40 +00:00
}
2014-02-10 09:17:16 +00:00
this . dropdown = $ ( QWeb . render ( 'field_selection' , { fields : fields , header _id : id } ) ) ;
$ ( event . target ) . after ( this . dropdown ) ;
2014-08-22 10:52:58 +00:00
this . dropdown . css ( {
position : 'absolute' ,
left : event . originalEvent . layerX ,
} ) ;
this . $ ( '.field-selection' ) . next ( '.dropdown-menu' ) . first ( ) . toggle ( ) ;
2013-12-05 10:07:10 +00:00
} ,
field _selection : function ( event ) {
2014-01-24 15:16:35 +00:00
var id = event . target . getAttribute ( 'data-id' ) ,
field _id = event . target . getAttribute ( 'data-field-id' ) ,
2014-01-22 16:07:07 +00:00
interval ,
groupby = this . create _field _value ( field _id ) ;
2013-12-05 10:07:10 +00:00
event . preventDefault ( ) ;
2014-01-13 13:38:00 +00:00
if ( this . fields [ field _id ] . type === 'date' || this . fields [ field _id ] . type === 'datetime' ) {
2014-01-24 15:28:21 +00:00
interval = event . target . getAttribute ( 'data-interval' ) ;
2014-01-22 16:07:07 +00:00
groupby . field = groupby . field + ':' + interval ;
2014-01-13 13:38:00 +00:00
}
2014-01-22 16:07:07 +00:00
this . expand ( id , groupby ) ;
2013-11-22 13:59:27 +00:00
} ,
2014-01-21 14:30:34 +00:00
// ----------------------------------------------------------------------
// Pivot Table integration
// ----------------------------------------------------------------------
2014-01-22 16:07:07 +00:00
expand : function ( header _id , groupby ) {
2014-01-21 14:30:34 +00:00
var self = this ,
header = this . pivot . get _header ( header _id ) ,
2014-01-24 15:16:35 +00:00
update _groupby = ! ! groupby ;
groupby = groupby || header . root . groupby [ header . path . length ] ;
2014-01-21 14:30:34 +00:00
this . pivot . expand ( header _id , groupby ) . then ( function ( ) {
2014-05-09 09:09:35 +00:00
if ( header . root === self . pivot . rows ) {
// expanding rows can be done by only inserting in the dom
// console.log(event.target);
var rows = self . build _rows ( header . children ) ;
var doc _fragment = $ ( document . createDocumentFragment ( ) ) ;
rows . map ( function ( row ) {
2014-09-16 08:11:47 +00:00
doc _fragment . append ( self . draw _row ( row , 0 ) ) ;
2014-05-09 09:09:35 +00:00
} ) ;
self . $row _clicked . after ( doc _fragment ) ;
} else {
// expanding cols will redraw the full table
self . display _data ( ) ;
}
2014-01-21 14:30:34 +00:00
if ( update _groupby && self . graph _view ) {
self . graph _view . register _groupby ( self . pivot . rows . groupby , self . pivot . cols . groupby ) ;
}
} ) ;
} ,
2014-05-08 12:40:02 +00:00
fold _row : function ( header , event ) {
var rows _before = this . pivot . rows . headers . length ,
update _groupby = this . pivot . fold ( header ) ,
rows _after = this . pivot . rows . headers . length ,
rows _removed = rows _before - rows _after ;
if ( rows _after === 1 ) {
// probably faster to redraw the unique row instead of removing everything
this . display _data ( ) ;
} else {
var $row = $ ( event . target ) . parent ( ) . parent ( ) ;
$row . nextAll ( ) . slice ( 0 , rows _removed ) . remove ( ) ;
}
if ( update _groupby && this . graph _view ) {
this . graph _view . register _groupby ( this . pivot . rows . groupby , this . pivot . cols . groupby ) ;
}
} ,
2014-01-21 14:30:34 +00:00
2014-05-08 12:40:02 +00:00
fold _col : function ( header ) {
var update _groupby = this . pivot . fold ( header ) ;
2014-01-21 14:30:34 +00:00
this . display _data ( ) ;
if ( update _groupby && this . graph _view ) {
this . graph _view . register _groupby ( this . pivot . rows . groupby , this . pivot . cols . groupby ) ;
}
} ,
swap _axis : function ( ) {
this . pivot . swap _axis ( ) ;
this . display _data ( ) ;
this . graph _view . register _groupby ( this . pivot . rows . groupby , this . pivot . cols . groupby ) ;
} ,
2014-02-04 11:31:35 +00:00
// ----------------------------------------------------------------------
// Convert Pivot data structure into table structure :
// compute rows, cols, colors, cell width, cell height, ...
// ----------------------------------------------------------------------
2014-04-04 08:55:04 +00:00
build _table : function ( raw ) {
2014-02-04 11:31:35 +00:00
return {
headers : this . build _headers ( ) ,
measure _row : this . build _measure _row ( ) ,
2014-05-09 09:09:35 +00:00
rows : this . build _rows ( this . pivot . rows . headers , raw ) ,
2014-02-05 13:14:06 +00:00
nbr _measures : this . pivot . measures . length ,
title : this . title ,
2014-02-04 11:31:35 +00:00
} ;
} ,
build _headers : function ( ) {
var pivot = this . pivot ,
nbr _measures = pivot . measures . length ,
2014-07-25 12:35:42 +00:00
height = _ . max ( _ . map ( pivot . cols . headers , function ( g ) { return g . path . length ; } ) ) + 1 ,
2014-02-04 11:31:35 +00:00
rows = [ ] ;
_ . each ( pivot . cols . headers , function ( col ) {
var cell _width = nbr _measures * ( col . expanded ? pivot . get _ancestor _leaves ( col ) . length : 1 ) ,
2014-07-25 12:35:42 +00:00
cell _height = col . expanded ? 1 : height - col . path . length ,
2014-02-04 11:31:35 +00:00
cell = { width : cell _width , height : cell _height , title : col . title , id : col . id , expanded : col . expanded } ;
2014-07-25 12:35:42 +00:00
if ( rows [ col . path . length ] ) {
rows [ col . path . length ] . push ( cell ) ;
2014-02-04 11:31:35 +00:00
} else {
2014-07-25 12:35:42 +00:00
rows [ col . path . length ] = [ cell ] ;
2014-02-04 11:31:35 +00:00
}
} ) ;
if ( pivot . get _cols _leaves ( ) . length > 1 ) {
2014-07-25 12:35:42 +00:00
rows [ 0 ] . push ( { width : nbr _measures , height : height , title : ' ' , id : pivot . main _col ( ) . id } ) ;
2014-02-04 11:31:35 +00:00
}
if ( pivot . cols . headers . length === 1 ) {
2014-02-05 13:14:06 +00:00
rows = [ [ { width : nbr _measures , height : 1 , title : _t ( 'Total' ) , id : pivot . main _col ( ) . id , expanded : false } ] ] ;
2014-02-04 11:31:35 +00:00
}
return rows ;
} ,
build _measure _row : function ( ) {
var nbr _leaves = this . pivot . get _cols _leaves ( ) . length ,
nbr _cols = nbr _leaves + ( ( nbr _leaves > 1 ) ? 1 : 0 ) ,
result = [ ] ,
add _total = this . pivot . get _cols _leaves ( ) . length > 1 ,
i , m ;
for ( i = 0 ; i < nbr _cols ; i ++ ) {
for ( m = 0 ; m < this . pivot . measures . length ; m ++ ) {
result . push ( {
text : this . pivot . measures [ m ] . string ,
is _bold : add _total && ( i === nbr _cols - 1 )
} ) ;
}
}
return result ;
} ,
2014-04-04 08:55:04 +00:00
make _cell : function ( row , col , value , index , raw ) {
2015-01-07 08:52:14 +00:00
var formatted _value = raw && ! _ . isUndefined ( value ) ? value : openerp . web . format _value ( value , this . pivot . measures [ index ] ) ,
2014-02-05 09:58:08 +00:00
cell = { value : formatted _value } ;
2014-02-04 11:31:35 +00:00
if ( this . heatmap _mode === 'none' ) { return cell ; }
var total = ( this . heatmap _mode === 'both' ) ? this . pivot . get _total ( ) [ index ]
: ( this . heatmap _mode === 'row' ) ? this . pivot . get _total ( row ) [ index ]
: this . pivot . get _total ( col ) [ index ] ;
2014-02-05 09:58:08 +00:00
var color = Math . floor ( 90 + 165 * ( total - Math . abs ( value ) ) / total ) ;
2014-02-04 11:31:35 +00:00
if ( color < 255 ) {
cell . color = color ;
}
return cell ;
} ,
2014-05-09 09:09:35 +00:00
build _rows : function ( headers , raw ) {
2014-02-04 11:31:35 +00:00
var self = this ,
pivot = this . pivot ,
2014-04-30 07:47:33 +00:00
m , i , j , k , cell , row ;
var rows = [ ] ;
var cells , pivot _cells , values ;
2014-05-09 09:09:35 +00:00
var nbr _of _rows = headers . length ;
2014-04-30 07:47:33 +00:00
var col _headers = pivot . get _cols _leaves ( ) ;
for ( i = 0 ; i < nbr _of _rows ; i ++ ) {
2014-05-09 09:09:35 +00:00
row = headers [ i ] ;
2014-04-30 07:47:33 +00:00
cells = [ ] ;
pivot _cells = [ ] ;
for ( j = 0 ; j < pivot . cells . length ; j ++ ) {
if ( pivot . cells [ j ] . x == row . id || pivot . cells [ j ] . y == row . id ) {
pivot _cells . push ( pivot . cells [ j ] ) ;
}
2014-04-09 09:39:20 +00:00
}
2014-04-30 07:47:33 +00:00
for ( j = 0 ; j < col _headers . length ; j ++ ) {
values = undefined ;
for ( k = 0 ; k < pivot _cells . length ; k ++ ) {
if ( pivot _cells [ k ] . x == col _headers [ j ] . id || pivot _cells [ k ] . y == col _headers [ j ] . id ) {
values = pivot _cells [ k ] . values ;
2014-04-09 09:39:20 +00:00
break ;
2014-04-30 07:47:33 +00:00
}
2014-04-09 09:39:20 +00:00
}
if ( ! values ) { values = new Array ( pivot . measures . length ) ; }
2014-02-04 11:31:35 +00:00
for ( m = 0 ; m < pivot . measures . length ; m ++ ) {
2014-04-30 07:47:33 +00:00
cells . push ( self . make _cell ( row , col _headers [ j ] , values [ m ] , m , raw ) ) ;
2014-02-04 11:31:35 +00:00
}
2014-04-30 07:47:33 +00:00
}
if ( col _headers . length > 1 ) {
2014-02-04 11:31:35 +00:00
var totals = pivot . get _total ( row ) ;
for ( m = 0 ; m < pivot . measures . length ; m ++ ) {
2014-04-30 07:47:33 +00:00
cell = self . make _cell ( row , pivot . cols . headers [ 0 ] , totals [ m ] , m , raw ) ;
2014-02-05 09:58:08 +00:00
cell . is _bold = 'true' ;
cells . push ( cell ) ;
2014-02-04 11:31:35 +00:00
}
}
2014-04-30 07:47:33 +00:00
rows . push ( {
2014-02-04 11:31:35 +00:00
id : row . id ,
indent : row . path . length ,
title : row . title ,
expanded : row . expanded ,
cells : cells ,
2014-04-30 07:47:33 +00:00
} ) ;
}
return rows ;
2014-02-04 11:31:35 +00:00
} ,
2014-01-15 09:37:49 +00:00
// ----------------------------------------------------------------------
// Main display method
// ----------------------------------------------------------------------
display _data : function ( ) {
2014-04-22 15:03:16 +00:00
var scroll = $ ( window ) . scrollTop ( ) ;
2014-01-15 09:37:49 +00:00
this . $ ( '.graph_main_content svg' ) . remove ( ) ;
this . $ ( '.graph_main_content div' ) . remove ( ) ;
this . table . empty ( ) ;
2014-02-03 11:33:32 +00:00
this . table . toggleClass ( 'heatmap' , this . heatmap _mode !== 'none' ) ;
2014-04-22 14:59:55 +00:00
this . $ ( '.graph_options_selection label' ) . last ( ) . toggleClass ( 'disabled' , this . pivot . no _data ) ;
2014-01-21 14:30:34 +00:00
this . width = this . $el . width ( ) ;
this . height = Math . min ( Math . max ( document . documentElement . clientHeight - 116 - 60 , 250 ) , Math . round ( 0.8 * this . $el . width ( ) ) ) ;
2014-01-15 09:37:49 +00:00
2014-01-24 15:16:35 +00:00
this . $ ( '.graph_header' ) . toggle ( this . visible _ui ) ;
2014-01-15 09:37:49 +00:00
if ( this . pivot . no _data ) {
this . $ ( '.graph_main_content' ) . append ( $ ( QWeb . render ( 'graph_no_data' ) ) ) ;
} else {
2014-01-16 14:00:58 +00:00
if ( this . mode === 'pivot' ) {
2014-01-15 09:37:49 +00:00
this . draw _table ( ) ;
2014-04-22 15:03:16 +00:00
$ ( window ) . scrollTop ( scroll ) ;
2014-01-15 09:37:49 +00:00
} else {
2014-01-24 15:16:35 +00:00
this . $ ( '.graph_main_content' ) . append ( $ ( '<div><svg>' ) ) ;
2014-01-15 09:37:49 +00:00
this . svg = this . $ ( '.graph_main_content svg' ) [ 0 ] ;
this [ this . mode ] ( ) ;
}
}
} ,
// ----------------------------------------------------------------------
// Drawing the table
// ----------------------------------------------------------------------
2013-11-22 07:43:27 +00:00
draw _table : function ( ) {
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
var custom _gbs = this . graph _view . get _custom _filter _groupbys ( ) ,
frozen _rows = custom _gbs . groupby . length ,
frozen _cols = custom _gbs . col _groupby . length ;
2014-02-04 11:31:35 +00:00
var table = this . build _table ( ) ;
2014-04-30 07:47:33 +00:00
var doc _fragment = $ ( document . createDocumentFragment ( ) ) ;
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
this . draw _headers ( table . headers , doc _fragment , frozen _cols ) ;
2014-04-30 07:47:33 +00:00
this . draw _measure _row ( table . measure _row , doc _fragment ) ;
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
this . draw _rows ( table . rows , doc _fragment , frozen _rows ) ;
2014-04-30 07:47:33 +00:00
this . table . append ( doc _fragment ) ;
2014-02-04 11:31:35 +00:00
} ,
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
make _header _cell : function ( header , frozen ) {
2014-02-04 11:31:35 +00:00
var cell = ( _ . has ( header , 'cells' ) ? $ ( '<td>' ) : $ ( '<th>' ) )
. addClass ( 'graph_border' )
. attr ( 'rowspan' , header . height )
. attr ( 'colspan' , header . width ) ;
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
var $content = $ ( '<span>' ) . attr ( 'href' , '#' )
2014-02-04 11:31:35 +00:00
. text ( ' ' + ( header . title || _t ( 'Undefined' ) ) )
2014-05-08 11:00:27 +00:00
. css ( 'margin-left' , header . indent * 30 + 'px' )
2014-02-04 11:31:35 +00:00
. attr ( 'data-id' , header . id ) ;
if ( _ . has ( header , 'expanded' ) ) {
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
if ( ( 'indent' in header ) && header . indent >= frozen ) {
$content . addClass ( header . expanded ? 'fa fa-minus-square' : 'fa fa-plus-square' ) ;
$content . addClass ( 'web_graph_click' ) ;
}
if ( ! ( 'indent' in header ) && header . lvl >= frozen ) {
$content . addClass ( header . expanded ? 'fa fa-minus-square' : 'fa fa-plus-square' ) ;
$content . addClass ( 'web_graph_click' ) ;
}
2013-11-22 09:43:22 +00:00
} else {
2014-05-08 11:13:11 +00:00
$content . css ( 'font-weight' , 'bold' ) ;
2013-11-22 09:43:22 +00:00
}
2014-05-08 11:13:11 +00:00
return cell . append ( $content ) ;
2013-11-18 15:26:20 +00:00
} ,
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
draw _headers : function ( headers , doc _fragment , frozen _cols ) {
2014-02-04 11:31:35 +00:00
var make _cell = this . make _header _cell ,
2014-05-08 11:13:11 +00:00
$empty _cell = $ ( '<th>' ) . attr ( 'rowspan' , headers . length ) ,
$thead = $ ( '<thead>' ) ;
2014-01-03 14:22:15 +00:00
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
_ . each ( headers , function ( row , lvl ) {
2014-05-08 11:13:11 +00:00
var $row = $ ( '<tr>' ) ;
2014-02-04 11:31:35 +00:00
_ . each ( row , function ( header ) {
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
header . lvl = lvl ;
$row . append ( make _cell ( header , frozen _cols ) ) ;
2014-02-04 11:31:35 +00:00
} ) ;
2014-05-08 11:13:11 +00:00
$thead . append ( $row ) ;
2014-01-03 14:22:15 +00:00
} ) ;
2014-05-08 11:13:11 +00:00
$thead . children ( ':first' ) . prepend ( $empty _cell ) ;
doc _fragment . append ( $thead ) ;
this . $thead = $thead ;
2014-02-04 11:31:35 +00:00
} ,
2014-05-09 09:09:35 +00:00
draw _measure _row : function ( measure _row ) {
2014-05-08 11:13:11 +00:00
var $row = $ ( '<tr>' ) . append ( '<th>' ) ;
2014-02-04 11:31:35 +00:00
_ . each ( measure _row , function ( cell ) {
2014-05-08 11:13:11 +00:00
var $cell = $ ( '<th>' ) . addClass ( 'measure_row' ) . text ( cell . text ) ;
if ( cell . is _bold ) { $cell . css ( 'font-weight' , 'bold' ) ; }
$row . append ( $cell ) ;
2014-02-04 11:31:35 +00:00
} ) ;
2014-05-08 11:13:11 +00:00
this . $thead . append ( $row ) ;
2014-02-04 11:31:35 +00:00
} ,
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
draw _row : function ( row , frozen _rows ) {
2014-05-09 09:09:35 +00:00
var $row = $ ( '<tr>' )
. attr ( 'data-indent' , row . indent )
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
. append ( this . make _header _cell ( row , frozen _rows ) ) ;
2014-04-30 07:47:33 +00:00
2014-05-09 09:09:35 +00:00
var cells _length = row . cells . length ;
var cells _list = [ ] ;
var cell , hcell ;
for ( var j = 0 ; j < cells _length ; j ++ ) {
cell = row . cells [ j ] ;
hcell = '<td' ;
if ( cell . is _bold || cell . color ) {
hcell += ' style="' ;
if ( cell . is _bold ) hcell += 'font-weight: bold;' ;
if ( cell . color ) hcell += 'background-color:' + $ . Color ( 255 , cell . color , cell . color ) + ';' ;
hcell += '"' ;
}
hcell += '>' + cell . value + '</td>' ;
cells _list [ j ] = hcell ;
}
return $row . append ( cells _list . join ( '' ) ) ;
} ,
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
draw _rows : function ( rows , doc _fragment , frozen _rows ) {
2014-05-09 09:09:35 +00:00
var rows _length = rows . length ,
$tbody = $ ( '<tbody>' ) ;
2014-05-08 11:27:23 +00:00
doc _fragment . append ( $tbody ) ;
2014-05-09 09:09:35 +00:00
for ( var i = 0 ; i < rows _length ; i ++ ) {
[FIX] web: fixes issues with custom filters and search view
The problem was that when the user manipulates the graph view (in pivot
table mode), the graph view resetted the group by facet in the search
view. It was not a problem unless a custom filter with a groupby was
already there, in which case, the group bys were duplicated.
The search view is now smarter, it only resets the additional groupbys
(and col_groupbys). Also, to prevent usability problems, the graph
view disable the '+/-' groupbys added by a custom filters.
Note that this fix is only temporary: a revamp of custom filters, facets,
search view is coming in the next months. (at least, that's the idea). Right
now, too much 'search logic' is in the graph view.
Another note: this fix is somewhat fragile: it makes some assumptions
about the search query (mainly that the custom filter is the first facet,
also, that no other filters add groupbys/col_groupbys)
2014-09-09 10:26:16 +00:00
$tbody . append ( this . draw _row ( rows [ i ] , frozen _rows ) ) ;
2014-04-30 07:47:33 +00:00
}
2013-11-27 14:45:05 +00:00
} ,
2013-12-18 13:40:40 +00:00
2014-01-15 09:37:49 +00:00
// ----------------------------------------------------------------------
// Drawing charts code
// ----------------------------------------------------------------------
2014-01-10 14:08:37 +00:00
bar : function ( ) {
2013-12-18 15:07:56 +00:00
var self = this ,
dim _x = this . pivot . rows . groupby . length ,
dim _y = this . pivot . cols . groupby . length ,
2014-01-17 14:50:56 +00:00
show _controls = ( this . width > 400 && this . height > 300 && dim _x + dim _y >= 2 ) ,
2013-12-18 15:49:49 +00:00
data ;
2013-12-18 15:07:56 +00:00
2014-01-15 09:37:49 +00:00
// No groupby
2013-12-18 15:07:56 +00:00
if ( ( dim _x === 0 ) && ( dim _y === 0 ) ) {
2014-01-28 11:10:22 +00:00
data = [ { key : _t ( 'Total' ) , values : [ {
x : _t ( 'Total' ) ,
2014-04-22 15:04:01 +00:00
y : this . pivot . get _total ( ) [ 0 ] ,
2013-12-18 15:07:56 +00:00
} ] } ] ;
2014-01-15 09:37:49 +00:00
// Only column groupbys
2013-12-18 15:07:56 +00:00
} else if ( ( dim _x === 0 ) && ( dim _y >= 1 ) ) {
2014-01-16 14:00:58 +00:00
data = _ . map ( this . pivot . get _cols _with _depth ( 1 ) , function ( header ) {
2013-12-18 15:07:56 +00:00
return {
key : header . title ,
2014-01-16 14:00:58 +00:00
values : [ { x : header . title , y : self . pivot . get _total ( header ) [ 0 ] } ]
2013-12-18 15:07:56 +00:00
} ;
} ) ;
2014-01-15 09:37:49 +00:00
// Just 1 row groupby
2013-12-18 15:07:56 +00:00
} else if ( ( dim _x === 1 ) && ( dim _y === 0 ) ) {
2014-01-10 11:35:57 +00:00
data = _ . map ( this . pivot . main _row ( ) . children , function ( pt ) {
2014-04-22 15:04:01 +00:00
var value = self . pivot . get _total ( pt ) [ 0 ] ,
2014-01-28 11:10:22 +00:00
title = ( pt . title !== undefined ) ? pt . title : _t ( 'Undefined' ) ;
2013-12-18 15:49:49 +00:00
return { x : title , y : value } ;
2013-12-18 15:07:56 +00:00
} ) ;
2014-01-10 11:35:57 +00:00
data = [ { key : self . pivot . measures [ 0 ] . string , values : data } ] ;
2014-01-15 09:37:49 +00:00
// 1 row groupby and some col groupbys
2013-12-18 15:07:56 +00:00
} else if ( ( dim _x === 1 ) && ( dim _y >= 1 ) ) {
2014-01-10 11:35:57 +00:00
data = _ . map ( this . pivot . get _cols _with _depth ( 1 ) , function ( colhdr ) {
var values = _ . map ( self . pivot . get _rows _with _depth ( 1 ) , function ( header ) {
2013-12-18 15:07:56 +00:00
return {
2014-01-28 11:10:22 +00:00
x : header . title || _t ( 'Undefined' ) ,
2014-01-13 15:23:16 +00:00
y : self . pivot . get _values ( header . id , colhdr . id ) [ 0 ] || 0
2013-12-18 15:07:56 +00:00
} ;
} ) ;
2014-01-28 11:10:22 +00:00
return { key : colhdr . title || _t ( 'Undefined' ) , values : values } ;
2013-12-18 15:07:56 +00:00
} ) ;
2014-01-15 09:37:49 +00:00
// At least two row groupby
2013-12-18 15:07:56 +00:00
} else {
2014-01-10 11:35:57 +00:00
var keys = _ . uniq ( _ . map ( this . pivot . get _rows _with _depth ( 2 ) , function ( hdr ) {
2014-01-28 11:10:22 +00:00
return hdr . title || _t ( 'Undefined' ) ;
2013-12-18 15:07:56 +00:00
} ) ) ;
data = _ . map ( keys , function ( key ) {
2014-01-10 11:35:57 +00:00
var values = _ . map ( self . pivot . get _rows _with _depth ( 1 ) , function ( hdr ) {
2013-12-18 15:07:56 +00:00
var subhdr = _ . find ( hdr . children , function ( child ) {
2014-01-28 11:10:22 +00:00
return ( ( child . title === key ) || ( ( child . title === undefined ) && ( key === _t ( 'Undefined' ) ) ) ) ;
2013-12-18 15:07:56 +00:00
} ) ;
return {
2014-01-28 11:10:22 +00:00
x : hdr . title || _t ( 'Undefined' ) ,
2014-01-03 14:22:15 +00:00
y : ( subhdr ) ? self . pivot . get _total ( subhdr ) [ 0 ] : 0
2013-12-18 15:07:56 +00:00
} ;
} ) ;
return { key : key , values : values } ;
} ) ;
}
2013-12-18 15:49:49 +00:00
nv . addGraph ( function ( ) {
var chart = nv . models . multiBarChart ( )
2013-12-27 14:28:14 +00:00
. reduceXTicks ( false )
2013-12-20 11:02:43 +00:00
. stacked ( self . bar _ui === 'stack' )
2014-01-17 14:50:56 +00:00
. showControls ( show _controls ) ;
2015-04-29 09:07:36 +00:00
chart . yAxis . tickFormat ( function ( d ) { return openerp . web . format _value ( d , { type : 'float' } ) ; } ) ;
2013-12-18 15:49:49 +00:00
2013-12-27 15:07:19 +00:00
if ( self . width / data [ 0 ] . values . length < 80 ) {
2013-12-27 14:28:14 +00:00
chart . rotateLabels ( - 15 ) ;
chart . reduceXTicks ( true ) ;
chart . margin ( { bottom : 40 } ) ;
}
2013-12-24 14:09:42 +00:00
2013-12-18 15:49:49 +00:00
d3 . select ( self . svg )
. datum ( data )
. attr ( 'width' , self . width )
. attr ( 'height' , self . height )
. call ( chart ) ;
nv . utils . windowResize ( chart . update ) ;
return chart ;
} ) ;
2013-12-18 15:07:56 +00:00
} ,
2014-01-10 14:08:37 +00:00
line : function ( ) {
2013-12-18 15:07:56 +00:00
var self = this ,
dim _x = this . pivot . rows . groupby . length ,
dim _y = this . pivot . cols . groupby . length ;
2014-04-22 15:04:41 +00:00
var rows = this . pivot . get _rows _with _depth ( dim _x ) ,
labels = _ . pluck ( rows , 'title' ) ;
2013-12-18 15:07:56 +00:00
var data = _ . map ( this . pivot . get _cols _leaves ( ) , function ( col ) {
2014-04-22 15:04:41 +00:00
var values = _ . map ( rows , function ( row , index ) {
return { x : index , y : self . pivot . get _values ( row . id , col . id ) [ 0 ] || 0 } ;
2013-12-18 15:07:56 +00:00
} ) ;
var title = _ . map ( col . path , function ( p ) {
2014-01-28 11:10:22 +00:00
return p || _t ( 'Undefined' ) ;
2013-12-18 15:07:56 +00:00
} ) . join ( '/' ) ;
if ( dim _y === 0 ) {
2014-01-10 11:35:57 +00:00
title = self . pivot . measures [ 0 ] . string ;
2013-12-18 15:07:56 +00:00
}
return { values : values , key : title } ;
} ) ;
nv . addGraph ( function ( ) {
var chart = nv . models . lineChart ( )
2014-04-22 15:04:01 +00:00
. x ( function ( d , u ) { return u ; } ) ;
2013-12-18 15:07:56 +00:00
2014-04-22 15:04:41 +00:00
chart . xAxis . tickFormat ( function ( d , u ) { return labels [ d ] ; } ) ;
2013-12-18 15:07:56 +00:00
d3 . select ( self . svg )
. attr ( 'width' , self . width )
. attr ( 'height' , self . height )
. datum ( data )
. call ( chart ) ;
return chart ;
} ) ;
} ,
2014-01-10 14:08:37 +00:00
pie : function ( ) {
2013-12-18 15:07:56 +00:00
var self = this ,
2013-12-24 11:22:24 +00:00
dim _x = this . pivot . rows . groupby . length ;
2013-12-18 15:07:56 +00:00
var data = _ . map ( this . pivot . get _rows _leaves ( ) , function ( row ) {
var title = _ . map ( row . path , function ( p ) {
2014-01-28 11:10:22 +00:00
return p || _t ( 'Undefined' ) ;
2013-12-18 15:07:56 +00:00
} ) . join ( '/' ) ;
if ( dim _x === 0 ) {
2016-08-25 08:38:12 +00:00
title = self . measure _label || _t ( 'Undefined' ) ;
2013-12-18 15:07:56 +00:00
}
2014-04-22 15:04:01 +00:00
return { x : title , y : self . pivot . get _total ( row ) [ 0 ] } ;
2013-12-18 15:07:56 +00:00
} ) ;
nv . addGraph ( function ( ) {
var chart = nv . models . pieChart ( )
. width ( self . width )
2014-04-22 15:04:01 +00:00
. height ( self . height )
. color ( d3 . scale . category10 ( ) . range ( ) ) ;
2013-12-18 15:07:56 +00:00
d3 . select ( self . svg )
. datum ( data )
. transition ( ) . duration ( 1200 )
. attr ( 'width' , self . width )
. attr ( 'height' , self . height )
. call ( chart ) ;
nv . utils . windowResize ( chart . update ) ;
return chart ;
} ) ;
} ,
2014-02-03 11:33:32 +00:00
// ----------------------------------------------------------------------
// Controller stuff...
// ----------------------------------------------------------------------
export _xls : function ( ) {
2014-02-05 09:58:08 +00:00
var c = openerp . webclient . crashmanager ;
2016-01-26 14:40:42 +00:00
var table = this . build _table ( true ) ;
if ( table . measure _row . length + 1 > 256 ) {
c . show _message ( _t ( "For Excel compatibility, data cannot be exported if there is more than 256 columns.\n\nTip: try to flip axis, filter further or reduce the number of measures." ) )
return ;
}
2014-02-04 11:31:35 +00:00
openerp . web . blockUI ( ) ;
2014-02-03 11:33:32 +00:00
this . session . get _file ( {
url : '/web_graph/export_xls' ,
2016-01-26 14:40:42 +00:00
data : { data : JSON . stringify ( table ) } ,
2014-02-03 11:33:32 +00:00
complete : openerp . web . unblockUI ,
2014-02-05 09:58:08 +00:00
error : c . rpc _error . bind ( c )
2014-02-03 11:33:32 +00:00
} ) ;
} ,
2013-11-22 07:43:27 +00:00
} ) ;
2014-01-21 14:30:34 +00:00
// Utility function: returns true if the beginning of array2 is array1 and
// if array1 is not array2
function is _strict _beginning _of ( array1 , array2 ) {
if ( array1 . length >= array2 . length ) { return false ; }
var result = true ;
for ( var i = 0 ; i < array1 . length ; i ++ ) {
2014-01-24 15:16:35 +00:00
if ( ! _ . isEqual ( array1 [ i ] , array2 [ i ] ) ) { return false ; }
2014-01-21 14:30:34 +00:00
}
return result ;
}
2014-01-14 12:51:42 +00:00
} ) ( ) ;