osbzr/gooderp_addons

View on GitHub
extra_views/static/src/js/extra_widget.js

Summary

Maintainability
A
1 hr
Test Coverage
odoo.define('ExtraWidget', function(require) {
    "use strict";

    var config = require('web.config');
    var core = require('web.core');
    var Model = require('web.DataModel');
    var formats = require('web.formats');
    var Widget = require('web.Widget');

    var _t = core._t;
    var QWeb = core.qweb;

    // hide top legend when too many item for device size
    var MAX_LEGEND_LENGTH = 25 * (1 + config.device.size_class);

    return Widget.extend({
        className: "o_extra_svg_container",
        init: function(parent, model, options) {
            this._super(parent);
            this.context = options.context;
            this.fields = options.fields;
            this.fields.__count__ = { string: _t("Count"), type: "integer" };
            this.model = new 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__";
            this.stacked = options.stacked;
            this.name = this.getParent().ViewManager.title;
        },
        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 = [];
            this.labels = []
            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]);
                    if (this.labels.length > j) {
                        this.labels[j].push(values[j])
                    } else {
                        this.labels.push([])
                        this.labels[j].push(values[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('ExtraViews.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_views();
            }
        },
        display_views: function() {
            var self = this;
            var myChart = echarts.init(self.$el.parents().find('#main')[0]);
            var option = self.get_options()
            myChart.setOption(option, true);
            return myChart;
        },
        get_options: function() {
            var self = this;
            return eval("self.get_" + self.mode + "_option()");
        },
        prepare_bar_data: function() {
            var self = this;
            _.each(self.data, function(data_row) {
                if (self.xaxis_data && !self.legend_data) {
                    self.series_data.push(data_row.value);
                } else if (self.xaxis_data && self.legend_data) {
                    var row_index = self.series_data.find(function(row) {
                        return row.name === data_row.labels[1];
                    });
                    if (row_index) {
                        row_index.data.push(data_row.value)
                    } else {
                        self.series_data.push({
                            'name': data_row.labels[1],
                            'type': 'bar',
                            'stack': self.context.bar_type && data_row.labels[1] || 'sum',
                            'data': [data_row.value]
                        });
                    };
                };
            });

        },
        get_bar_option: function() {
            var self = this;
            self.legend_data = this.labels && _.unique(this.labels[1]) || [];
            self.xaxis_data = this.labels && _.unique(this.labels[0]) || [];
            self.series_data = [];
            self.prepare_bar_data();
            var option = {

                tooltip: {
                    show: true
                },
                toolbox: self.bar_tool_box(),
                calculable: true,
                legend: {
                    data: self.legend_data || []
                },
                xAxis: [{
                    type: 'category',
                    data: self.xaxis_data || []
                }],
                yAxis: [{
                    type: 'value'
                }],
                series: self.series_data || [],
            }
            return option;
        },
        prepare_pie_data: function() {
            var self = this;
            _.each(self.data, function(data_row) {
                var row_index = self.series_data.find(function(row) {
                    return row.name === data_row.labels[0];
                })
                if (row_index) {
                    row_index.value += data_row.value
                } else {
                    self.series_data.push({ 'value': data_row.value, 'name': data_row.labels[0] })
                }
            });
        },
        get_pie_option: function() {
            var self = this;
            self.legend_data = this.labels && _.unique(this.labels[1]) || [];
            self.xaxis_data = this.labels && _.unique(this.labels[0]) || [];
            self.series_data = [];
            self.prepare_pie_data();
            var option = {
                title: {
                    text: self.name,
                    x: 'center'
                },
                tooltip: {
                    trigger: 'item',
                    formatter: "{a} <br/>{b} : {c} ({d}%)"
                },
                legend: {
                    orient: 'vertical',
                    x: 'left',
                    data: self.xaxis_data
                },
                toolbox: self.pie_tool_box(),
                calculable: true,
                series: [{
                    name: self.name,
                    type: 'pie',
                    radius: '55%',
                    center: ['50%', '60%'],
                    data: self.series_data,
                }],
            };
            return option;
        },

        bar_tool_box: function() {
            var toolbox = {
                show: true,
                feature: {
                    mark: { show: true },
                    dataView: { show: true, readOnly: false },
                    magicType: { show: true, type: ['line', 'bar', 'stack', 'tiled'] },
                    restore: { show: true },
                    saveAsImage: { show: true }
                }
            };
            return toolbox;
        },

        pie_tool_box: function() {
            var toolbox = {
                show: true,
                feature: {
                    mark: { show: true },
                    dataView: { show: true, readOnly: false },
                    magicType: {
                        show: true,
                        type: ['pie', 'funnel'],
                        option: {
                            funnel: {
                                x: '25%',
                                width: '50%',
                                funnelAlign: 'left',
                                max: Math.max(self.series_data)
                            }
                        }
                    },
                    restore: { show: true },
                    saveAsImage: { show: true }
                }
            };
            return toolbox;
        }
    });
});