diff --git a/web_widget_x2many_2d_matrix/README.rst b/web_widget_x2many_2d_matrix/README.rst index 1372c625..c0693fcf 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 `_) + +12.0.1.0.0 (2018-11-20) +~~~~~~~~~~~~~~~~~~~~~~~ + +* [12.0][MIG] web_widget_x2many_2d_matrix + (`#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 bfee53ec..3299e66b 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 a84da800..d3f10cae 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 00000000..8bad8c46 --- /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 `_) + +12.0.1.0.0 (2018-11-20) +~~~~~~~~~~~~~~~~~~~~~~~ + +* [12.0][MIG] web_widget_x2many_2d_matrix + (`#1101 `_) diff --git a/web_widget_x2many_2d_matrix/static/description/index.html b/web_widget_x2many_2d_matrix/static/description/index.html index bd5775f2..1be53a2a 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 @@ ul.auto-toc {

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:

-Screenshot +Screenshot

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.

Table of contents

-

Usage

+

Usage

Use this widget by saying:

 <field name="my_field" widget="x2many_2d_matrix" />
@@ -457,7 +462,7 @@ row totals. True by default
 column totals. True by default
 
 
-

Example

+

Example

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 project.task as our @@ -509,7 +514,7 @@ the field in the default function:

-

Known issues / Roadmap

+

Known issues / Roadmap

  • Support extra attributes on each field cell via field_extra_attrs param. We could set a cell as not editable, required or readonly for instance. @@ -523,8 +528,25 @@ is merged.
  • Support extra invisible fields inside each cell.
+
+

Changelog

+
+

12.0.1.0.1 (2018-12-07)

+
    +
  • [FIX] Cells are unable to render property. +(#1126)
  • +
+
+
+

12.0.1.0.0 (2018-11-20)

+
    +
  • [12.0][MIG] web_widget_x2many_2d_matrix +(#1101)
  • +
+
+
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. 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 @@ If you spotted it first, help us smashing it by providing a detailed and welcome

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Therp BV
  • Tecnativa
  • Camptocamp
  • +
  • Brainbean Apps
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association

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 ac627e44..30808ae1 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 + * 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 = $('

', {'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 = $('', {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 = $('', {class: 'row-total text-right'}); - this._apply_aggregate_value($cell, row.aggregate); + var $cell = $('', {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 = $('', { '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 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 = $('', {class: 'col-total text-right'}); - this._apply_aggregate_value($cell, this.total); + var $cell = $('', {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 = $('', {class: 'col-total text-right'}); + var $cell = $(''); + 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 addf7cd4..bdaead56 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]); });