forked from Techsystech/web
[FIX] web_widget_x2many_2d_matrix: _renderBodyCell + _renderAggregateColCells
parent
24dc54df5a
commit
343d0560d5
|
@ -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
|
||||
~~~~~~~~~~~~
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>`_)
|
|
@ -397,29 +397,34 @@ ul.auto-toc {
|
|||
<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">
|
||||
<field name="my_field" widget="x2many_2d_matrix" />
|
||||
|
@ -457,7 +462,7 @@ row totals. True by default</dd>
|
|||
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 @@ the field in the default function:</p>
|
|||
</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 @@ is merged.</li>
|
|||
<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 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||
<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 <<a class="reference external" href="mailto:hbrunn@therp.nl">hbrunn@therp.nl</a>></li>
|
||||
<li>Pedro M. Baeza <<a class="reference external" href="mailto:pedro.baeza@tecnativa.com">pedro.baeza@tecnativa.com</a>></li>
|
||||
|
@ -555,7 +578,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
|
|||
</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
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -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]);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue