summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrien Dieudonne <adr@odoo.com>2018-09-19 11:42:06 +0200
committerAdrien Dieudonne <adr@odoo.com>2018-09-20 13:30:50 +0200
commit067754f0f6100b0b2a4bc627dbafdaf3955c8102 (patch)
treedab74bf0878668abcf73fc98342330bec7bb533b
parentb5a12b4aac9484cd342e29f2a0402fb148b09e2e (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__.py1
-rw-r--r--addons/web/static/src/js/widgets/pie_chart.js200
-rw-r--r--addons/web/static/src/xml/pie_chart.xml10
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>