summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/view_graph.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src/js/view_graph.js')
-rw-r--r--addons/web/static/src/js/view_graph.js445
1 files changed, 0 insertions, 445 deletions
diff --git a/addons/web/static/src/js/view_graph.js b/addons/web/static/src/js/view_graph.js
deleted file mode 100644
index 385f347e307..00000000000
--- a/addons/web/static/src/js/view_graph.js
+++ /dev/null
@@ -1,445 +0,0 @@
-/*---------------------------------------------------------
- * Odoo Pivot Table view
- *---------------------------------------------------------*/
-
-(function (a, b, c) {
-'use strict';
-
-var instance = openerp,
- _lt = instance.web._lt,
- _t = instance.web._t,
- QWeb = instance.web.qweb;
-
-nv.dev = false; // sets nvd3 library in production mode
-
-instance.web.views.add('graph', 'instance.web.GraphView');
-
-instance.web.GraphView = instance.web.View.extend({
- className: 'oe_graph',
- display_name: _lt('Graph'),
- view_type: 'graph',
-
- init: function(parent, dataset, view_id, options) {
- this._super(parent, dataset, view_id, options);
-
- this.model = new instance.web.Model(dataset.model, {group_by_no_leaf: true});
- this.measures = [];
- this.active_measure = '__count__';
- this.initial_groupbys = [];
- this.widget = undefined;
- },
- start: function () {
- var load_fields = this.model.call('fields_get', [])
- .then(this.prepare_fields.bind(this));
-
- return $.when(this._super(), load_fields).then(this.render_buttons.bind(this));
- },
- render_buttons: function () {
- var context = {measures: _.pairs(_.omit(this.measures, '__count__'))};
- this.$buttons.html(QWeb.render('GraphView.buttons', context));
- this.$measure_list = this.$buttons.find('.oe-measure-list');
- this.update_measure();
- this.$buttons.find('button').tooltip();
- this.$buttons.click(this.on_button_click.bind(this));
- },
- update_measure: function () {
- var self = this;
- this.$measure_list.find('li').each(function (index, li) {
- $(li).toggleClass('selected', $(li).data('field') === self.active_measure);
- });
- },
- view_loading: function (fvg) {
- var self = this;
- fvg.arch.children.forEach(function (field) {
- var name = field.attrs.name;
- if (field.attrs.interval) {
- name += ':' + field.attrs.interval;
- }
- if (field.attrs.type === 'measure') {
- self.active_measure = name;
- } else {
- self.initial_groupbys.push(name);
- }
- });
- },
- do_show: function () {
- this.do_push_state({});
- this.$el.show();
- return this._super();
- },
- prepare_fields: function (fields) {
- var self = this;
- this.fields = fields;
- _.each(fields, function (field, name) {
- if ((name !== 'id') && (field.store === true)) {
- if (field.type === 'integer' || field.type === 'float') {
- self.measures[name] = field;
- }
- }
- });
- this.measures.__count__ = {string: _t("Quantity"), type: "integer"};
- },
- do_search: function (domain, context, group_by) {
- if (!this.widget) {
- this.initial_groupbys = context.graph_groupbys || this.initial_groupbys;
- this.widget = new instance.web.GraphWidget(this, this.dataset.model, {
- measure: context.graph_measure || this.active_measure,
- mode: context.graph_mode || this.active_mode,
- domain: domain,
- groupbys: this.initial_groupbys,
- context: context,
- fields: this.fields,
- });
- // append widget
- this.$el.hide();
- this.widget.appendTo(this.$el);
- } else {
- var groupbys = group_by.length ? group_by : this.initial_groupbys.slice(0);
- this.widget.update_data(domain, groupbys);
- }
- },
- get_context: function () {
- return !this.widget ? {} : {
- graph_mode: this.widget.mode,
- graph_measure: this.widget.measure,
- graph_groupbys: this.widget.groupbys
- };
- },
- on_button_click: function (event) {
- var $target = $(event.target);
- if ($target.hasClass('oe-bar-mode')) {this.widget.set_mode('bar');}
- if ($target.hasClass('oe-line-mode')) {this.widget.set_mode('line');}
- if ($target.hasClass('oe-pie-mode')) {this.widget.set_mode('pie');}
- if ($target.parents('.oe-measure-list').length) {
- var parent = $target.parent(),
- field = parent.data('field');
- this.active_measure = field;
- parent.toggleClass('selected');
- event.stopPropagation();
- this.update_measure();
- this.widget.set_measure(this.active_measure);
- }
- },
-});
-
-instance.web.GraphWidget = instance.web.Widget.extend({
- init: function (parent, model, options) {
- this._super(parent);
- this.context = options.context;
- this.fields = options.fields;
- this.fields.__count__ = _t("Quantity");
- this.model = new instance.web.Model(model, {group_by_no_leaf: true});
-
- this.domain = options.domain || [];
- this.groupbys = options.groupbys || [];
- this.mode = options.mode || "bar";
- this.measure = options.measure || "__count__";
- },
- start: function () {
- return this.load_data().then(this.proxy('display_graph'));
- },
- update_data: function (domain, groupbys) {
- this.domain = domain;
- this.groupbys = groupbys;
- return this.load_data().then(this.proxy('display_graph'));
- },
- set_mode: function (mode) {
- this.mode = mode;
- this.display_graph();
- },
- set_measure: function (measure) {
- this.measure = measure;
- return this.load_data().then(this.proxy('display_graph'));
- },
- load_data: function () {
- var fields = this.groupbys.slice(0);
- if (this.measure !== '__count__'.slice(0))
- fields = fields.concat(this.measure);
- return this.model
- .query(fields)
- .filter(this.domain)
- .context(this.context)
- .lazy(false)
- .group_by(this.groupbys.slice(0,2))
- .then(this.proxy('prepare_data'));
- },
- prepare_data: function () {
- var raw_data = arguments[0],
- is_count = this.measure === '__count__';
- var data_pt, j, values, value;
-
- this.data = [];
- for (var i = 0; i < raw_data.length; i++) {
- data_pt = raw_data[i].attributes;
- values = [];
- if (this.groupbys.length === 1) data_pt.value = [data_pt.value];
- for (j = 0; j < data_pt.value.length; j++) {
- values[j] = this.sanitize_value(data_pt.value[j], data_pt.grouped_on[j]);
- }
- value = is_count ? data_pt.length : data_pt.aggregates[this.measure];
- this.data.push({
- labels: values,
- value: value
- });
- }
- },
- sanitize_value: function (value, field) {
- if (value === false) return _t("Undefined");
- if (value instanceof Array) return value[1];
- if (field && this.fields[field] && (this.fields[field].type === 'selection')) {
- var selected = _.where(this.fields[field].selection, {0: value})[0];
- return selected ? selected[1] : value;
- }
- return value;
- },
- display_graph: function () {
- if (this.to_remove) {
- nv.utils.offWindowResize(this.to_remove);
- }
- this.$el.empty();
- if (!this.data.length) {
- this.$el.append(QWeb.render('GraphView.error', {
- title: _t("No data to display"),
- description: _t("No data available for this chart. " +
- "Try to add some records, or make sure that" +
- "there is no active filter in the search bar."),
- }));
- } else {
- this['display_' + this.mode]();
- }
- },
- display_bar: function () {
- // prepare data for bar chart
- var data, values,
- measure = this.fields[this.measure].string;
- // zero groupbys
- if (this.groupbys.length === 0) {
- data = [{
- values: [{
- x: this.ViewManager.title,
- y: this.data[0].value}],
- key: measure
- }];
- }
- // one groupby
- if (this.groupbys.length === 1) {
- values = this.data.map(function (datapt) {
- return {x: datapt.labels, y: datapt.value};
- });
- data = [
- {
- values: values,
- key: measure,
- }
- ];
- }
- if (this.groupbys.length > 1) {
- var xlabels = [],
- series = [],
- label, serie, value;
- values = {};
- for (var i = 0; i < this.data.length; i++) {
- label = this.data[i].labels[0];
- serie = this.data[i].labels[1];
- value = this.data[i].value;
- if ((!xlabels.length) || (xlabels[xlabels.length-1] !== label)) {
- xlabels.push(label);
- }
- series.push(this.data[i].labels[1]);
- if (!(serie in values)) {values[serie] = {};}
- values[serie][label] = this.data[i].value;
- }
- series = _.uniq(series);
- data = [];
- var current_serie, j;
- for (i = 0; i < series.length; i++) {
- current_serie = {values: [], key: series[i]};
- for (j = 0; j < xlabels.length; j++) {
- current_serie.values.push({
- x: xlabels[j],
- y: values[series[i]][xlabels[j]] || 0,
- });
- }
- data.push(current_serie);
- }
- }
- var svg = d3.select(this.$el[0]).append('svg');
- svg.datum(data);
-
- svg.transition().duration(0);
-
- var chart = nv.models.multiBarChart();
- chart.options({
- delay: 250,
- transitionDuration: 10,
- showLegend: true,
- showXAxis: true,
- showYAxis: true,
- rightAlignYAxis: false,
- stacked: true,
- reduceXTicks: false,
- // rotateLabels: 40,
- showControls: (this.groupbys.length > 1)
- });
-
- chart(svg);
- this.to_remove = chart.update;
- nv.utils.onWindowResize(chart.update);
- },
- display_pie: function () {
- var data = [],
- tickValues,
- tickFormat,
- measure = this.fields[this.measure].string;
-
- var all_negative = true,
- some_negative = false,
- all_zero = true;
- this.data.forEach(function (datapt) {
- all_negative = all_negative && (datapt.value < 0);
- some_negative = some_negative || (datapt.value < 0);
- all_zero = all_zero && (datapt.value === 0)
- });
- if (some_negative && !all_negative) {
- return this.$el.append(QWeb.render('GraphView.error', {
- title: _t("Invalid data"),
- description: _t("Pie chart cannot mix positive and negative numbers. " +
- "Try to change your domain to only display positive results"),
- }));
- }
- if (all_zero) {
- return this.$el.append(QWeb.render('GraphView.error', {
- title: _t("Invalid data"),
- description: _t("Pie chart cannot display all zero numbers.. " +
- "Try to change your domain to display positive results"),
- }));
- }
- if (this.groupbys.length) {
- data = this.data.map(function (datapt) {
- return {x:datapt.labels.join("/"), y: datapt.value};
- });
- }
- var svg = d3.select(this.$el[0]).append('svg');
- svg.datum(data);
-
- svg.transition().duration(100);
-
- var chart = nv.models.pieChart();
- chart.options({
- delay: 250,
- transitionDuration: 100,
- color: d3.scale.category10().range(),
- });
-
- chart(svg);
- this.to_remove = chart.update;
- nv.utils.onWindowResize(chart.update);
- },
- display_line: function () {
- if (this.data.length < 2) {
- this.$el.append(QWeb.render('GraphView.error', {
- title: _t("Not enough data points"),
- description: "You need at least two data points to display a line chart."
- }));
- return;
- }
- var self = this,
- data = [],
- tickValues,
- tickFormat,
- measure = this.fields[this.measure].string;
- if (this.groupbys.length === 1) {
- var values = this.data.map(function (datapt, index) {
- return {x: index, y: datapt.value};
- });
- data = [
- {
- values: values,
- key: measure,
- }
- ];
- tickValues = this.data.map(function (d, i) { return i;});
- tickFormat = function (d) {return self.data[d].labels;};
- }
- if (this.groupbys.length > 1) {
- data = [];
- var data_dict = {},
- tick = 0,
- tickLabels = [],
- serie, tickLabel,
- identity = function (p) {return p;};
- tickValues = [];
- for (var i = 0; i < this.data.length; i++) {
- if (this.data[i].labels[0] !== tickLabel) {
- tickLabel = this.data[i].labels[0];
- tickValues.push(tick);
- tickLabels.push(tickLabel);
- tick++;
- }
- serie = this.data[i].labels[1];
- if (!data_dict[serie]) {
- data_dict[serie] = {
- values: [],
- key: serie,
- };
- }
- data_dict[serie].values.push({
- x: tick, y: this.data[i].value,
- });
- data = _.map(data_dict, identity);
- }
- tickFormat = function (d) {return tickLabels[d];};
- }
-
- var svg = d3.select(this.$el[0]).append('svg');
- svg.datum(data);
-
- svg.transition().duration(0);
-
- var chart = nv.models.lineChart();
- chart.options({
- margin: {left: 50, right: 50},
- useInteractiveGuideline: true,
- showLegend: true,
- showXAxis: true,
- showYAxis: true,
- });
- chart.xAxis.tickValues(tickValues)
- .tickFormat(tickFormat);
-
- chart(svg);
- this.to_remove = chart.update;
- nv.utils.onWindowResize(chart.update);
- },
- destroy: function () {
- nv.utils.offWindowResize(this.to_remove);
- return this._super();
- }
-});
-
-// monkey patch nvd3 to allow removing eventhandler on windowresize events
-// see https://github.com/novus/nvd3/pull/396 for more details
-
-// Adds a resize listener to the window.
-nv.utils.onWindowResize = function(fun) {
- if (fun === null) return;
- window.addEventListener('resize', fun);
-};
-
-// Backwards compatibility with current API.
-nv.utils.windowResize = nv.utils.onWindowResize;
-
-// Removes a resize listener from the window.
-nv.utils.offWindowResize = function(fun) {
- if (fun === null) return;
- window.removeEventListener('resize', fun);
-};
-
-// monkey patch nvd3 to prevent crashes when user changes view and nvd3 tries
-// to remove tooltips after 500 ms... seriously nvd3, what were you thinking?
-nv.tooltip.cleanup = function () {
- $('.nvtooltip').remove();
-};
-
-
-})();