diff options
| author | Gery Debongnie <ged@openerp.com> | 2013-11-22 08:43:27 +0100 |
|---|---|---|
| committer | Gery Debongnie <ged@openerp.com> | 2013-11-22 08:43:27 +0100 |
| commit | d0cb5149b4dc03f233fcce60d498b24ab8ac0259 (patch) | |
| tree | 925e6b54a2538a0ec7b82ce9f58c1e21a50ba7b0 /addons/web_graph/static/src/js | |
| parent | a309c97505dd01072225a1f45b39c19f1e6b32e6 (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.js | 1326 | ||||
| -rw-r--r-- | addons/web_graph/static/src/js/pivot.js | 132 |
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 |
