diff options
| author | Gery Debongnie <ged@openerp.com> | 2013-11-08 16:20:48 +0100 |
|---|---|---|
| committer | Gery Debongnie <ged@openerp.com> | 2013-11-08 16:20:48 +0100 |
| commit | eab6a192e9413c09b67b28fbf856d3314051bc4a (patch) | |
| tree | 07fac9a59d458c5448ae3a8ae9c17ad56fce5e78 /addons/web_graph/static/src | |
| parent | 7ad9aecc13e23ce40a4b22e31ed5f7f9435adf4c (diff) | |
[IMP] add pie, line and bar chart to the chartview widget (addon web_graph)
bzr revid: ged@openerp.com-20131108152048-0akyhf0c7lcdsqjh
Diffstat (limited to 'addons/web_graph/static/src')
| -rw-r--r-- | addons/web_graph/static/src/js/graph.js | 190 | ||||
| -rw-r--r-- | addons/web_graph/static/src/xml/web_graph.xml | 2 |
2 files changed, 189 insertions, 3 deletions
diff --git a/addons/web_graph/static/src/js/graph.js b/addons/web_graph/static/src/js/graph.js index 173f2e8973a..aa4275493b6 100644 --- a/addons/web_graph/static/src/js/graph.js +++ b/addons/web_graph/static/src/js/graph.js @@ -12,6 +12,10 @@ var _t = instance.web._t; instance.web.views.add('graph', 'instance.web_graph.GraphView'); + /** + * GraphView view. It mostly contains two widgets (PivotTable and ChartView) + * and some data. + */ instance.web_graph.GraphView = instance.web.View.extend({ template: 'GraphView', display_name: _lt('Graph'), @@ -19,13 +23,17 @@ instance.web_graph.GraphView = instance.web.View.extend({ events: { 'click .graph_mode_selection li' : function (event) { event.preventDefault(); - var mode = event.target.attributes['data-mode'].nodeValue; + var self = this, + mode = event.target.attributes['data-mode'].nodeValue; if (mode == 'data') { this.chart_view.hide(); this.pivot_table.show(); } else { this.pivot_table.hide(); - this.chart_view.show(mode); + this.get_data().done(function (data) { + self.chart_view.draw(data, mode); + self.chart_view.show(mode); + }); } }, }, @@ -34,20 +42,56 @@ instance.web_graph.GraphView = instance.web.View.extend({ this._super(parent, dataset, view_id, options); this.pivot_table = new PivotTable(this); this.chart_view = new ChartView(this); + this.x_groups = []; + this.measure = null; + this.domain = []; + this.model = null; + }, view_loading: function (fields_view_get) { + var self = this; + this.model = new instance.web.Model(fields_view_get.model, {group_by_no_leaf: true}); + + // get the default groupbys and measure defined in the field view + _.each(fields_view_get.arch.children, function (field) { + if ('name' in field.attrs) { + if ('operator' in field.attrs) { + self.measure = field.attrs.name; + } else { + self.x_groups.push(field.attrs.name); + } + } + }); + + this.chart_view.set_measure(this.measure); this.pivot_table.appendTo('.graph_pivot'); this.chart_view.appendTo('.graph_chart'); this.chart_view.hide(); + this.get_data().done(this.pivot_table.draw); + }, + + get_data: function () { + var view_fields = this.x_groups.concat(this.measure); + + return query_groups(this.model, view_fields, this.domain, this.x_groups); + }, + + do_search: function (domain, context, group_by) { + this.domain = new instance.web.CompoundDomain(domain); }, do_show: function () { this.do_push_state({}); 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', @@ -59,10 +103,18 @@ var PivotTable = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, + draw: function (data) { + console.log("data",data); + }, }); + /** + * ChartView widget. It displays the data in chart form, using the nvd3 + * library. Various modes include bar charts, pie charts or line charts. + */ var ChartView = instance.web.Widget.extend({ template: 'chart_view', + measure: null, show: function () { this.$el.css('display', 'block'); @@ -72,8 +124,142 @@ var ChartView = instance.web.Widget.extend({ this.$el.css('display', 'none'); }, + set_measure: function (measure) { + this.measure = measure; + }, + + draw: function (data, mode) { + // d3.select('.graph_chart_svg').remove(); + + $('.graph_chart_svg').empty(); + $('.graph_chart_svg').append('<svg></svg>'); + + switch (mode) { + case 'bar_chart': + this.render_bar_chart(data); + break; + case 'pie_chart': + this.render_pie_chart(data); + break; + case 'line_chart': + this.render_line_chart(data); + break; + } + }, + + format_data: function (datapt) { + var val = datapt.attributes; + return { + x: datapt.attributes.value[1], + y: this.measure ? val.aggregates[this.measure] : val.length, + }; + }, + + render_bar_chart: function (data) { + var formatted_data = [{ + key: 'Bar chart', + values: _.map(data, this.format_data.bind(this)), + }]; + + nv.addGraph(function () { + var chart = nv.models.discreteBarChart() + .tooltips(false) + .showValues(true) + .staggerLabels(true) + .width(650) + .height(400); + + d3.select('.graph_chart_svg svg') + .datum(formatted_data) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + + render_pie_chart: function (data) { + var formatted_data = _.map(data, this.format_data.bind(this)); + + nv.addGraph(function () { + var chart = nv.models.pieChart() + .color(d3.scale.category10().range()) + .width(650) + .height(400); + + d3.select('.graph_chart_svg svg') + .datum(formatted_data) + .transition().duration(1200) + .attr('width', 650) + .attr('height', 400) + .call(chart); + + nv.utils.windowResize(chart.update); + return chart; + }); + }, + + render_line_chart: function (data) { + var measure_label = (this.measure) ? this.measure : 'Quantity'; + + var formatted_data = [{ + key: measure_label, + values: _.map(data, this.format_data.bind(this)) + }]; + + nv.addGraph(function () { + var width = 600, + height = 300; + + var chart = nv.models.lineChart() + .x(function (d,u) { return u; }) + .width(width) + .height(height) + .margin({top: 30, right: 20, bottom: 20, left: 60}); + + d3.select('.graph_chart_svg svg') + .attr('width', width) + .attr('height', height) + .datum(formatted_data) + .call(chart); + + return chart; + }); + }, + }); +/** + * Query the server and return a deferred which will return the data + * with all the groupbys applied (this is done for now, but the goal + * is to modify read_group in order to allow eager and lazy groupbys + */ +function query_groups (model, fields, domain, groupbys) { + return model.query(fields) + .filter(domain) + .group_by(groupbys) + .then(function (results) { + var non_empty_results = _.filter(results, function (group) { + return group.attributes.length > 0; + }); + if (groupbys.length <= 1) { + return non_empty_results; + } else { + var get_subgroups = $.when.apply(null, _.map(non_empty_results, function (result) { + var new_domain = result.model._domain; + var new_groupings = groupbys.slice(1); + return query_groups(model, fields,new_domain, new_groupings).then(function (subgroups) { + result.subgroups_data = subgroups; + }); + })); + return get_subgroups.then(function () { + return non_empty_results; + }); + } + }); +} }; diff --git a/addons/web_graph/static/src/xml/web_graph.xml b/addons/web_graph/static/src/xml/web_graph.xml index f38dadc74ce..4798e4b1c72 100644 --- a/addons/web_graph/static/src/xml/web_graph.xml +++ b/addons/web_graph/static/src/xml/web_graph.xml @@ -25,7 +25,7 @@ </t> <t t-name="chart_view"> - <svg></svg> + <div class="graph_chart_svg"></div> </t> </templates> |
