diff options
| author | Adrien Dieudonne <adr@odoo.com> | 2018-09-19 11:42:06 +0200 |
|---|---|---|
| committer | Adrien Dieudonne <adr@odoo.com> | 2018-09-20 13:30:50 +0200 |
| commit | 067754f0f6100b0b2a4bc627dbafdaf3955c8102 (patch) | |
| tree | dab74bf0878668abcf73fc98342330bec7bb533b | |
| parent | b5a12b4aac9484cd342e29f2a0402fb148b09e2e (diff) | |
[REF] web: Use graph renderer to render pie_chart widget
Before this rev., the pie_chart widget was rendered from scratch
with nv.d3 and we had duplicated code.
In comparison mode, two widgets were instancied and it was a bit
difficult to synchronize the size of these svg graphs.
nv.d3 graphs are attached when the dom is ready because it needs
to calculate the available space. UI bugs can appear if the dom
changes... .update() must be executed on the graph to avoid this
as we already do in graph renderer.
So now, the rendering of the pie_chart widget is done by the
graph renderer.
As comparaison mode is supported by the rendering, only one
widget needs to be instancied.
Task ID: 1835644
| -rw-r--r-- | addons/web/__manifest__.py | 1 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/pie_chart.js | 200 | ||||
| -rw-r--r-- | addons/web/static/src/xml/pie_chart.xml | 10 |
3 files changed, 59 insertions, 152 deletions
diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index bbfe3a134a0..e14aa45c82e 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -25,6 +25,7 @@ This module provides the core of the Odoo Web Client. "static/src/xml/base.xml", "static/src/xml/kanban.xml", "static/src/xml/menu.xml", + "static/src/xml/pie_chart.xml", "static/src/xml/rainbow_man.xml", "static/src/xml/report.xml", "static/src/xml/web_calendar.xml", diff --git a/addons/web/static/src/js/widgets/pie_chart.js b/addons/web/static/src/js/widgets/pie_chart.js index def6147fb05..85e4a8121ec 100644 --- a/addons/web/static/src/js/widgets/pie_chart.js +++ b/addons/web/static/src/js/widgets/pie_chart.js @@ -4,187 +4,83 @@ odoo.define('web.PieChart', function (require) { /** * This widget render a Pie Chart. It is used in the dashboard view. */ -var ajax = require('web.ajax'); -var config = require('web.config'); + +var core = require('web.core'); +var Domain = require('web.Domain'); +var viewRegistry = require('web.view_registry'); var Widget = require('web.Widget'); var widgetRegistry = require('web.widget_registry'); -var GROUPABLE_TYPES = ['many2one', 'char', 'boolean', 'selection', 'date', 'datetime']; +var qweb = core.qweb; var PieChart = Widget.extend({ className: 'o_pie_chart', - cssLibs: [ - '/web/static/lib/nvd3/nv.d3.css' - ], - jsLibs: [ - '/web/static/lib/nvd3/d3.v3.js', - '/web/static/lib/nvd3/nv.d3.js', - '/web/static/src/js/libs/nvd3.js' - ], + xmlDependencies: ['/web/static/src/xml/pie_chart.xml'], /** - * override - * + * @override * @param {Widget} parent * @param {Object} record - * @param {Object} node + * @param {Object} node node from arch */ init: function (parent, record, node) { - this._super(parent); - - this.record = record; - this.model = record.model; - - if (node.attrs.modifiers) { - this.measure = node.attrs.modifiers.measure || ''; - this.measureField = this.record.fields[this.measure]; - this.groupBy = node.attrs.modifiers.groupby.split(':')[0] || ''; - this.interval = node.attrs.modifiers.groupby.split(':')[1]; + this._super.apply(this, arguments); - if (!_.contains(Object.keys(this.record.fields), this.groupBy)) { - return; - } - - this.groupByField = this.record.fields[this.groupBy]; - this.groupByType = this.groupByField.type; - this.title = node.attrs.modifiers.title || this.measure || ''; - this.trueLabel = node.attrs.modifiers.trueLabel || 'True'; - this.falseLabel = node.attrs.modifiers.falseLabel || 'False'; - } - }, - /** - * override - */ - willStart: function () { - var self = this; - this.data = []; + var modifiers = node.attrs.modifiers; + var domain = record.domain.concat( + Domain.prototype.stringToArray(modifiers.domain || '[]')); + var arch = qweb.render('web.PieChart', { + modifiers: modifiers, + }); - var query = { - model: this.model, - method: 'read_group', - domain: [], - groupBy: [this.groupBy + (this.interval ? ':' + this.interval : '')], - fields: [this.measure], - lazy: false, + this.subViewParams = { + context: record.context, + domain: domain, + groupBy: [], + modelName: record.model, + withControlPanel: false, + isEmbedded: true, + mode: 'pie', + title: modifiers.title || modifiers.measure || '', }; - // Handle case where measure attribute is missing. - query.fields = this.measure ? [this.measure] : []; - - return $.when(this._rpc(query), ajax.loadLibs(this)).then( - function (result) { - if (result) { - if (_.contains(GROUPABLE_TYPES, self.groupByType)) { - for (var i = 0; i < result.length; i++) { - var value = result[i][self.measure]; - var label = undefined; - var interval = self.interval ? ':' + self.interval : ''; - var groupby = self.groupBy + interval; - - switch (self.groupByType) { - case 'boolean': - label = ['False', 'True'][i]; - break; - case 'many2one': - label = result[i][groupby][1]; - break; - default: - label = result[i][groupby]; - } - - self.data.push({ - 'label': label, - 'value': value, - }); - } - } - } - }); + this.viewInfo = { + arch: arch, + fields: record.fields, + viewFields: record.fieldsInfo.dashboard, + }; }, - /** - * This method ensure that Pie Chart is attached to DOM before being rendered. + * Instantiates the pie chart view and starts the graph controller. * - * If we don't do that, Pie Chart can be rendered without being aware of the - * size of its container, it is then rendered with a size of 0 0 and remains - * invisible (even with a good lens). - */ - on_attach_callback: function() { - this._render(); - }, - - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - /** - * @private + * @override */ - _render: function () { - // Note: The rendering of this widget is aynchronous as NVD3 does a - // setTimeout(0) before executing the callback given to addGraph. + willStart: function () { var self = this; - if(!this.data || !_.isArray(this.data)) { - return; - } - - var $label = this._renderLabel(this.title); - this.$el.empty(); - $label.appendTo(this.$el); - $('<svg width=auto height=auto>').appendTo(this.$el); - - var legend_right = config.device.size_class > config.device.SIZES.XS; - var legendPosition = legend_right ? 'right' : 'top'; - var color = d3.scale.category10().range(); + var def1 = this._super.apply(this, arguments); - nv.addGraph(function () { - self.chart = nv.models.pieChart() - .x(function(d) { return d.label }) - .y(function(d) { return d.value }) - .legendPosition(legendPosition) - .labelType('percent') - .showLabels(true) - .showLegend(true) - .color(color); - - self.chart.legend.rightAlign(false); - self.chart.legend.align(true); - self.chart.legend.expanded(true); - - d3.select(self.$('svg')[0]) - .datum(self.data) - .transition().duration(0) - .call(self.chart); - self.chart.update(); + var SubView = viewRegistry.get('graph'); + var subView = new SubView(this.viewInfo, this.subViewParams); + var def2 = subView.getController(this).then(function (controller) { + self.controller = controller; + return self.controller.appendTo(document.createDocumentFragment()); }); + return $.when(def1, def2); }, /** - * @private - * @param {any} value - * @param {any} field - * @returns {string} + * @override */ - _getNumberedValue: function (value, field) { - var id = value[0]; - var name = value[1]; - this.numbering[field] = this.numbering[field] || {}; - this.numbering[field][name] = this.numbering[field][name] || {}; - var numbers = this.numbering[field][name]; - numbers[id] = numbers[id] || _.size(numbers) + 1; - return name + (numbers[id] > 1 ? " (" + numbers[id] + ")" : ""); + start: function () { + this.$el.append(this.controller.$el); + return this._super.apply(this, arguments); }, - /** - * Renders a pie chart's label. + /** + * Call `on_attach_callback` for each subview * - * @private - * @param {String} title - * @returns {jQueryElement} + * @override */ - _renderLabel: function (title) { - var $result = $('<label>', {text: title}); - return $result; + on_attach_callback: function () { + this.controller.on_attach_callback(); }, }); diff --git a/addons/web/static/src/xml/pie_chart.xml b/addons/web/static/src/xml/pie_chart.xml new file mode 100644 index 00000000000..31f31b5b8d2 --- /dev/null +++ b/addons/web/static/src/xml/pie_chart.xml @@ -0,0 +1,10 @@ +<template> + +<t t-name="web.PieChart"> + <graph type="pie"> + <field t-att-name="modifiers.groupby.split(':')[0]" t-att-interval="modifiers.groupby.split(':')[1]"/> + <field t-if="modifiers.measure" t-att-name="modifiers.measure" type="measure"/> + </graph> +</t> + +</template> |
