[IMP] adds support for more than one measure in graph view. (addon web_graph)

bzr revid: ged@openerp.com-20140103142215-z19pnxmnla8xugx0
This commit is contained in:
Gery Debongnie 2014-01-03 15:22:15 +01:00
parent 8347c44966
commit 2514343b52
3 changed files with 120 additions and 61 deletions

View File

@ -1,26 +1,28 @@
.graph_main_content td {
font-size: 12px;
background: #fff;
/*background: #fff;*/
margin: 45px;
border-collapse: collapse;
text-align: left;
vertical-align: middle;
}
.graph_main_content th {
font-size: 13px;
font-weight: normal;
color: #039;
padding: 10px 8px;
border-bottom: 2px solid #6678b1;
vertical-align: top;
}
.graph_main_content thead {
border: 1px solid #6678b1;
border-bottom: 2px solid #6678b1;
/*color: #039;*/
}
.graph_main_content tbody {
.graph_main_content tbody td{
border: 1px solid #ccc;
}
@ -28,7 +30,6 @@
border-bottom: 1px solid #ccc;
padding: 6px 8px;
text-align: right;
text-color: black;
}
td.graph_border {
@ -77,3 +78,11 @@ span.web_graph_indent {
color: black;
text-decoration: none;
}
th.measure_row {
color: black;
font-size: 12px;
/*border: 0 !important;*/
padding:0px 5px 0px 5px ;
margin:0;
}

View File

@ -51,7 +51,8 @@ instance.web_graph.GraphView = instance.web.View.extend({
view_loading: function (fields_view_get) {
var self = this,
arch = fields_view_get.arch,
measure = null,
measures = [],
title = arch.attrs.string,
stacked = false;
if (!_.has(arch.attrs, 'type')) {
@ -90,20 +91,24 @@ instance.web_graph.GraphView = instance.web.View.extend({
self.default_col_groupby.push(field.attrs.name);
break;
case 'measure':
measure = field.attrs.name;
measures.push(field.attrs.name);
break;
}
} else { // old style, kept for backward compatibility
if ('operator' in field.attrs) {
measure = (measure) ? measure : field.attrs.name;
measures.push(field.attrs.name);
} else {
self.default_row_groupby.push(field.attrs.name);
}
}
});
if (measures.length === 0) {
measures.push('__count');
}
this.graph_widget.config({
measure:measure,
measures:measures,
update:false,
title: title,
bar_ui: (stacked) ? 'stack' : 'group'
});
},
@ -214,6 +219,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({
this.visible_ui = true;
this.bar_ui = 'group'; // group or stack
this.config(options || {});
this.title = 'Graph';
},
// hide ui/show, stacked/grouped
@ -227,6 +233,9 @@ instance.web_graph.Graph = instance.web.Widget.extend({
if (_.has(options, 'bar_ui')) {
this.bar_ui = options.bar_ui;
}
if (_.has(options, 'title')) {
this.title = options.title;
}
this.pivot.config(options);
},
@ -335,8 +344,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({
measure_selection: function (event) {
event.preventDefault();
var measure = event.target.attributes['data-choice'].nodeValue;
var actual_measure = (measure === '__count') ? null : measure;
this.pivot.config({measure:actual_measure});
this.pivot.config({measures:[measure]});
},
option_selection: function (event) {
@ -413,13 +421,13 @@ instance.web_graph.Graph = instance.web.Widget.extend({
******************************************************************************/
draw_table: function () {
this.pivot.rows.main.title = 'Total';
this.pivot.cols.main.title = this.measure_label();
this.pivot.cols.main.title = this.title;
this.draw_top_headers();
_.each(this.pivot.rows.headers, this.proxy('draw_row'));
},
measure_label: function () {
return (this.pivot.measure) ? this.fields[this.pivot.measure].string : 'Quantity';
measure_label: function (measure) {
return (measure !== '__count') ? this.fields[measure].string : 'Quantity';
},
make_border_cell: function (colspan, rowspan, headercell) {
@ -456,7 +464,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({
}
function make_col_header (col) {
var cell = self.make_border_cell(col.width, col.height, true);
var cell = self.make_border_cell(col.width*pivot.measures.length, col.height, true);
return cell.append(self.make_header_title(col).attr('data-id', col.id));
}
@ -479,24 +487,62 @@ instance.web_graph.Graph = instance.web.Widget.extend({
make_cells(pivot.cols.headers, 0);
} else {
make_cells(pivot.cols.main.children, 1);
header_cells[0].push(self.make_border_cell(1, height, true).append('Total').css('font-weight', 'bold'));
if (pivot.get_cols_leaves().length > 1) {
header_cells[0].push(self.make_border_cell(pivot.measures.length, height, true).append('Total').css('font-weight', 'bold'));
}
}
_.each(header_cells, function (cells) {
thead.append($('<tr></tr>').append(cells));
});
if (pivot.measures.length >= 2) {
thead.append(self.make_measure_row());
}
self.table.append(thead);
},
get_measure_type: function () {
var measure = this.pivot.measure;
return (measure) ? this.fields[measure].type : 'integer';
make_measure_row: function() {
var self = this,
measures = this.pivot.measures,
cols = this.pivot.cols.headers,
measure_cells,
measure_row = $('<tr></tr>');
measure_row.append($('<th></th>'));
_.each(cols, function (col) {
if (!col.children.length) {
for (var i = 0; i < measures.length; i++) {
measure_cells = $('<th></th>').addClass('measure_row');
measure_cells.append(self.measure_label(measures[i]));
measure_row.append(measure_cells);
}
}
});
if (this.pivot.get_cols_leaves().length > 1) {
for (var i = 0; i < measures.length; i++) {
measure_cells = $('<th></th>').addClass('measure_row');
measure_cells.append(self.measure_label(measures[i]));
measure_row.append(measure_cells);
}
}
return measure_row;
},
get_measure_types: function () {
var self = this;
return _.map(this.pivot.measures, function (measure) {
return (measure !== '__count') ? self.fields[measure].type : 'integer';
});
},
draw_row: function (row) {
var self = this,
pivot = this.pivot,
measure_type = this.get_measure_type(),
measure_types = this.get_measure_types(),
html_row = $('<tr></tr>'),
row_header = this.make_border_cell(1,1)
.append(this.make_header_title(row).attr('data-id', row.id))
@ -510,21 +556,24 @@ instance.web_graph.Graph = instance.web.Widget.extend({
_.each(pivot.cols.headers, function (col) {
if (col.children.length === 0) {
var value = pivot.get_value(row.id, col.id),
cell = make_cell(value, col);
html_row.append(cell);
var values = pivot.get_value(row.id, col.id, new Array(measure_types.length));
for (var i = 0; i < values.length; i++) {
html_row.append(make_cell(values[i], measure_types[i], col));
}
}
});
if (pivot.cols.main.children.length > 0) {
var cell = make_cell(pivot.get_total(row), pivot.cols.main)
.css('font-weight', 'bold');
html_row.append(cell);
if (pivot.get_cols_leaves().length > 1) {
var total_vals = pivot.get_total(row);
for (var j = 0; j < total_vals.length; j++) {
var cell = make_cell(total_vals[j], measure_types[j], pivot.cols.main).css('font-weight', 'bold');
html_row.append(cell);
}
}
this.table.append(html_row);
function make_cell (value, col) {
function make_cell (value, measure_type, col) {
var color,
total,
cell = $('<td></td>');
@ -564,31 +613,31 @@ instance.web_graph.Graph = instance.web.Widget.extend({
if ((dim_x === 0) && (dim_y === 0)) {
data = [{key: 'Total', values:[{
x: 'Total',
y: this.pivot.get_value(this.pivot.rows.main.id, this.pivot.cols.main.id),
y: this.pivot.get_value(this.pivot.rows.main.id, this.pivot.cols.main.id)[0],
}]}];
// Only column groupbys ****************************************************
} else if ((dim_x === 0) && (dim_y >= 1)){
data = _.map(this.pivot.get_columns_depth(1), function (header) {
return {
key: header.title,
values: [{x:header.root.main.title, y: self.pivot.get_total(header)}]
values: [{x:header.root.main.title, y: self.pivot.get_total(header)[0]}]
};
});
// Just 1 row groupby ******************************************************
} else if ((dim_x === 1) && (dim_y === 0)) {
data = _.map(this.pivot.rows.main.children, function (pt) {
var value = self.pivot.get_value(pt.id, self.pivot.cols.main.id),
var value = self.pivot.get_value(pt.id, self.pivot.cols.main.id)[0],
title = (pt.title !== undefined) ? pt.title : 'Undefined';
return {x: title, y: value};
});
data = [{key: this.measure_label(), values:data}];
data = [{key: self.measure_label(self.pivot.measures[0]), values:data}];
// 1 row groupby and some col groupbys**************************************
} else if ((dim_x === 1) && (dim_y >= 1)) {
data = _.map(this.pivot.get_columns_depth(1), function (colhdr) {
var values = _.map(self.pivot.get_rows_depth(1), function (header) {
return {
x: header.title || 'Undefined',
y: self.pivot.get_value(header.id, colhdr.id, 0)
y: self.pivot.get_value(header.id, colhdr.id, 0)[0]
};
});
return {key: colhdr.title || 'Undefined', values: values};
@ -605,7 +654,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({
});
return {
x: hdr.title || 'Undefined',
y: (subhdr) ? self.pivot.get_total(subhdr) : 0
y: (subhdr) ? self.pivot.get_total(subhdr)[0] : 0
};
});
return {key:key, values: values};
@ -651,7 +700,7 @@ instance.web_graph.Graph = instance.web.Widget.extend({
return p || 'Undefined';
}).join('/');
if (dim_y === 0) {
title = self.measure_label();
title = self.measure_label(self.pivot.measures[0]);
}
return {values: values, key: title};
});

View File

@ -14,7 +14,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
this.cols = { groupby: [], main: null, headers: null };
this.cells = [];
this.domain = domain;
this.measure = null;
this.measures = ['__count'];
this.data_loader = new openerp.web_graph.DataLoader(model);
@ -22,11 +22,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
},
visible_fields: function () {
var result = this.rows.groupby.concat(this.cols.groupby);
if (this.measure) {
result = result.concat(this.measure);
}
return result;
var result = this.rows.groupby.concat(this.cols.groupby, this.measures);
return _.without(result, '__count');
},
config: function (options) {
@ -37,7 +34,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
domain:this.domain,
col_groupby: this.cols.groupby,
row_groupby: this.rows.groupby,
measure: this.measure,
measures: this.measures,
silent:false
};
options = _.extend(default_options, options);
@ -50,8 +47,8 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
this.domain = options.domain;
changed = true;
}
if (options.measure !== this.measure) {
this.measure = options.measure;
if (!_.isEqual(options.measures, this.measures)) {
this.measures = options.measures;
changed = true;
}
if (!_.isEqual(options.col_groupby, this.cols.groupby)) {
@ -71,26 +68,26 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
if (options.update && changed) { this.update_data(); }
},
set_value: function (id1, id2, value) {
set_value: function (id1, id2, values) {
var x = Math.min(id1, id2),
y = Math.max(id1, id2),
cell = _.find(this.cells, function (c) {
return ((c.x == x) && (c.y == y));
});
if (cell) {
cell.value = value;
cell.values = values;
} else {
this.cells.push({x: x, y: y, value: value});
this.cells.push({x: x, y: y, values: values});
}
},
get_value: function (id1, id2, default_value) {
get_value: function (id1, id2, default_values) {
var x = Math.min(id1, id2),
y = Math.max(id1, id2),
cell = _.find(this.cells, function (c) {
return ((c.x == x) && (c.y == y));
});
return (cell === undefined) ? default_value : cell.value;
return (cell === undefined) ? default_values : cell.values;
},
is_row: function (id) {
@ -187,11 +184,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
}
});
if (other) {
if (self.measure) {
self.set_value(new_header_id, other.id, data.attributes.aggregates[self.measure]);
} else {
self.set_value(new_header_id, other.id, data.attributes.length);
}
self.set_value(new_header_id, other.id, _.map(self.measures, function (measure) {
return (measure === '__count') ? data.attributes.length : data.attributes.aggregates[measure];
}));
}
});
});
@ -239,7 +234,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend(openerp.EventDispatcherM
options = {
col_groupby: this.cols.groupby,
row_groupby: this.rows.groupby,
measure: this.measure,
measures: this.measures,
domain: this.domain,
};
@ -391,9 +386,9 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({
var self = this,
cols = options.col_groupby,
rows = options.row_groupby,
visible_fields = rows.concat(cols);
visible_fields = _.without(rows.concat(cols, options.measures), '__count');
if (options.measure) { visible_fields = visible_fields.concat(options.measure); }
// if (options.measure) { visible_fields = visible_fields.concat(options.measure); }
var groupbys = _.map(_.range(cols.length + 1), function (i) {
return cols.slice(0, i).concat(rows);
@ -416,9 +411,13 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({
});
},
get_value: function (data, measure) {
get_value: function (data, measures) {
var attr = data.attributes;
return (measure) ? attr.aggregates[measure] : attr.length;
var result = _.map(measures, function (measure) {
return (measure === '__count') ? attr.length : attr.aggregates[measure];
});
return result;
// return (measure) ? attr.aggregates[measure] : attr.length;
},
format_data: function (total, col_data, row_data, cell_data, options) {
@ -451,7 +450,7 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({
children: [],
title: (parent) ? data.attributes.value : '',
domain: (parent) ? data.model._domain : options.domain,
total: this.get_value(options.total, options.measure),
total: this.get_value(options.total, options.measures),
};
if (main.path.length < depth) {
@ -468,7 +467,9 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({
var attr = group.attributes,
group_val = (attr.value instanceof Array) ? attr.value[1] : attr.value,
path = current_path,
value = (options.measure) ? attr.aggregates[options.measure] : attr.length;
values = _.map(options.measures, function (measure) {
return (measure === '__count') ? attr.length : attr.aggregates[measure];
});
group_val = (group_val === false) ? undefined : group_val;
@ -483,7 +484,7 @@ openerp.web_graph.DataLoader = openerp.web.Class.extend({
});
current_cells.push({x: Math.min(row.id, col.id),
y: Math.max(row.id, col.id),
value: value});
values: values});
if (attr.has_children) {
self.make_cells (group.subgroups_data, index, path, current_cells, rows, cols, options);