summaryrefslogtreecommitdiff
path: root/addons/web_graph/static/src/js
diff options
context:
space:
mode:
authorGery Debongnie <ged@openerp.com>2013-11-22 08:43:27 +0100
committerGery Debongnie <ged@openerp.com>2013-11-22 08:43:27 +0100
commitd0cb5149b4dc03f233fcce60d498b24ab8ac0259 (patch)
tree925e6b54a2538a0ec7b82ce9f58c1e21a50ba7b0 /addons/web_graph/static/src/js
parenta309c97505dd01072225a1f45b39c19f1e6b32e6 (diff)
[REF] large refactoring in progress. goal is to separate the data handling code (pivot) from the ui code (drawing, buttons, events (addon web_graph)
bzr revid: ged@openerp.com-20131122074327-bfnlw3ew1120um0k
Diffstat (limited to 'addons/web_graph/static/src/js')
-rw-r--r--addons/web_graph/static/src/js/graph.js1326
-rw-r--r--addons/web_graph/static/src/js/pivot.js132
2 files changed, 911 insertions, 547 deletions
diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js
index 7d73f0df695..3363f7cb3a8 100644
--- a/addons/web_graph/static/src/js/graph.js
+++ b/addons/web_graph/static/src/js/graph.js
@@ -22,26 +22,26 @@ instance.web_graph.GraphView = instance.web.View.extend({
template: 'GraphView',
display_name: _lt('Graph'),
view_type: 'graph',
- mode: 'pivot', // pivot, bar_chart, line_chart or pie_chart
- pivot_table: null,
events: {
'click .graph_mode_selection li' : function (event) {
event.preventDefault();
this.mode = event.target.attributes['data-mode'].nodeValue;
- this.display_data();
+ console.log("change mode",this.mode);
},
},
view_loading: function (fields_view_get) {
- var self = this;
- var model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true});
- var domain = [];
- var col_groupby = [];
- var row_groupby = [];
- var measure = null;
- var fields;
- var important_fields = [];
+ var self = this,
+ model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}),
+ domain = [],
+ measure = null,
+ fields,
+ important_fields = [],
+ col_groupby = [],
+ row_groupby = [];
+
+ this.pivot_table = null;
// get the default groupbys and measure defined in the field view
_.each(fields_view_get.arch.children, function (field) {
@@ -96,33 +96,26 @@ instance.web_graph.GraphView = instance.web.View.extend({
});
},
- display_data : function () {
- var content = this.$el.filter('.graph_main_content');
- content.find('svg').remove();
- var self = this;
- if (this.mode === 'pivot') {
- this.pivot_table.show();
- } else {
- this.pivot_table.hide();
- content.append('<svg></svg>');
- var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby);
- query_groups(this.data.model, view_fields, this.data.domain, this.data.row_groupby).then(function (groups) {
- Charts[self.mode](groups, self.data.measure, self.data.measure_label);
- });
-
- }
+ start: function () {
+ this.table = $('<table></table>');
+ this.svg = $('<svg></svg>');
+ this.$el.filter('.graph_main_content').append(this.table);
+ this.$el.filter('.graph_main_content').append(this.svg);
+ return this.load_view();
},
do_search: function (domain, context, group_by) {
+ var self = this;
this.data.domain = new instance.web.CompoundDomain(domain);
- if (this.pivot_table) {
- this.pivot_table.draw(true);
+ if (!this.pivot_table) {
+ self.pivot_table = new PivotTable(self.data);
+ self.pivot_table.start().then(self.proxy('draw_table'));
} else {
- this.pivot_table = new PivotTable(this.data);
- this.pivot_table.appendTo('.graph_main_content');
+ this.pivot_table.update_values.done(function () {
+ self.draw_table();
+ });
}
- this.display_data();
},
do_show: function () {
@@ -130,556 +123,795 @@ instance.web_graph.GraphView = instance.web.View.extend({
return this._super();
},
-});
-
-
- /**
- * PivotTable widget. It displays the data in tabular data and allows the
- * user to drill down and up in the table
- */
-var PivotTable = instance.web.Widget.extend({
- template: 'pivot_table',
- data: null,
- headers: [],
- rows: [],
- cols: [],
- id_seed : 0,
-
- events: {
- 'click .web_graph_click' : function (event) {
- event.preventDefault();
-
- if (event.target.attributes['data-row-id'] !== undefined) {
- this.handle_row_event(event);
- }
- if (event.target.attributes['data-col-id'] !== undefined) {
- this.handle_col_event(event);
- }
- },
-
- 'click a.field-selection' : function (event) {
- var id,
- field_id = event.target.attributes['data-field-id'].nodeValue;
- event.preventDefault();
- this.dropdown.remove();
- if (event.target.attributes['data-row-id'] !== undefined) {
- id = event.target.attributes['data-row-id'].nodeValue;
- this.expand_row(id, field_id);
- }
- if (event.target.attributes['data-col-id'] !== undefined) {
- id = event.target.attributes['data-col-id'].nodeValue;
- this.expand_col(id, field_id);
- }
- },
- },
-
- handle_row_event: function (event) {
- var row_id = event.target.attributes['data-row-id'].nodeValue,
- row = this.get_row(row_id);
-
- if (row.expanded) {
- this.fold_row(row_id);
- } else {
- if (row.path.length < this.data.row_groupby.length) {
- var field_to_expand = this.data.row_groupby[row.path.length];
- this.expand_row(row_id, field_to_expand);
- } else {
- this.display_dropdown({row_id:row_id,
- target: $(event.target),
- x: event.pageX,
- y: event.pageY});
- }
- }
- },
-
- handle_col_event: function (event) {
- var col_id = event.target.attributes['data-col-id'].nodeValue,
- col = this.get_col(col_id);
-
- if (col.expanded) {
- this.fold_col(col_id);
- } else {
- if (col.path.length < this.data.col_groupby.length) {
- var field_to_expand = this.data.col_groupby[col.path.length];
- this.expand_col(col_id, field_to_expand);
- } else {
- this.display_dropdown({col_id: col_id,
- target: $(event.target),
- x: event.pageX,
- y: event.pageY});
- }
- }
- },
-
- init: function (data) {
- this.data = data;
- },
-
- start: function () {
- this.draw(true);
- },
-
- draw: function (load_data) {
- var self = this;
-
- if (load_data) {
- var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby);
- query_groups_data(this.data.model, view_fields, this.data.domain, this.data.col_groupby, this.data.row_groupby[0])
- .then(function (groups) {
- self.data.groups = groups;
- return self.get_groups([]);
- }).then(function (total) {
- total[0].path = [];
- self.data.total = [total];
- self.build_table();
- self.draw(false);
- });
- } else {
- this.$el.empty();
-
- this.draw_top_headers();
-
- _.each(this.rows, function (row) {
- self.$el.append(row.html);
- });
- }
- },
-
- show: function () {
- this.$el.css('display', 'block');
- },
-
- hide: function () {
- this.$el.css('display', 'none');
- },
-
- display_dropdown: function (options) {
- var self = this,
- already_grouped = self.data.row_groupby.concat(self.data.col_groupby),
- possible_groups = _.difference(self.data.important_fields, already_grouped),
- dropdown_options = {
- fields: _.map(possible_groups, function (field) {
- return {id: field, value: self.get_descr(field)};
- })};
- if (options.row_id) {
- dropdown_options.row_id= options.row_id;
- } else {
- dropdown_options.col_id = options.col_id;
- }
-
- this.dropdown = $(QWeb.render('field_selection', dropdown_options));
- options.target.after(this.dropdown);
- this.dropdown.css({position:'absolute',
- left:options.x,
- top:options.y});
- $('.field-selection').next('.dropdown-menu').toggle();
- },
-
- build_table: function () {
- var self = this;
- this.rows = [];
-
-
- var col_id = this.generate_id();
-
- this.cols= [{
- id: col_id,
- path: [],
- value: this.data.measure_label,
- expanded: false,
- parent: null,
- children: [],
- cells: [], // a cell is {td:<jquery td>, row_id:<some id>}
- domain: this.data.domain,
- }];
-
- self.make_top_headers();
-
- var main_row = this.make_row(this.data.total[0]);
-
- _.each(this.data.groups, function (group) {
- self.make_row(group, main_row.id);
- });
- },
-
- get_descr: function (field_id) {
- return this.data.fields[field_id].string;
- },
-
- get_groups: function (groupby) {
- var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby);
- return query_groups(this.data.model, view_fields, this.data.domain, groupby);
+ draw_table: function () {
+ this.draw_top_headers();
+ _.each(this.pivot_table.rows, this.proxy('draw_row'));
},
- make_top_headers : function () {
+ draw_top_headers: function () {
var self = this,
- header;
-
- function partition (columns) {
- return _.reduce(columns, function (partial, col) {
- if (partial.length === 0) return [[col]];
- if (col.path.length > _.first(_.last(partial)).path.length) {
- _.last(partial).push(col);
- } else {
- partial.push([col]);
- }
- return partial;
- }, []);
- }
+ pivot = this.pivot_table;
- function side_by_side(blocks) {
- var result = _.zip.apply(_,blocks);
- result = _.map(result, function(line) {return _.compact(_.flatten(line))});
- return result;
- }
-
- function make_header_cell(col, span) {
- var options = {
- is_border:true,
- foldable:true,
- row_span: (span === undefined) ? 1 : span,
- col_id: col.id,
- };
- var result = self.make_cell(col.value, options);
- if (col.expanded) {
- result.find('.icon-plus-sign')
- .removeClass('icon-plus-sign')
- .addClass('icon-minus-sign');
- }
- return result;
- }
-
- function calculate_width(cols) {
- if (cols.length === 1) {
- return 1;
- }
- var p = partition(_.rest(cols));
- return _.reduce(p, function(x, y){ return x + calculate_width(y); }, 0);
- }
-
- function make_header_cells(cols, height) {
- var p = partition(cols);
- if ((p.length === 1) && (p[0].length === 1)) {
- var result = [[make_header_cell(cols[0], height)]];
- return result;
- }
- if ((p.length === 1) && (p[0].length > 1)) {
- var cell = make_header_cell(p[0][0]);
- cell.attr('colspan', calculate_width(cols));
- return [[cell]].concat(make_header_cells(_.rest(cols), height - 1));
- }
- if (p.length > 1) {
- return side_by_side(_.map(p, function (group) {
- return make_header_cells(group, height);
- }));
+ function get_column_tree(cols, level) {
+ var height,
+ width,
+ children = _.map(cols[0].children, function (child) {
+ get_column_tree(child, level - 1);
+ });
+ if (children.length > 0) {
+ height = 1;
+ width = _.reduce(children, function (x,y) { return x + y;}, 0);
+ } else {
+ height = level;
+ width = 1;
}
+ return {level: level,
+ width: width,
+ height: height,
+ col:cols[0],
+ children: children};
}
- if (this.cols.length === 1) {
- header = $('<tr></tr>');
- header.append(this.make_cell('', {is_border:true}));
- header.append(this.make_cell(this.cols[0].value,
- {is_border:true, foldable:true, col_id:this.cols[0].id}));
- header.addClass('graph_top');
- this.headers = [header];
- } else {
- var height = _.max(_.map(self.cols, function(g) {return g.path.length;}));
- var header_rows = make_header_cells(_.rest(this.cols), height);
-
- header_rows[0].splice(0,0,self.make_cell('', {is_border:true, }).attr('rowspan', height))
- self.headers = [];
- _.each(header_rows, function (cells) {
- header = $('<tr></tr>');
- header.append(cells);
- header.addClass('graph_top');
- self.headers.push(header);
- });
- }
- },
-
- draw_top_headers: function () {
- var self = this;
- $("tr.graph_top").remove();
- _.each(this.headers.reverse(), function (header) {
- self.$el.prepend(header);
- });
-
- },
-
- make_row: function (groups, parent_id) {
- var self = this,
- path,
- value,
- expanded,
- domain,
- parent,
- has_parent = (parent_id !== undefined),
- row_id = this.generate_id();
-
- if (has_parent) {
- parent = this.get_row(parent_id);
- path = parent.path.concat(groups[0].attributes.value[1]);
- value = groups[0].attributes.value[1];
- expanded = false;
- parent.children.push(row_id);
- domain = groups[0].model._domain;
- } else {
- parent = null;
- path = [];
- value = 'Total';
- expanded = true;
- domain = this.data.domain;
+ function make_cell(elem) {
+ var title = $('<span> </span>')
+ .addClass('web_graph_click')
+ .attr('href', '#')
+ .attr('data-col-id', elem.col.id)
+ .addClass((elem.col.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign')
+ .append(elem.col.name);
+ return $('<td></td>').addClass('graph_border')
+ .append(title)
+ .attr('rowspan', elem.height)
+ .attr('colspan', elem.width);
}
- var jquery_row = $('<tr></tr>');
+ var height = _.max(_.map(pivot.cols, function(g) {return g.path.length;}));
+ height = (height === 0) ? 1 : height;
- var header = self.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id});
- jquery_row.append(header);
+ var col_tree = get_column_tree(pivot.cols, height);
- var cell;
+ var header_cells = [[$('<td></td>')
+ .attr('rowspan', height)
+ .addClass('graph_border')]];
- _.each(this.cols, function (col) {
- var element = _.find(groups, function (group) {
- return _.isEqual(_.rest(group.path), col.path);
- });
- if (element === undefined) {
- cell = self.make_cell('');
+ function make_cells (queue, level) {
+ var tree = queue.shift();
+ queue = queue.concat(tree.children);
+ if (tree.level == level) {
+ _.last(header_cells).push(make_cell(tree));
} else {
- cell = self.make_cell(element.attributes.aggregates[self.data.measure]);
+ level -=1;
+ header_cells.push([make_cell(tree)]);
}
- if (col.expanded) {
- cell.css('display', 'none');
+ if (queue.length !== 0) {
+ make_cells(queue, level);
}
- col.cells.push({td:cell, row_id:row_id});
- jquery_row.append(cell);
- });
-
- if (!has_parent) {
- header.find('.icon-plus-sign')
- .removeClass('icon-plus-sign')
- .addClass('icon-minus-sign');
}
- var row = {
- id: row_id,
- path: path,
- value: value,
- expanded: expanded,
- parent: parent_id,
- children: [],
- html: jquery_row,
- domain: domain,
- };
- this.rows.push(row); // to do, insert it properly, after all childs of parent
- return row;
- },
-
- generate_id: function () {
- this.id_seed += 1;
- return this.id_seed - 1;
- },
-
- get_row: function (id) {
- return _.find(this.rows, function(row) {
- return (row.id == id);
- });
- },
-
- get_col: function (id) {
- return _.find(this.cols, function(col) {
- return (col.id == id);
+ make_cells([col_tree], height);
+ _.each(header_cells, function (cells) {
+ var row = $("<tr></tr>").append(cells);
+ self.table.append(row);
});
},
- make_cell: function (content, options) {
- options = _.extend({is_border: false, indent:0, foldable:false}, options);
- content = (content !== undefined) ? content : 'Undefined';
-
- var cell = $('<td></td>');
- if (options.is_border) cell.addClass('graph_border');
- if (options.row_span) cell.attr('rowspan', options.row_span);
- if (options.col_span) cell.attr('rowspan', options.col_span);
- _.each(_.range(options.indent), function () {
- cell.prepend($('<span/>', {class:'web_graph_indent'}));
- });
-
- if (options.foldable) {
- var attrs = {class:'icon-plus-sign web_graph_click', href:'#'};
- if (options.row_id !== undefined) attrs['data-row-id'] = options.row_id;
- if (options.col_id !== undefined) attrs['data-col-id'] = options.col_id;
- var plus = $('<span/>', attrs);
- plus.append(' ');
- plus.append(content);
- cell.append(plus);
- } else {
- cell.append(content);
+ draw_row: function (row) {
+ var pivot = this.pivot_table,
+ html_row = $('<tr></tr>'),
+ name = $('<span> </span>')
+ .addClass('web_graph_click')
+ .attr('href', '#')
+ .attr('data-row-id', row.id)
+ .addClass((row.is_expanded) ? 'icon-minus-sign' : 'icon-plus-sign')
+ .append(row.name),
+ row_header = $('<td></td>')
+ .append(name)
+ .addClass('graph_border');
+
+ for (var i in _.range(row.path.length)) {
+ row_header.prepend($('<span/>', {class:'web_graph_indent'}));
}
- return cell;
- },
- expand_row: function (row_id, field_id) {
- var self = this;
- var row = this.get_row(row_id);
+ html_row.append(row_header);
- if (row.path.length == this.data.row_groupby.length) {
- this.data.row_groupby.push(field_id);
- }
- row.expanded = true;
- row.html.find('.icon-plus-sign')
- .removeClass('icon-plus-sign')
- .addClass('icon-minus-sign');
-
- var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure);
- query_groups_data(this.data.model, visible_fields, row.domain, this.data.col_groupby, field_id)
- .then(function (groups) {
- _.each(groups.reverse(), function (group) {
- var new_row = self.make_row(group, row_id);
- row.html.after(new_row.html);
- });
+ _.each(pivot.cols, function (col) {
+ var cell = $('<td></td>').append(pivot.get_value(row.id, col.id));
+ html_row.append(cell)
});
+ this.table.append(html_row);
+ }
+});
- },
-
- expand_col: function (col_id, field_id) {
- var self = this;
- var col = this.get_col(col_id);
-
- if (col.path.length == this.data.col_groupby.length) {
- this.data.col_groupby.push(field_id);
- }
- col.expanded = true;
-
- var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure);
- query_groups_data(this.data.model, visible_fields, col.domain, this.data.row_groupby, field_id)
- .then(function (groups) {
- _.each(groups, function (group) {
- var new_col = {
- id: self.generate_id(),
- path: col.path.concat(group[0].attributes.value[1]),
- value: group[0].attributes.value[1],
- expanded: false,
- parent: col_id,
- children: [],
- cells: [], // a cell is {td:<jquery td>, row_id:<some id>}
- domain: group[0].model._domain,
- };
- col.children.push(new_col.id);
- insertAfter(self.cols, col, new_col)
- _.each(col.cells, function (cell) {
- var col_path = self.get_row(cell.row_id).path;
-
- var datapt = _.find(group, function (g) {
- return _.isEqual(g.path.slice(1), col_path);
- });
-
- var value;
- if (datapt === undefined) {
- value = '';
- } else {
- value = datapt.attributes.aggregates[self.data.measure];
- }
- var new_cell = {
- row_id: cell.row_id,
- td: self.make_cell(value)
- };
- new_col.cells.push(new_cell);
- cell.td.after(new_cell.td);
- cell.td.css('display','none');
- });
-
- });
- self.make_top_headers();
- self.draw_top_headers();
- });
- },
-
- fold_row: function (row_id) {
- var self = this;
- var row = this.get_row(row_id);
-
- _.each(row.children, function (child_row) {
- self.remove_row(child_row);
- });
- row.children = [];
-
- row.expanded = false;
- row.html.find('.icon-minus-sign')
- .removeClass('icon-minus-sign')
- .addClass('icon-plus-sign');
-
- var fold_levels = _.map(self.rows, function(g) {return g.path.length;});
- var new_groupby_length = _.max(fold_levels);
-
- this.data.row_groupby.splice(new_groupby_length);
- },
-
- remove_row: function (row_id) {
- var self = this;
- var row = this.get_row(row_id);
-
- _.each(row.children, function (child_row) {
- self.remove_row(child_row);
- });
-
- row.html.remove();
- removeFromArray(this.rows, row);
-
- _.each(this.cols, function (col) {
- col.cells = _.filter(col.cells, function (cell) {
- return cell.row_id !== row_id;
- });
- });
- },
-
- fold_col: function (col_id) {
- var self = this;
- var col = this.get_col(col_id);
-
- _.each(col.children, function (child_col) {
- self.remove_col(child_col);
- });
- col.children = [];
- _.each(col.cells, function (cell) {
- cell.td.css('display','table-cell');
- });
- col.expanded = false;
- // row.html.find('.icon-minus-sign')
- // .removeClass('icon-minus-sign')
- // .addClass('icon-plus-sign');
- var fold_levels = _.map(self.cols, function(g) {return g.path.length;});
- var new_groupby_length = _.max(fold_levels);
+// make_top_headers : function () {
+// var self = this,
+// header;
+
+// function partition (columns) {
+// return _.reduce(columns, function (partial, col) {
+// if (partial.length === 0) return [[col]];
+// if (col.path.length > _.first(_.last(partial)).path.length) {
+// _.last(partial).push(col);
+// } else {
+// partial.push([col]);
+// }
+// return partial;
+// }, []);
+// }
+
+// function side_by_side(blocks) {
+// var result = _.zip.apply(_,blocks);
+// result = _.map(result, function(line) {return _.compact(_.flatten(line))});
+// return result;
+// }
+
+// function make_header_cell(col, span) {
+// var options = {
+// is_border:true,
+// foldable:true,
+// row_span: (span === undefined) ? 1 : span,
+// col_id: col.id,
+// };
+// var result = self.make_cell(col.value, options);
+// if (col.expanded) {
+// result.find('.icon-plus-sign')
+// .removeClass('icon-plus-sign')
+// .addClass('icon-minus-sign');
+// }
+// return result;
+// }
+
+// function calculate_width(cols) {
+// if (cols.length === 1) {
+// return 1;
+// }
+// var p = partition(_.rest(cols));
+// return _.reduce(p, function(x, y){ return x + calculate_width(y); }, 0);
+// }
+
+// function make_header_cells(cols, height) {
+// var p = partition(cols);
+// if ((p.length === 1) && (p[0].length === 1)) {
+// var result = [[make_header_cell(cols[0], height)]];
+// return result;
+// }
+// if ((p.length === 1) && (p[0].length > 1)) {
+// var cell = make_header_cell(p[0][0]);
+// cell.attr('colspan', calculate_width(cols));
+// return [[cell]].concat(make_header_cells(_.rest(cols), height - 1));
+// }
+// if (p.length > 1) {
+// return side_by_side(_.map(p, function (group) {
+// return make_header_cells(group, height);
+// }));
+// }
+// }
+
+// if (this.cols.length === 1) {
+// header = $('<tr></tr>');
+// header.append(this.make_cell('', {is_border:true}));
+// header.append(this.make_cell(this.cols[0].value,
+// {is_border:true, foldable:true, col_id:this.cols[0].id}));
+// header.addClass('graph_top');
+// this.headers = [header];
+// } else {
+// var height = _.max(_.map(self.cols, function(g) {return g.path.length;}));
+// var header_rows = make_header_cells(_.rest(this.cols), height);
+
+// header_rows[0].splice(0,0,self.make_cell('', {is_border:true, }).attr('rowspan', height))
+// self.headers = [];
+// _.each(header_rows, function (cells) {
+// header = $('<tr></tr>');
+// header.append(cells);
+// header.addClass('graph_top');
+// self.headers.push(header);
+// });
+// }
+// },
+
+
+ // mode: 'pivot', // pivot, bar_chart, line_chart or pie_chart
+ // pivot_table: null,
+
+ // events: {
+ // 'click .graph_mode_selection li' : function (event) {
+ // event.preventDefault();
+ // this.mode = event.target.attributes['data-mode'].nodeValue;
+ // this.display_data();
+ // },
+ // },
+
+ // display_data : function () {
+ // var content = this.$el.filter('.graph_main_content');
+ // content.find('svg').remove();
+ // var self = this;
+ // if (this.mode === 'pivot') {
+ // this.pivot_table.show();
+ // } else {
+ // this.pivot_table.hide();
+ // content.append('<svg></svg>');
+ // var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby);
+ // query_groups(this.data.model, view_fields, this.data.domain, this.data.row_groupby).then(function (groups) {
+ // Charts[self.mode](groups, self.data.measure, self.data.measure_label);
+ // });
+
+ // }
+ // },
+
+
+ // if (this.pivot_table) {
+ // this.pivot_table.draw(true);
+ // } else {
+
+ // this.pivot_table = new PivotTable(this.data);
+ // this.pivot_table.appendTo('.graph_main_content');
+ // }
+ // this.display_data();
- this.data.col_groupby.splice(new_groupby_length);
- this.make_top_headers();
- this.draw_top_headers();
+ /**
+ * PivotTable widget. It displays the data in tabular data and allows the
+ * user to drill down and up in the table
+ */
+// var PivotTable = instance.web.Widget.extend({
+// template: 'pivot_table',
+
+// init: function (data) {
+// var self = this;
+// makePivotTable(this.data).done(function (table) {
+// self.pivottable = table;
+// });
+// },
+
+// });
+
+// var PivotTable = instance.web.Widget.extend({
+// template: 'pivot_table',
+// data: null,
+// headers: [],
+// rows: [],
+// cols: [],
+// id_seed : 0,
+
+// events: {
+// 'click .web_graph_click' : function (event) {
+// event.preventDefault();
+
+// if (event.target.attributes['data-row-id'] !== undefined) {
+// this.handle_row_event(event);
+// }
+// if (event.target.attributes['data-col-id'] !== undefined) {
+// this.handle_col_event(event);
+// }
+// },
+
+// 'click a.field-selection' : function (event) {
+// var id,
+// field_id = event.target.attributes['data-field-id'].nodeValue;
+// event.preventDefault();
+// this.dropdown.remove();
+// if (event.target.attributes['data-row-id'] !== undefined) {
+// id = event.target.attributes['data-row-id'].nodeValue;
+// this.expand_row(id, field_id);
+// }
+// if (event.target.attributes['data-col-id'] !== undefined) {
+// id = event.target.attributes['data-col-id'].nodeValue;
+// this.expand_col(id, field_id);
+// }
+// },
+// },
+
+// handle_row_event: function (event) {
+// var row_id = event.target.attributes['data-row-id'].nodeValue,
+// row = this.get_row(row_id);
+
+// if (row.expanded) {
+// this.fold_row(row_id);
+// } else {
+// if (row.path.length < this.data.row_groupby.length) {
+// var field_to_expand = this.data.row_groupby[row.path.length];
+// this.expand_row(row_id, field_to_expand);
+// } else {
+// this.display_dropdown({row_id:row_id,
+// target: $(event.target),
+// x: event.pageX,
+// y: event.pageY});
+// }
+// }
+// },
+
+// handle_col_event: function (event) {
+// var col_id = event.target.attributes['data-col-id'].nodeValue,
+// col = this.get_col(col_id);
+
+// if (col.expanded) {
+// this.fold_col(col_id);
+// } else {
+// if (col.path.length < this.data.col_groupby.length) {
+// var field_to_expand = this.data.col_groupby[col.path.length];
+// this.expand_col(col_id, field_to_expand);
+// } else {
+// this.display_dropdown({col_id: col_id,
+// target: $(event.target),
+// x: event.pageX,
+// y: event.pageY});
+// }
+// }
+// },
+
+// init: function (data) {
+// this.data = data;
+// makePivotTable(this.data).done(function (table) {
+// self.pivottable = table;
+// });
+
+// },
+
+// start: function () {
+// this.draw(true);
+// },
+
+// draw: function (load_data) {
+// var self = this;
+
+// if (load_data) {
+// var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby);
+// query_groups_data(this.data.model, view_fields, this.data.domain, this.data.col_groupby, this.data.row_groupby[0])
+// .then(function (groups) {
+// self.data.groups = groups;
+// return self.get_groups([]);
+// }).then(function (total) {
+// total[0].path = [];
+// self.data.total = [total];
+// self.build_table();
+// self.draw(false);
+// });
+// } else {
+// this.$el.empty();
+
+// this.draw_top_headers();
+
+// _.each(this.rows, function (row) {
+// self.$el.append(row.html);
+// });
+// }
+// },
+
+// show: function () {
+// this.$el.css('display', 'block');
+// },
+
+// hide: function () {
+// this.$el.css('display', 'none');
+// },
+
+// display_dropdown: function (options) {
+// var self = this,
+// already_grouped = self.data.row_groupby.concat(self.data.col_groupby),
+// possible_groups = _.difference(self.data.important_fields, already_grouped),
+// dropdown_options = {
+// fields: _.map(possible_groups, function (field) {
+// return {id: field, value: self.get_descr(field)};
+// })};
+// if (options.row_id) {
+// dropdown_options.row_id= options.row_id;
+// } else {
+// dropdown_options.col_id = options.col_id;
+// }
+
+// this.dropdown = $(QWeb.render('field_selection', dropdown_options));
+// options.target.after(this.dropdown);
+// this.dropdown.css({position:'absolute',
+// left:options.x,
+// top:options.y});
+// $('.field-selection').next('.dropdown-menu').toggle();
+// },
+
+// build_table: function () {
+// var self = this;
+// this.rows = [];
+
+
+// var col_id = this.generate_id();
+
+// this.cols= [{
+// id: col_id,
+// path: [],
+// value: this.data.measure_label,
+// expanded: false,
+// parent: null,
+// children: [],
+// cells: [], // a cell is {td:<jquery td>, row_id:<some id>}
+// domain: this.data.domain,
+// }];
+
+// self.make_top_headers();
+
+// var main_row = this.make_row(this.data.total[0]);
+
+// _.each(this.data.groups, function (group) {
+// self.make_row(group, main_row.id);
+// });
+// },
+
+// get_descr: function (field_id) {
+// return this.data.fields[field_id].string;
+// },
+
+// get_groups: function (groupby) {
+// var view_fields = this.data.row_groupby.concat(this.data.measure, this.data.col_groupby);
+// return query_groups(this.data.model, view_fields, this.data.domain, groupby);
+// },
+
+// make_top_headers : function () {
+// var self = this,
+// header;
+
+// function partition (columns) {
+// return _.reduce(columns, function (partial, col) {
+// if (partial.length === 0) return [[col]];
+// if (col.path.length > _.first(_.last(partial)).path.length) {
+// _.last(partial).push(col);
+// } else {
+// partial.push([col]);
+// }
+// return partial;
+// }, []);
+// }
+
+// function side_by_side(blocks) {
+// var result = _.zip.apply(_,blocks);
+// result = _.map(result, function(line) {return _.compact(_.flatten(line))});
+// return result;
+// }
+
+// function make_header_cell(col, span) {
+// var options = {
+// is_border:true,
+// foldable:true,
+// row_span: (span === undefined) ? 1 : span,
+// col_id: col.id,
+// };
+// var result = self.make_cell(col.value, options);
+// if (col.expanded) {
+// result.find('.icon-plus-sign')
+// .removeClass('icon-plus-sign')
+// .addClass('icon-minus-sign');
+// }
+// return result;
+// }
+
+// function calculate_width(cols) {
+// if (cols.length === 1) {
+// return 1;
+// }
+// var p = partition(_.rest(cols));
+// return _.reduce(p, function(x, y){ return x + calculate_width(y); }, 0);
+// }
+
+// function make_header_cells(cols, height) {
+// var p = partition(cols);
+// if ((p.length === 1) && (p[0].length === 1)) {
+// var result = [[make_header_cell(cols[0], height)]];
+// return result;
+// }
+// if ((p.length === 1) && (p[0].length > 1)) {
+// var cell = make_header_cell(p[0][0]);
+// cell.attr('colspan', calculate_width(cols));
+// return [[cell]].concat(make_header_cells(_.rest(cols), height - 1));
+// }
+// if (p.length > 1) {
+// return side_by_side(_.map(p, function (group) {
+// return make_header_cells(group, height);
+// }));
+// }
+// }
+
+// if (this.cols.length === 1) {
+// header = $('<tr></tr>');
+// header.append(this.make_cell('', {is_border:true}));
+// header.append(this.make_cell(this.cols[0].value,
+// {is_border:true, foldable:true, col_id:this.cols[0].id}));
+// header.addClass('graph_top');
+// this.headers = [header];
+// } else {
+// var height = _.max(_.map(self.cols, function(g) {return g.path.length;}));
+// var header_rows = make_header_cells(_.rest(this.cols), height);
+
+// header_rows[0].splice(0,0,self.make_cell('', {is_border:true, }).attr('rowspan', height))
+// self.headers = [];
+// _.each(header_rows, function (cells) {
+// header = $('<tr></tr>');
+// header.append(cells);
+// header.addClass('graph_top');
+// self.headers.push(header);
+// });
+// }
+// },
+
+// draw_top_headers: function () {
+// var self = this;
+// $("tr.graph_top").remove();
+// _.each(this.headers.reverse(), function (header) {
+// self.$el.prepend(header);
+// });
+
+// },
+
+// make_row: function (groups, parent_id) {
+// var self = this,
+// path,
+// value,
+// expanded,
+// domain,
+// parent,
+// has_parent = (parent_id !== undefined),
+// row_id = this.generate_id();
+
+// if (has_parent) {
+// parent = this.get_row(parent_id);
+// path = parent.path.concat(groups[0].attributes.value[1]);
+// value = groups[0].attributes.value[1];
+// expanded = false;
+// parent.children.push(row_id);
+// domain = groups[0].model._domain;
+// } else {
+// parent = null;
+// path = [];
+// value = 'Total';
+// expanded = true;
+// domain = this.data.domain;
+// }
+
+// var jquery_row = $('<tr></tr>');
+
+// var header = self.make_cell(value, {is_border:true, indent: path.length, foldable:true, row_id: row_id});
+// jquery_row.append(header);
+
+// var cell;
+
+// _.each(this.cols, function (col) {
+// var element = _.find(groups, function (group) {
+// return _.isEqual(_.rest(group.path), col.path);
+// });
+// if (element === undefined) {
+// cell = self.make_cell('');
+// } else {
+// cell = self.make_cell(element.attributes.aggregates[self.data.measure]);
+// }
+// if (col.expanded) {
+// cell.css('display', 'none');
+// }
+// col.cells.push({td:cell, row_id:row_id});
+// jquery_row.append(cell);
+// });
+
+// if (!has_parent) {
+// header.find('.icon-plus-sign')
+// .removeClass('icon-plus-sign')
+// .addClass('icon-minus-sign');
+// }
+
+// var row = {
+// id: row_id,
+// path: path,
+// value: value,
+// expanded: expanded,
+// parent: parent_id,
+// children: [],
+// html: jquery_row,
+// domain: domain,
+// };
+// this.rows.push(row); // to do, insert it properly, after all childs of parent
+// return row;
+// },
+
+// generate_id: function () {
+// this.id_seed += 1;
+// return this.id_seed - 1;
+// },
+
+// get_row: function (id) {
+// return _.find(this.rows, function(row) {
+// return (row.id == id);
+// });
+// },
+
+// get_col: function (id) {
+// return _.find(this.cols, function(col) {
+// return (col.id == id);
+// });
+// },
+
+// make_cell: function (content, options) {
+// options = _.extend({is_border: false, indent:0, foldable:false}, options);
+// content = (content !== undefined) ? content : 'Undefined';
+
+// var cell = $('<td></td>');
+// if (options.is_border) cell.addClass('graph_border');
+// if (options.row_span) cell.attr('rowspan', options.row_span);
+// if (options.col_span) cell.attr('rowspan', options.col_span);
+// _.each(_.range(options.indent), function () {
+// cell.prepend($('<span/>', {class:'web_graph_indent'}));
+// });
+
+// if (options.foldable) {
+// var attrs = {class:'icon-plus-sign web_graph_click', href:'#'};
+// if (options.row_id !== undefined) attrs['data-row-id'] = options.row_id;
+// if (options.col_id !== undefined) attrs['data-col-id'] = options.col_id;
+// var plus = $('<span/>', attrs);
+// plus.append(' ');
+// plus.append(content);
+// cell.append(plus);
+// } else {
+// cell.append(content);
+// }
+// return cell;
+// },
+
+// expand_row: function (row_id, field_id) {
+// var self = this;
+// var row = this.get_row(row_id);
+
+// if (row.path.length == this.data.row_groupby.length) {
+// this.data.row_groupby.push(field_id);
+// }
+// row.expanded = true;
+// row.html.find('.icon-plus-sign')
+// .removeClass('icon-plus-sign')
+// .addClass('icon-minus-sign');
+
+// var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure);
+// query_groups_data(this.data.model, visible_fields, row.domain, this.data.col_groupby, field_id)
+// .then(function (groups) {
+// _.each(groups.reverse(), function (group) {
+// var new_row = self.make_row(group, row_id);
+// row.html.after(new_row.html);
+// });
+// });
+
+// },
+
+// expand_col: function (col_id, field_id) {
+// var self = this;
+// var col = this.get_col(col_id);
+
+// if (col.path.length == this.data.col_groupby.length) {
+// this.data.col_groupby.push(field_id);
+// }
+// col.expanded = true;
+
+// var visible_fields = this.data.row_groupby.concat(this.data.col_groupby, this.data.measure);
+// query_groups_data(this.data.model, visible_fields, col.domain, this.data.row_groupby, field_id)
+// .then(function (groups) {
+// _.each(groups, function (group) {
+// var new_col = {
+// id: self.generate_id(),
+// path: col.path.concat(group[0].attributes.value[1]),
+// value: group[0].attributes.value[1],
+// expanded: false,
+// parent: col_id,
+// children: [],
+// cells: [], // a cell is {td:<jquery td>, row_id:<some id>}
+// domain: group[0].model._domain,
+// };
+// col.children.push(new_col.id);
+// insertAfter(self.cols, col, new_col)
+// _.each(col.cells, function (cell) {
+// var col_path = self.get_row(cell.row_id).path;
+
+// var datapt = _.find(group, function (g) {
+// return _.isEqual(g.path.slice(1), col_path);
+// });
+
+// var value;
+// if (datapt === undefined) {
+// value = '';
+// } else {
+// value = datapt.attributes.aggregates[self.data.measure];
+// }
+// var new_cell = {
+// row_id: cell.row_id,
+// td: self.make_cell(value)
+// };
+// new_col.cells.push(new_cell);
+// cell.td.after(new_cell.td);
+// cell.td.css('display','none');
+// });
+
+// });
+// self.make_top_headers();
+// self.draw_top_headers();
+// });
+// },
+
+// fold_row: function (row_id) {
+// var self = this;
+// var row = this.get_row(row_id);
+
+// _.each(row.children, function (child_row) {
+// self.remove_row(child_row);
+// });
+// row.children = [];
+
+// row.expanded = false;
+// row.html.find('.icon-minus-sign')
+// .removeClass('icon-minus-sign')
+// .addClass('icon-plus-sign');
+
+// var fold_levels = _.map(self.rows, function(g) {return g.path.length;});
+// var new_groupby_length = _.max(fold_levels);
+
+// this.data.row_groupby.splice(new_groupby_length);
+// },
+
+// remove_row: function (row_id) {
+// var self = this;
+// var row = this.get_row(row_id);
+
+// _.each(row.children, function (child_row) {
+// self.remove_row(child_row);
+// });
+
+// row.html.remove();
+// removeFromArray(this.rows, row);
+
+// _.each(this.cols, function (col) {
+// col.cells = _.filter(col.cells, function (cell) {
+// return cell.row_id !== row_id;
+// });
+// });
+// },
+
+// fold_col: function (col_id) {
+// var self = this;
+// var col = this.get_col(col_id);
+
+// _.each(col.children, function (child_col) {
+// self.remove_col(child_col);
+// });
+// col.children = [];
+
+// _.each(col.cells, function (cell) {
+// cell.td.css('display','table-cell');
+// });
+// col.expanded = false;
+// // row.html.find('.icon-minus-sign')
+// // .removeClass('icon-minus-sign')
+// // .addClass('icon-plus-sign');
+
+// var fold_levels = _.map(self.cols, function(g) {return g.path.length;});
+// var new_groupby_length = _.max(fold_levels);
+
+// this.data.col_groupby.splice(new_groupby_length);
+// this.make_top_headers();
+// this.draw_top_headers();
- },
+// },
- remove_col: function (col_id) {
- var self = this;
- var col = this.get_col(col_id);
+// remove_col: function (col_id) {
+// var self = this;
+// var col = this.get_col(col_id);
- _.each(col.children, function (child_col) {
- self.remove_col(child_col);
- });
+// _.each(col.children, function (child_col) {
+// self.remove_col(child_col);
+// });
- _.each(col.cells, function (cell) {
- cell.td.remove();
- });
- // row.html.remove();
- removeFromArray(this.cols, col);
-
- // _.each(this.cols, function (col) {
- // col.cells = _.filter(col.cells, function (cell) {
- // return cell.row_id !== row_id;
- // });
- // });
- },
+// _.each(col.cells, function (cell) {
+// cell.td.remove();
+// });
+// // row.html.remove();
+// removeFromArray(this.cols, col);
+// // _.each(this.cols, function (col) {
+// // col.cells = _.filter(col.cells, function (cell) {
+// // return cell.row_id !== row_id;
+// // });
+// // });
+// },
-});
+
+// });
};
diff --git a/addons/web_graph/static/src/js/pivot.js b/addons/web_graph/static/src/js/pivot.js
new file mode 100644
index 00000000000..3df67e188d8
--- /dev/null
+++ b/addons/web_graph/static/src/js/pivot.js
@@ -0,0 +1,132 @@
+
+
+var PivotTable = openerp.web.Class.extend({
+ init: function (options) {
+ this.rows = [];
+ this.cols = [];
+ this.cells = [];
+ this.row_groupby = options.row_groupby;
+ this.col_groupby = [];
+ this.model = options.model;
+ this.measure = options.measure;
+ this.measure_label = options.measure_label;
+ this.domain = options.domain;
+
+ this.id_seed = -1;
+ },
+
+ // Load initial data into the rows, cols and cells array.
+ // This function needs to be called after init and before
+ // drawing the table (otherwise the data returned will be empty...)
+ start: function () {
+ var self = this;
+ var main_row = {
+ id: this.generate_id(),
+ path: [],
+ name: "Total",
+ is_expanded: false,
+ parent: null,
+ children: [],
+ domain: this.domain,
+ };
+ this.rows.push(main_row);
+
+ var main_col = {
+ id: this.generate_id(),
+ path: [],
+ name: this.measure_label,
+ is_expanded: false,
+ parent: null,
+ children: [],
+ domain: this.domain,
+ };
+ this.cols.push(main_col);
+
+ // get total and create first cell
+ var tot = query_groups (this.model, this.measure, this.domain, [])
+ .then(function (total) {
+ var val = total[0].attributes.aggregates[self.measure];
+ self.set_value(main_row.id, main_col.id, val);
+ });
+
+ var grp = query_groups (this.model, this.visible_fields(), this.domain, this.row_groupby)
+ .then(function (groups) {
+ _.each(groups, function (group) {
+ var new_row = {
+ id: self.generate_id(),
+ path: [group.attributes.value[1]],
+ name: group.attributes.value[1],
+ is_expanded: false,
+ parent: main_row,
+ children: [],
+ domain: group.model._domain,
+ }
+ self.rows.push(new_row);
+ main_row.children.push(new_row.id);
+ self.set_value(new_row.id, main_col.id,
+ group.attributes.aggregates[self.measure]);
+ });
+ main_row.is_expanded = true;
+ });
+
+ return $.when(tot, grp);
+ },
+
+ generate_id: function () {
+ this.id_seed += 1;
+ return this.id_seed;
+ },
+
+ visible_fields: function () {
+ return this.row_groupby.concat(this.col_groupby, this.measure);
+ },
+
+ set_value: function (row, col, value) {
+ var cell = _.find(this.cells, function (c) {
+ return ((c.row_id == row) && (c.col_id == col));
+ });
+ if (cell) {
+ cell.value = value;
+ } else {
+ this.cells.push({row_id: row, col_id: col, value: value});
+ }
+ },
+
+ get_value: function (row, col) {
+ var cell = _.find(this.cells, function (c) {
+ return ((c.row_id == row) && (c.col_id == col));
+ });
+ return (cell) ? cell.value : '';
+ }
+
+
+});
+
+
+
+ // function expand_row (row, field) {
+
+ // }
+
+ // function expand_col (col, field) {
+
+ // }
+
+ // function fold_row (row) {
+
+ // }
+
+ // function fold_col (col) {
+
+ // }
+
+
+// function update_values () {
+// // update all cells (reload data from db)
+// // return a deferred
+// }
+
+// var id_seed = -1;
+
+// return init();
+// } \ No newline at end of file