From 343d0560d5079729cafef9fd7fe53eb47902f827 Mon Sep 17 00:00:00 2001
From: Alexey Pelykh <alexey.pelykh@gmail.com>
Date: Thu, 6 Dec 2018 14:25:47 +0200
Subject: [PATCH] [FIX] web_widget_x2many_2d_matrix: _renderBodyCell +
 _renderAggregateColCells

---
 web_widget_x2many_2d_matrix/README.rst        |  18 ++-
 web_widget_x2many_2d_matrix/__manifest__.py   |   3 +-
 .../readme/DESCRIPTION.rst                    |   2 +-
 .../readme/HISTORY.rst                        |  11 ++
 .../static/description/index.html             |  57 ++++++---
 .../static/src/js/2d_matrix_renderer.js       | 108 +++++++++++-------
 .../static/src/js/widget_x2many_2d_matrix.js  |  12 +-
 7 files changed, 148 insertions(+), 63 deletions(-)
 create mode 100644 web_widget_x2many_2d_matrix/readme/HISTORY.rst

diff --git a/web_widget_x2many_2d_matrix/README.rst b/web_widget_x2many_2d_matrix/README.rst
index 1372c625ae4a..c0693fcf41c4 100644
--- a/web_widget_x2many_2d_matrix/README.rst
+++ b/web_widget_x2many_2d_matrix/README.rst
@@ -42,7 +42,7 @@ An example use case would be: Select some projects and some employees so that
 a manager can easily fill in the planned_hours for one task per employee. The
 result could look like this:
 
-.. image:: https://raw.githubusercontent.com/web_widget_x2many_2d_matrix/static/description/screenshot.png
+.. image:: https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png
     :alt: Screenshot
 
 The beauty of this is that you have an arbitrary amount of columns with this
@@ -168,6 +168,21 @@ Known issues / Roadmap
 
 * Support extra invisible fields inside each cell.
 
+Changelog
+=========
+
+12.0.1.0.1 (2018-12-07)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* [FIX] Cells are unable to render property.
+  (`#1126 <https://github.com/OCA/web/issues/1126>`_)
+
+12.0.1.0.0 (2018-11-20)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* [12.0][MIG] web_widget_x2many_2d_matrix
+  (`#1101 <https://github.com/OCA/web/issues/1101>`_)
+
 Bug Tracker
 ===========
 
@@ -187,6 +202,7 @@ Authors
 * Therp BV
 * Tecnativa
 * Camptocamp
+* Brainbean Apps
 
 Contributors
 ~~~~~~~~~~~~
diff --git a/web_widget_x2many_2d_matrix/__manifest__.py b/web_widget_x2many_2d_matrix/__manifest__.py
index bfee53ec3550..3299e66b71ac 100644
--- a/web_widget_x2many_2d_matrix/__manifest__.py
+++ b/web_widget_x2many_2d_matrix/__manifest__.py
@@ -4,11 +4,12 @@
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
 {
     'name': '2D matrix for x2many fields',
-    'version': '12.0.1.0.0',
+    'version': '12.0.1.0.1',
     'author': (
         'Therp BV, '
         'Tecnativa, '
         'Camptocamp, '
+        'Brainbean Apps, '
         'Odoo Community Association (OCA)'
     ),
     'website': 'https://github.com/OCA/web',
diff --git a/web_widget_x2many_2d_matrix/readme/DESCRIPTION.rst b/web_widget_x2many_2d_matrix/readme/DESCRIPTION.rst
index a84da8005ae6..d3f10cae8eef 100644
--- a/web_widget_x2many_2d_matrix/readme/DESCRIPTION.rst
+++ b/web_widget_x2many_2d_matrix/readme/DESCRIPTION.rst
@@ -15,7 +15,7 @@ An example use case would be: Select some projects and some employees so that
 a manager can easily fill in the planned_hours for one task per employee. The
 result could look like this:
 
-.. image:: /web_widget_x2many_2d_matrix/static/description/screenshot.png
+.. image:: https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png
     :alt: Screenshot
 
 The beauty of this is that you have an arbitrary amount of columns with this
diff --git a/web_widget_x2many_2d_matrix/readme/HISTORY.rst b/web_widget_x2many_2d_matrix/readme/HISTORY.rst
new file mode 100644
index 000000000000..8bad8c46cd42
--- /dev/null
+++ b/web_widget_x2many_2d_matrix/readme/HISTORY.rst
@@ -0,0 +1,11 @@
+12.0.1.0.1 (2018-12-07)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* [FIX] Cells are unable to render property.
+  (`#1126 <https://github.com/OCA/web/issues/1126>`_)
+
+12.0.1.0.0 (2018-11-20)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* [12.0][MIG] web_widget_x2many_2d_matrix
+  (`#1101 <https://github.com/OCA/web/issues/1101>`_)
diff --git a/web_widget_x2many_2d_matrix/static/description/index.html b/web_widget_x2many_2d_matrix/static/description/index.html
index bd5775f28619..1be53a2a7d6c 100644
--- a/web_widget_x2many_2d_matrix/static/description/index.html
+++ b/web_widget_x2many_2d_matrix/static/description/index.html
@@ -397,29 +397,34 @@ <h1 class="title">2D matrix for x2many fields</h1>
 <p>An example use case would be: Select some projects and some employees so that
 a manager can easily fill in the planned_hours for one task per employee. The
 result could look like this:</p>
-<img alt="Screenshot" src="https://raw.githubusercontent.com/web_widget_x2many_2d_matrix/static/description/screenshot.png" />
+<img alt="Screenshot" src="https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png" />
 <p>The beauty of this is that you have an arbitrary amount of columns with this
 widget, trying to get this in standard x2many lists involves some quite ugly
 hacks.</p>
 <p><strong>Table of contents</strong></p>
 <div class="contents local topic" id="contents">
 <ul class="simple">
-<li><a class="reference internal" href="#usage" id="id1">Usage</a><ul>
-<li><a class="reference internal" href="#example" id="id2">Example</a></li>
+<li><a class="reference internal" href="#usage" id="id5">Usage</a><ul>
+<li><a class="reference internal" href="#example" id="id6">Example</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#known-issues-roadmap" id="id3">Known issues / Roadmap</a></li>
-<li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
-<li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
-<li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
-<li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
-<li><a class="reference internal" href="#maintainers" id="id8">Maintainers</a></li>
+<li><a class="reference internal" href="#known-issues-roadmap" id="id7">Known issues / Roadmap</a></li>
+<li><a class="reference internal" href="#changelog" id="id8">Changelog</a><ul>
+<li><a class="reference internal" href="#id1" id="id9">12.0.1.0.1 (2018-12-07)</a></li>
+<li><a class="reference internal" href="#id3" id="id10">12.0.1.0.0 (2018-11-20)</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#bug-tracker" id="id11">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="id12">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="id13">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="id14">Contributors</a></li>
+<li><a class="reference internal" href="#maintainers" id="id15">Maintainers</a></li>
 </ul>
 </li>
 </ul>
 </div>
 <div class="section" id="usage">
-<h1><a class="toc-backref" href="#id1">Usage</a></h1>
+<h1><a class="toc-backref" href="#id5">Usage</a></h1>
 <p>Use this widget by saying:</p>
 <pre class="literal-block">
 &lt;field name=&quot;my_field&quot; widget=&quot;x2many_2d_matrix&quot; /&gt;
@@ -457,7 +462,7 @@ <h1><a class="toc-backref" href="#id1">Usage</a></h1>
 column totals. True by default</dd>
 </dl>
 <div class="section" id="example">
-<h2><a class="toc-backref" href="#id2">Example</a></h2>
+<h2><a class="toc-backref" href="#id6">Example</a></h2>
 <p>You need a data structure already filled with values. Let’s assume we want to
 use this widget in a wizard that lets the user fill in planned hours for one
 task per project per user. In this case, we can use <tt class="docutils literal">project.task</tt> as our
@@ -509,7 +514,7 @@ <h2><a class="toc-backref" href="#id2">Example</a></h2>
 </div>
 </div>
 <div class="section" id="known-issues-roadmap">
-<h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
+<h1><a class="toc-backref" href="#id7">Known issues / Roadmap</a></h1>
 <ul class="simple">
 <li>Support extra attributes on each field cell via <cite>field_extra_attrs</cite> param.
 We could set a cell as not editable, required or readonly for instance.
@@ -523,8 +528,25 @@ <h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
 <li>Support extra invisible fields inside each cell.</li>
 </ul>
 </div>
+<div class="section" id="changelog">
+<h1><a class="toc-backref" href="#id8">Changelog</a></h1>
+<div class="section" id="id1">
+<h2><a class="toc-backref" href="#id9">12.0.1.0.1 (2018-12-07)</a></h2>
+<ul class="simple">
+<li>[FIX] Cells are unable to render property.
+(<a class="reference external" href="https://github.com/OCA/web/issues/1126">#1126</a>)</li>
+</ul>
+</div>
+<div class="section" id="id3">
+<h2><a class="toc-backref" href="#id10">12.0.1.0.0 (2018-11-20)</a></h2>
+<ul class="simple">
+<li>[12.0][MIG] web_widget_x2many_2d_matrix
+(<a class="reference external" href="https://github.com/OCA/web/issues/1101">#1101</a>)</li>
+</ul>
+</div>
+</div>
 <div class="section" id="bug-tracker">
-<h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
+<h1><a class="toc-backref" href="#id11">Bug Tracker</a></h1>
 <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
 In case of trouble, please check there if your issue has already been reported.
 If you spotted it first, help us smashing it by providing a detailed and welcomed
@@ -532,17 +554,18 @@ <h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
 <p>Do not contact contributors directly about support or help with technical issues.</p>
 </div>
 <div class="section" id="credits">
-<h1><a class="toc-backref" href="#id5">Credits</a></h1>
+<h1><a class="toc-backref" href="#id12">Credits</a></h1>
 <div class="section" id="authors">
-<h2><a class="toc-backref" href="#id6">Authors</a></h2>
+<h2><a class="toc-backref" href="#id13">Authors</a></h2>
 <ul class="simple">
 <li>Therp BV</li>
 <li>Tecnativa</li>
 <li>Camptocamp</li>
+<li>Brainbean Apps</li>
 </ul>
 </div>
 <div class="section" id="contributors">
-<h2><a class="toc-backref" href="#id7">Contributors</a></h2>
+<h2><a class="toc-backref" href="#id14">Contributors</a></h2>
 <ul class="simple">
 <li>Holger Brunn &lt;<a class="reference external" href="mailto:hbrunn&#64;therp.nl">hbrunn&#64;therp.nl</a>&gt;</li>
 <li>Pedro M. Baeza &lt;<a class="reference external" href="mailto:pedro.baeza&#64;tecnativa.com">pedro.baeza&#64;tecnativa.com</a>&gt;</li>
@@ -555,7 +578,7 @@ <h2><a class="toc-backref" href="#id7">Contributors</a></h2>
 </ul>
 </div>
 <div class="section" id="maintainers">
-<h2><a class="toc-backref" href="#id8">Maintainers</a></h2>
+<h2><a class="toc-backref" href="#id15">Maintainers</a></h2>
 <p>This module is maintained by the OCA.</p>
 <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
 <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
diff --git a/web_widget_x2many_2d_matrix/static/src/js/2d_matrix_renderer.js b/web_widget_x2many_2d_matrix/static/src/js/2d_matrix_renderer.js
index ac627e44c7c0..30808ae1be02 100644
--- a/web_widget_x2many_2d_matrix/static/src/js/2d_matrix_renderer.js
+++ b/web_widget_x2many_2d_matrix/static/src/js/2d_matrix_renderer.js
@@ -1,23 +1,25 @@
 /* Copyright 2018 Simone Orsi <simone.orsi@camptocamp.com>
+ * Copyright 2018 Brainbean Apps
  * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
 
 odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (require) {
     "use strict";
 
-    // Heavily inspired by Odoo's `ListRenderer`
     var BasicRenderer = require('web.BasicRenderer');
     var config = require('web.config');
     var core = require('web.core');
     var field_utils = require('web.field_utils');
     var _t = core._t;
+    
     var FIELD_CLASSES = {
-        // Copied from ListRenderer
         float: 'o_list_number',
         integer: 'o_list_number',
         monetary: 'o_list_number',
         text: 'o_list_text',
     };
 
+    // X2Many2dMatrixRenderer is heavily inspired by Odoo's ListRenderer
+    // and is reusing portions of code from list_renderer.js
     var X2Many2dMatrixRenderer = BasicRenderer.extend({
 
         /**
@@ -53,8 +55,11 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
         _renderView: function () {
             var self = this;
 
+            this.$el
+                .removeClass('table-responsive')
+                .empty();
+
             // Display a nice message if there's no data to display
-            this.$el.empty();
             if (!self.rows.length) {
                 var $alert = $('<div>', {'class': 'alert alert-info'});
                 $alert.text(_t('Sorry no matrix data to display.'));
@@ -170,7 +175,10 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
          * @returns {String} a string with the generated html.
          */
         _renderRows: function () {
-            return _.map(this.rows, this._renderRow.bind(this));
+            return _.map(this.rows, function (row) {
+                row.attrs.name = this.matrix_data.field_value;
+                return this._renderRow(row);
+            }.bind(this));
         },
 
         /**
@@ -187,11 +195,11 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
             var $tr = $('<tr/>', {class: 'o_data_row'}),
                 _data = _.without(row.data, undefined);
             $tr = $tr.append(this._renderLabelCell(_data[0]));
-            var $cells = _.map(this.columns, function (node, index) {
+            var $cells = _.map(this.columns, function (column, index) {
                 var record = row.data[index];
                 // Make the widget use our field value for each cell
-                node.attrs.name = this.matrix_data.field_value;
-                return this._renderBodyCell(record, node, index, {mode:''});
+                column.attrs.name = this.matrix_data.field_value;
+                return this._renderBodyCell(record, column, index, {mode:''});
             }.bind(this));
             $tr = $tr.append($cells);
             if (row.aggregate) {
@@ -227,8 +235,8 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
          * @returns {jQueryElement} The rendered cell.
          */
         _renderAggregateRowCell: function (row) {
-            var $cell = $('<td/>', {class: 'row-total text-right'});
-            this._apply_aggregate_value($cell, row.aggregate);
+            var $cell = $('<td/>', {class: 'row-total'});
+            this.applyAggregateValue($cell, row);
             return $cell;
         },
 
@@ -246,9 +254,7 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
          */
         _renderBodyCell: function (record, node, colIndex, options) {
             var tdClassName = 'o_data_cell';
-            if (node.tag === 'button') {
-                tdClassName += ' o_list_button';
-            } else if (node.tag === 'field') {
+            if (node.tag === 'field') {
                 var typeClass = FIELD_CLASSES[
                     this.state.fields[node.attrs.name].type
                 ];
@@ -259,11 +265,14 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
                     tdClassName += ' o_' + node.attrs.widget + '_cell';
                 }
             }
+
             // TODO roadmap: here we should collect possible extra params
             // the user might want to attach to each single cell.
+
             var $td = $('<td>', {
                 'class': tdClassName,
             });
+
             if (_.isUndefined(record)) {
                 // Without record, nothing elese to do
                 return $td;
@@ -272,6 +281,7 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
                 'data-form-id': record.id,
                 'data-id': record.data.id,
             });
+
             // We register modifiers on the <td> element so that it gets
             // the correct modifiers classes (for styling)
             var modifiers = this._registerModifiers(
@@ -286,13 +296,28 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
             if (modifiers.invisible && !(options && options.renderInvisible)) {
                 return $td;
             }
+
             // Enforce mode of the parent
             options.mode = this.getParent().mode;
-            var widget = this._renderFieldWidget(
-                node, record, _.pick(options, 'mode')
-            );
-            this._handleAttributes(widget.$el, node);
-            return $td.append(widget.$el);
+
+            if (node.tag === 'widget') {
+                return $td.append(this._renderWidget(record, node));
+            }
+            if (node.attrs.widget || (options && (options.renderWidgets || options.mode === 'edit'))) {
+                var $el = this._renderFieldWidget(node, record, _.pick(options, 'mode'));
+                this._handleAttributes($el, node);
+                return $td.append($el);
+            }
+            var name = node.attrs.name;
+            var field = this.state.fields[name];
+            var value = record.data[name];
+            var formattedValue = field_utils.format[field.type](value, field, {
+                data: record.data,
+                escape: true,
+                isPassword: 'password' in node.attrs,
+            });
+            this._handleAttributes($td, node);
+            return $td.html(formattedValue);
         },
 
         /**
@@ -325,8 +350,8 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
                 return;
             }
 
-            var $cell = $('<td>', {class: 'col-total text-right'});
-            this._apply_aggregate_value($cell, this.total);
+            var $cell = $('<td>', {class: 'col-total'});
+            this.applyAggregateValue($cell, this.total);
             return $cell;
         },
 
@@ -338,10 +363,14 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
          */
         _renderAggregateColCells: function () {
             var self = this;
+
             return _.map(this.columns, function (column) {
-                var $cell = $('<td>', {class: 'col-total text-right'});
+                var $cell = $('<td>');
+                if (config.debug) {
+                    $cell.addClass(column.attrs.name);
+                }
                 if (column.aggregate) {
-                    self._apply_aggregate_value($cell, column.aggregate);
+                    self.applyAggregateValue($cell, column)
                 }
                 return $cell;
             });
@@ -367,15 +396,16 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
                 return;
             }
             this.total = {
-                fname: fname,
-                ftype: type,
-                help: _t('Sum Total'),
-                value: 0,
+                attrs: {
+                    name: fname,
+                },
+                aggregate: {
+                    help: _t('Sum Total'),
+                    value: 0,
+                },
             };
             _.each(this.columns, function (column, index) {
                 column.aggregate = {
-                    fname: fname,
-                    ftype: type,
                     help: _t('Sum'),
                     value: 0,
                 };
@@ -451,8 +481,6 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
             }
             _.each(this.rows, function (row) {
                 row.aggregate = {
-                    fname: fname,
-                    ftype: type,
                     help: _t('Sum'),
                     value: 0,
                 };
@@ -475,17 +503,19 @@ odoo.define('web_widget_x2many_2d_matrix.X2Many2dMatrixRenderer', function (requ
          * @param {jQueryElement} $cell
          * The Cell where the aggregate should be added.
          *
-         * @param {Object} aggregate
-         * The object which contains the information about the aggregate value
+         * @param {Object} axis
+         * The object which contains the information about the aggregate value axis
          */
-        _apply_aggregate_value: function ($cell, aggregate) {
-            var field = this.state.fields[aggregate.fname],
-                formatter = field_utils.format[field.type];
-            var formattedValue = formatter(
-                aggregate.value, field, {escape: true}
-            );
-            $cell.addClass('total').attr('title', aggregate.help)
-                .html(formattedValue);
+        applyAggregateValue: function ($cell, axis) {
+            var field = this.state.fields[axis.attrs.name];
+            var value = axis.aggregate.value;
+            var help = axis.aggregate.help;
+            var formatFunc = field_utils.format[axis.attrs.widget];
+            if (!formatFunc) {
+                formatFunc = field_utils.format[field.type];
+            }
+            var formattedValue = formatFunc(value, field, { escape: true });
+            $cell.addClass('o_list_number').attr('title', help).html(formattedValue);
         },
 
         /**
diff --git a/web_widget_x2many_2d_matrix/static/src/js/widget_x2many_2d_matrix.js b/web_widget_x2many_2d_matrix/static/src/js/widget_x2many_2d_matrix.js
index addf7cd4087e..bdaead56a553 100644
--- a/web_widget_x2many_2d_matrix/static/src/js/widget_x2many_2d_matrix.js
+++ b/web_widget_x2many_2d_matrix/static/src/js/widget_x2many_2d_matrix.js
@@ -56,9 +56,6 @@ odoo.define('web_widget_x2many_2d_matrix.widget', function (require) {
                         node[property];
                 }
             }
-            // And this?
-            this.field_editability =
-                node.field_editability || this.field_editability;
             this.show_row_totals =
                 this.parse_boolean(node.show_row_totals || '1');
             this.show_column_totals =
@@ -138,7 +135,14 @@ odoo.define('web_widget_x2many_2d_matrix.widget', function (require) {
         _make_row: function (y) {
             var self = this;
             // Use object so that we can attach more data if needed
-            var row = {'data': []};
+            var row = {
+                'tag': 'field',
+                'attrs': {
+                    'name': this.field_y_axis,
+                    'string': y,
+                },
+                'data': [],
+            };
             $.each(self.by_x_axis, function (x) {
                 row.data.push(self.by_y_axis[y][x]);
             });