diff options
Diffstat (limited to 'addons/web/static/src/js/view_graph.js')
| -rw-r--r-- | addons/web/static/src/js/view_graph.js | 445 |
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(); -}; - - -})(); |
