Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,278 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
===========================
2D matrix for x2many fields
===========================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e422b074c4b533bda09b6422c878ae711365bf51d0a784706df06696acc6a3d3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
:target: https://github.com/OCA/web/tree/18.0/web_widget_x2many_2d_matrix
:alt: OCA/web
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_widget_x2many_2d_matrix
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows to show an x2many field with 3-tuples ($x_value,
$y_value, $value) in a table
========= =========== ===========
\ $x_value1 $x_value2
========= =========== ===========
$y_value1 $value(1/1) $value(2/1)
$y_value2 $value(1/2) $value(2/2)
========= =========== ===========
where value(n/n) is editable.
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|
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.
.. |Screenshot| image:: https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png
**Table of contents**
.. contents::
:local:
Usage
=====
Use this widget by saying:
::
<field name="my_field" widget="x2many_2d_matrix" />
This assumes that my_field refers to a model with the fields x, y and
value. If your fields are named differently, pass the correct names as
attributes:
.. code:: xml
<field name="my_field" widget="x2many_2d_matrix" field_x_axis="my_field1" field_y_axis="my_field2" field_value="my_field3">
<list>
<field name="my_field"/>
<field name="my_field1"/>
<field name="my_field2"/>
<field name="my_field3"/>
</list>
</field>
You can pass the following parameters:
field_x_axis The field that indicates the x value of a point
field_y_axis The field that indicates the y value of a point
field_value Show this field as value
show_row_totals If field_value is a numeric field, it indicates if you
want to calculate row totals. True by default
show_column_totals If field_value is a numeric field, it indicates if
you want to calculate column totals. True by default
x_axis_clickable If the x axis field is a many2one field, render the
values as links to the record in question
y_axis_clickable If the y axis field is a many2one field, render the
values as links to the record in question
For the value field, you can set any attributes you'd set in a normal
list view, ie if your value field is a many2one field and you want to
disable creating records via this field, you'd write
.. code:: xml
<field name="my_field3" options="{'no_create': true}"/>
or if you want to have a custom domain or context
.. code:: xml
<field name="my_field3" domain="[('some_field', '=', my_field1)]" context="{'default_some_field': my_field1}" />
Note that to be able to refer to other fields than the ones used as
coordinates or value, you have to add them inside the ``list`` node.
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 data model and point to it from our wizard. The
crucial part is that we fill the field in the default function:
.. code:: python
from odoo import fields, models
class MyWizard(models.TransientModel):
_name = 'my.wizard'
def _default_task_ids(self):
# your list of project should come from the context, some selection
# in a previous wizard or wherever else
projects = self.env['project.project'].browse([1, 2, 3])
# same with users
users = self.env['res.users'].browse([1, 2, 3])
return [
(0, 0, {
'name': 'Sample task name',
'project_id': p.id,
'user_id': u.id,
'planned_hours': 0,
'message_needaction': False,
'date_deadline': fields.Date.today(),
})
# if the project doesn't have a task for the user,
# create a new one
if not p.task_ids.filtered(lambda x: x.user_id == u) else
# otherwise, return the task
(4, p.task_ids.filtered(lambda x: x.user_id == u)[0].id)
for p in projects
for u in users
]
task_ids = fields.Many2many('project.task', default=_default_task_ids)
Now in our wizard, we can use:
.. code:: xml
<field name="task_ids" widget="x2many_2d_matrix" field_x_axis="project_id" field_y_axis="user_id" field_value="planned_hours">
<list>
<field name="task_ids"/>
<field name="project_id"/>
<field name="user_id"/>
<field name="planned_hours"/>
</list>
</field>
Known issues / Roadmap
======================
- Support limit total records in the matrix. Ref:
https://github.com/OCA/web/issues/901
- Support cell traversal through keyboard arrows.
- Entering the widget from behind by pressing ``Shift+TAB`` in your
keyboard will enter into the 1st cell until
https://github.com/odoo/odoo/pull/26490 is merged.
- Support kanban mode. Current behaviour forces list mode.
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
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_widget_x2many_2d_matrix%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* Hunki Enterprises BV
* Therp BV
* Tecnativa
* Camptocamp
* CorporateHub
* Onestein
Contributors
------------
- Holger Brunn <mail@hunki-enterprises.com>
- Pedro M. Baeza <pedro.baeza@tecnativa.com>
- Artem Kostyuk <a.kostyuk@mobilunity.com>
- Simone Orsi <simone.orsi@camptocamp.com>
- Timon Tschanz <timon.tschanz@camptocamp.com>
- Jairo Llopis <jairo.llopis@tecnativa.com>
- Dennis Sluijk <d.sluijk@onestein.nl>
- `CorporateHub <https://corporatehub.eu/>`__
- Alexey Pelykh <alexey.pelykh@corphub.eu>
- Adrià Gil Sorribes <adria.gil@forgeflow.com>
- Christopher Ormaza <chris.ormaza@forgeflow.com>
- SodexisTeam <dev@sodexis.com>
- Jasmin Solanki jasmin.solanki@forgeflow.com
- David Jiménez david.jimenez@forgeflow.com
Maintainers
-----------
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
.. |maintainer-JasminSForgeFlow| image:: https://github.com/JasminSForgeFlow.png?size=40px
:target: https://github.com/JasminSForgeFlow
:alt: JasminSForgeFlow
.. |maintainer-DavidJForgeFlow| image:: https://github.com/DavidJForgeFlow.png?size=40px
:target: https://github.com/DavidJForgeFlow
:alt: DavidJForgeFlow
.. |maintainer-hbrunn| image:: https://github.com/hbrunn.png?size=40px
:target: https://github.com/hbrunn
:alt: hbrunn
Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-JasminSForgeFlow| |maintainer-DavidJForgeFlow| |maintainer-hbrunn|
This module is part of the `OCA/web <https://github.com/OCA/web/tree/18.0/web_widget_x2many_2d_matrix>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

View File

@@ -0,0 +1,46 @@
# Copyright 2015 Holger Brunn <hbrunn@therp.nl>
# Copyright 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# Copyright 2018 Simone Orsi <simone.orsi@camptocamp.com>
# Copyright 2020 CorporateHub (https://corporatehub.eu)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "2D matrix for x2many fields",
"version": "18.0.2.0.2",
"maintainers": ["JasminSForgeFlow", "DavidJForgeFlow", "hbrunn"],
"development_status": "Production/Stable",
"author": (
"Hunki Enterprises BV, "
"Therp BV, "
"Tecnativa, "
"Camptocamp, "
"CorporateHub, "
"Onestein, "
"Odoo Community Association (OCA)"
),
"website": "https://github.com/OCA/web",
"license": "AGPL-3",
"category": "Hidden/Dependency",
"summary": "Show list fields as a matrix",
"depends": ["web"],
"demo": [
"demo/res_groups_views.xml",
],
"installable": True,
"assets": {
"web.assets_backend": [
"web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/"
"x2many_2d_matrix_renderer.esm.js",
"web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/"
"x2many_2d_matrix_renderer.xml",
"web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/"
"x2many_2d_matrix_field.esm.js",
"web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/"
"x2many_2d_matrix_field.xml",
"web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/"
"x2many_2d_matrix_field.scss",
],
"web.assets_unit_tests": [
"web_widget_x2many_2d_matrix/static/tests/*",
],
},
}

View File

@@ -0,0 +1,129 @@
<odoo>
<record id="view_groups_form" model="ir.ui.view">
<field name="model">res.groups</field>
<field name="inherit_id" ref="base.view_groups_form" />
<field name="arch" type="xml">
<notebook position="inside">
<page string="Matrix widget">
<div
class="o_form_label"
>Many2one field as value and y axis, options and domain set on value field</div>
<field
name="users"
widget="x2many_2d_matrix"
field_x_axis="login"
field_y_axis="partner_id"
field_value="country_id"
>
<list>
<field name="login" />
<field name="partner_id" />
<field
name="country_id"
domain="[('name', 'like', 'land')]"
options="{'no_create': True}"
readonly="login == 'demo'"
required="login == 'admin'"
/>
</list>
</field>
<div
class="o_form_label"
>Char field as value, clickable X axis</div>
<field
name="users"
widget="x2many_2d_matrix"
field_x_axis="country_id"
field_y_axis="partner_id"
field_value="name"
x_axis_clickable="True"
>
<list>
<field name="name" required="login == 'admin'" />
<field name="partner_id" />
<field
name="country_id"
domain="[('name', 'like', 'land')]"
options="{'no_create': True}"
/>
</list>
</field>
<div class="o_form_label">Boolean field as value</div>
<field
name="users"
widget="x2many_2d_matrix"
field_x_axis="country_id"
field_y_axis="partner_id"
field_value="active"
>
<list>
<field name="active" />
<field name="partner_id" />
<field
name="country_id"
domain="[('name', 'like', 'land')]"
options="{'no_create': True}"
/>
</list>
</field>
<div class="o_form_label">Selection field as value</div>
<field
name="users"
widget="x2many_2d_matrix"
field_x_axis="country_id"
field_y_axis="partner_id"
field_value="lang"
>
<list>
<field name="lang" />
<field name="partner_id" />
<field
name="country_id"
domain="[('name', 'like', 'land')]"
options="{'no_create': True}"
/>
</list>
</field>
<div class="o_form_label">Float field as value</div>
<field
name="users"
widget="x2many_2d_matrix"
field_x_axis="country_id"
field_y_axis="partner_id"
field_value="partner_latitude"
>
<list>
<field name="partner_latitude" />
<field name="partner_id" />
<field
name="country_id"
domain="[('name', 'like', 'land')]"
options="{'no_create': True}"
/>
</list>
</field>
<div
class="o_form_label"
>Float field as value with float_time widget</div>
<field
name="users"
widget="x2many_2d_matrix"
field_x_axis="country_id"
field_y_axis="partner_id"
field_value="partner_latitude"
>
<list>
<field name="partner_latitude" widget="float_time" />
<field name="partner_id" />
<field
name="country_id"
domain="[('name', 'like', 'land')]"
options="{'no_create': True}"
/>
</list>
</field>
</page>
</notebook>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,67 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# SaFi J. <safi2266@gmail.com>, 2015
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-12-16 07:41+0000\n"
"PO-Revision-Date: 2015-12-16 17:24+0000\n"
"Last-Translator: SaFi J. <safi2266@gmail.com>\n"
"Language-Team: Arabic (http://www.transifex.com/oca/OCA-web-8-0/language/"
"ar/)\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, fuzzy, python-format
#~ msgid "Sum Total"
#~ msgstr "المجموع الاجمالي"

View File

@@ -0,0 +1,75 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# Rudolf Schnapka <rs@techno-flex.de>, 2016
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-10 07:31+0000\n"
"PO-Revision-Date: 2023-06-20 11:09+0000\n"
"Last-Translator: Nils Coenen <nils.coenen@nico-solutions.de>\n"
"Language-Team: German (http://www.transifex.com/oca/OCA-web-8-0/language/"
"de/)\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr "Nichts zu zeigen."
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "Leider keine Matrixdaten zur Anzeige."
#, python-format
#~ msgid "Sum"
#~ msgstr "Summe"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Gesamtsumme"

View File

@@ -0,0 +1,66 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-11-23 13:46+0000\n"
"PO-Revision-Date: 2023-09-02 20:35+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: Spanish (http://www.transifex.com/oca/OCA-web-8-0/language/"
"es/)\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr "Nada que mostrar."
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, fuzzy, python-format
#~ msgid "Sum Total"
#~ msgstr "Total"

View File

@@ -0,0 +1,66 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2016
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-10 07:31+0000\n"
"PO-Revision-Date: 2016-02-01 09:54+0000\n"
"Last-Translator: Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>\n"
"Language-Team: Finnish (http://www.transifex.com/oca/OCA-web-8-0/language/"
"fi/)\n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, fuzzy, python-format
#~ msgid "Sum Total"
#~ msgstr "Yhteensä"

View File

@@ -0,0 +1,74 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-06 15:50+0000\n"
"PO-Revision-Date: 2019-08-06 12:44+0000\n"
"Last-Translator: Nicolas JEUDY <njeudy@panda-chi.io>\n"
"Language-Team: French (http://www.transifex.com/oca/OCA-web-8-0/language/"
"fr/)\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 3.7.1\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "Désolé il n'y a pas de donnée matrice à afficher."
#, python-format
#~ msgid "Sum"
#~ msgstr "Somme"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Total"

View File

@@ -0,0 +1,76 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# Ana-Maria Olujić <ana-maria.olujic@slobodni-programi.hr>, 2016
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-08-25 00:51+0000\n"
"PO-Revision-Date: 2019-11-14 10:34+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>\n"
"Language-Team: Croatian (http://www.transifex.com/oca/OCA-web-8-0/language/"
"hr/)\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 3.8\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "Oprostite, nema matrice podataka za prikaz."
#, python-format
#~ msgid "Sum"
#~ msgstr "Suma"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Ukupno"

View File

@@ -0,0 +1,78 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-03-17 07:30+0000\n"
"PO-Revision-Date: 2025-08-19 15:27+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: Italian (http://www.transifex.com/oca/OCA-web-8-0/language/it/"
")\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.10.4\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr "Campo booleano come valore"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr "Campo carattere come valore, asse X cliccabile"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr "Campo a virgola mobile come valore"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr "Valore in virgola mobile con widget float_time"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
"Campo many2one come valore e asse y, opzioni e set dominio nel campo valore"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr "Wisget matrix"
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr "Niente da visualizzare."
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr "Campo selezione come valore"
#~ msgid "Char field as value"
#~ msgstr "Campo carattere come valore"
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "Spiacenti, nessun dato da visualizzare."
#, python-format
#~ msgid "Sum"
#~ msgstr "Somma"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Totale"

View File

@@ -0,0 +1,66 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# Viktoras Norkus <viktoras@bmx.lt>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-25 01:58+0000\n"
"PO-Revision-Date: 2018-02-15 12:40+0200\n"
"Last-Translator: Viktoras Norkus <viktoras@bmx.lt>, 2018\n"
"Language-Team: Lithuanian (https://www.transifex.com/oca/teams/23907/lt/)\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"(n%100<10 || n%100>=20) ? 1 : 2);\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, fuzzy, python-format
#~ msgid "Sum Total"
#~ msgstr "Suma"

View File

@@ -0,0 +1,71 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2021-04-22 15:47+0000\n"
"Last-Translator: Bosd <c5e2fd43-d292-4c90-9d1f-74ff3436329a@anonaddy.me>\n"
"Language-Team: none\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "Sorry er is geen matrix data om weertegeven."
#, python-format
#~ msgid "Sum"
#~ msgstr "Som"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Totaal"

View File

@@ -0,0 +1,67 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# Peter Hageman <hageman.p@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 11.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-03 03:50+0000\n"
"PO-Revision-Date: 2021-04-22 15:47+0000\n"
"Last-Translator: Bosd <c5e2fd43-d292-4c90-9d1f-74ff3436329a@anonaddy.me>\n"
"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/"
"teams/23907/nl_NL/)\n"
"Language: nl_NL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Totaal"

View File

@@ -0,0 +1,74 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-03-11 02:18+0000\n"
"PO-Revision-Date: 2019-09-03 01:23+0000\n"
"Last-Translator: Rodrigo Macedo <rmsolucoeseminformatic4@gmail.com>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/oca/OCA-web-8-0/"
"language/pt_BR/)\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 3.8\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "Desculpe não há dados de matriz para exibir."
#, python-format
#~ msgid "Sum"
#~ msgstr "Soma"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "Soma Total"

View File

@@ -0,0 +1,66 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-11-23 13:46+0000\n"
"PO-Revision-Date: 2015-11-08 05:48+0000\n"
"Last-Translator: Matjaž Mozetič <m.mozetic@matmoz.si>\n"
"Language-Team: Slovenian (http://www.transifex.com/oca/OCA-web-8-0/language/"
"sl/)\n"
"Language: sl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
"n%100==4 ? 2 : 3);\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, fuzzy, python-format
#~ msgid "Sum Total"
#~ msgstr "Skupaj"

View File

@@ -0,0 +1,66 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
# Translators:
# Ahmet Altınışık <aaltinisik@altinkaya.com.tr>, 2015
msgid ""
msgstr ""
"Project-Id-Version: web (8.0)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-01-08 21:34+0000\n"
"PO-Revision-Date: 2015-12-30 22:00+0000\n"
"Last-Translator: Ahmet Altınışık <aaltinisik@altinkaya.com.tr>\n"
"Language-Team: Turkish (http://www.transifex.com/oca/OCA-web-8-0/language/"
"tr/)\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, fuzzy, python-format
#~ msgid "Sum Total"
#~ msgstr "Toplam"

View File

@@ -0,0 +1,56 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""

View File

@@ -0,0 +1,71 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_widget_x2many_2d_matrix
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2019-09-01 17:23+0000\n"
"Last-Translator: 黎伟杰 <674416404@qq.com>\n"
"Language-Team: none\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Weblate 3.8\n"
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Boolean field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Char field as value, clickable X axis"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Float field as value with float_time widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid ""
"Many2one field as value and y axis, options and domain set on value field"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Matrix widget"
msgstr ""
#. module: web_widget_x2many_2d_matrix
#. odoo-javascript
#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0
msgid "Nothing to display."
msgstr ""
#. module: web_widget_x2many_2d_matrix
#: model_terms:ir.ui.view,arch_db:web_widget_x2many_2d_matrix.view_groups_form
msgid "Selection field as value"
msgstr ""
#, python-format
#~ msgid "Sorry no matrix data to display."
#~ msgstr "抱歉没有要显示的矩阵数据。"
#, python-format
#~ msgid "Sum"
#~ msgstr "总和"
#, python-format
#~ msgid "Sum Total"
#~ msgstr "总和"

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,14 @@
- Holger Brunn \<<mail@hunki-enterprises.com>\>
- Pedro M. Baeza \<<pedro.baeza@tecnativa.com>\>
- Artem Kostyuk \<<a.kostyuk@mobilunity.com>\>
- Simone Orsi \<<simone.orsi@camptocamp.com>\>
- Timon Tschanz \<<timon.tschanz@camptocamp.com>\>
- Jairo Llopis \<<jairo.llopis@tecnativa.com>\>
- Dennis Sluijk \<<d.sluijk@onestein.nl>\>
- [CorporateHub](https://corporatehub.eu/)
- Alexey Pelykh \<<alexey.pelykh@corphub.eu>\>
- Adrià Gil Sorribes \<<adria.gil@forgeflow.com>\>
- Christopher Ormaza \<<chris.ormaza@forgeflow.com>\>
- SodexisTeam \<<dev@sodexis.com>\>
- Jasmin Solanki <jasmin.solanki@forgeflow.com>
- David Jiménez <david.jimenez@forgeflow.com>

View File

@@ -0,0 +1,19 @@
This module allows to show an x2many field with 3-tuples (\$x_value,
\$y_value, \$value) in a table
| | \$x_value1 | \$x_value2 |
|------------|--------------|--------------|
| \$y_value1 | \$value(1/1) | \$value(2/1) |
| \$y_value2 | \$value(1/2) | \$value(2/2) |
where value(n/n) is editable.
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](https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png)
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.

View File

@@ -0,0 +1,9 @@
## 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))

View File

@@ -0,0 +1,7 @@
- Support limit total records in the matrix. Ref:
<https://github.com/OCA/web/issues/901>
- Support cell traversal through keyboard arrows.
- Entering the widget from behind by pressing `Shift+TAB` in your
keyboard will enter into the 1st cell until
<https://github.com/odoo/odoo/pull/26490> is merged.
- Support kanban mode. Current behaviour forces list mode.

View File

@@ -0,0 +1,112 @@
Use this widget by saying:
<field name="my_field" widget="x2many_2d_matrix" />
This assumes that my_field refers to a model with the fields x, y and
value. If your fields are named differently, pass the correct names as
attributes:
``` xml
<field name="my_field" widget="x2many_2d_matrix" field_x_axis="my_field1" field_y_axis="my_field2" field_value="my_field3">
<list>
<field name="my_field"/>
<field name="my_field1"/>
<field name="my_field2"/>
<field name="my_field3"/>
</list>
</field>
```
You can pass the following parameters:
field_x_axis
The field that indicates the x value of a point
field_y_axis
The field that indicates the y value of a point
field_value
Show this field as value
show_row_totals
If field_value is a numeric field, it indicates if you want to calculate
row totals. True by default
show_column_totals
If field_value is a numeric field, it indicates if you want to calculate
column totals. True by default
x_axis_clickable
If the x axis field is a many2one field, render the values as links to the record in question
y_axis_clickable
If the y axis field is a many2one field, render the values as links to the record in question
For the value field, you can set any attributes you'd set in a normal list view, ie if your value field is a many2one field and you want to disable creating records via this field, you'd write
```xml
<field name="my_field3" options="{'no_create': true}"/>
```
or if you want to have a custom domain or context
```xml
<field name="my_field3" domain="[('some_field', '=', my_field1)]" context="{'default_some_field': my_field1}" />
```
Note that to be able to refer to other fields than the ones used as coordinates or value, you have to add them inside the ``list`` node.
## 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 data model and point to it from our wizard. The
crucial part is that we fill the field in the default function:
``` python
from odoo import fields, models
class MyWizard(models.TransientModel):
_name = 'my.wizard'
def _default_task_ids(self):
# your list of project should come from the context, some selection
# in a previous wizard or wherever else
projects = self.env['project.project'].browse([1, 2, 3])
# same with users
users = self.env['res.users'].browse([1, 2, 3])
return [
(0, 0, {
'name': 'Sample task name',
'project_id': p.id,
'user_id': u.id,
'planned_hours': 0,
'message_needaction': False,
'date_deadline': fields.Date.today(),
})
# if the project doesn't have a task for the user,
# create a new one
if not p.task_ids.filtered(lambda x: x.user_id == u) else
# otherwise, return the task
(4, p.task_ids.filtered(lambda x: x.user_id == u)[0].id)
for p in projects
for u in users
]
task_ids = fields.Many2many('project.task', default=_default_task_ids)
```
Now in our wizard, we can use:
``` xml
<field name="task_ids" widget="x2many_2d_matrix" field_x_axis="project_id" field_y_axis="user_id" field_value="planned_hours">
<list>
<field name="task_ids"/>
<field name="project_id"/>
<field name="user_id"/>
<field name="planned_hours"/>
</list>
</field>
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,617 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="d-matrix-for-x2many-fields">
<h1>2D matrix for x2many fields</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:e422b074c4b533bda09b6422c878ae711365bf51d0a784706df06696acc6a3d3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/web/tree/18.0/web_widget_x2many_2d_matrix"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_widget_x2many_2d_matrix"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows to show an x2many field with 3-tuples ($x_value,
$y_value, $value) in a table</p>
<table border="1" class="docutils">
<colgroup>
<col width="29%" />
<col width="35%" />
<col width="35%" />
</colgroup>
<thead valign="bottom">
<tr><th class="head"></th>
<th class="head">$x_value1</th>
<th class="head">$x_value2</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>$y_value1</td>
<td>$value(1/1)</td>
<td>$value(2/1)</td>
</tr>
<tr><td>$y_value2</td>
<td>$value(1/2)</td>
<td>$value(2/2)</td>
</tr>
</tbody>
</table>
<p>where value(n/n) is editable.</p>
<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>
<p><img alt="Screenshot" src="https://raw.githubusercontent.com/OCA/web/12.0/web_widget_x2many_2d_matrix/static/description/screenshot.png" /></p>
<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="toc-entry-1">Usage</a><ul>
<li><a class="reference internal" href="#example" id="toc-entry-2">Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-3">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#changelog" id="toc-entry-4">Changelog</a><ul>
<li><a class="reference internal" href="#section-1" id="toc-entry-5">12.0.1.0.1 (2018-12-07)</a></li>
<li><a class="reference internal" href="#section-2" id="toc-entry-6">12.0.1.0.0 (2018-11-20)</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-7">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-8">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-9">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-10">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-11">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
<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;
</pre>
<p>This assumes that my_field refers to a model with the fields x, y and
value. If your fields are named differently, pass the correct names as
attributes:</p>
<pre class="code xml literal-block">
<span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field&quot;</span><span class="w"> </span><span class="na">widget=</span><span class="s">&quot;x2many_2d_matrix&quot;</span><span class="w"> </span><span class="na">field_x_axis=</span><span class="s">&quot;my_field1&quot;</span><span class="w"> </span><span class="na">field_y_axis=</span><span class="s">&quot;my_field2&quot;</span><span class="w"> </span><span class="na">field_value=</span><span class="s">&quot;my_field3&quot;</span><span class="nt">&gt;</span><span class="w">
</span><span class="nt">&lt;list&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field1&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field2&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field3&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;/list&gt;</span><span class="w">
</span><span class="nt">&lt;/field&gt;</span>
</pre>
<p>You can pass the following parameters:</p>
<p>field_x_axis The field that indicates the x value of a point</p>
<p>field_y_axis The field that indicates the y value of a point</p>
<p>field_value Show this field as value</p>
<p>show_row_totals If field_value is a numeric field, it indicates if you
want to calculate row totals. True by default</p>
<p>show_column_totals If field_value is a numeric field, it indicates if
you want to calculate column totals. True by default</p>
<p>x_axis_clickable If the x axis field is a many2one field, render the
values as links to the record in question</p>
<p>y_axis_clickable If the y axis field is a many2one field, render the
values as links to the record in question</p>
<p>For the value field, you can set any attributes youd set in a normal
list view, ie if your value field is a many2one field and you want to
disable creating records via this field, youd write</p>
<pre class="code xml literal-block">
<span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field3&quot;</span><span class="w"> </span><span class="na">options=</span><span class="s">&quot;{'no_create': true}&quot;</span><span class="nt">/&gt;</span>
</pre>
<p>or if you want to have a custom domain or context</p>
<pre class="code xml literal-block">
<span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;my_field3&quot;</span><span class="w"> </span><span class="na">domain=</span><span class="s">&quot;[('some_field', '=', my_field1)]&quot;</span><span class="w"> </span><span class="na">context=</span><span class="s">&quot;{'default_some_field': my_field1}&quot;</span><span class="w"> </span><span class="nt">/&gt;</span>
</pre>
<p>Note that to be able to refer to other fields than the ones used as
coordinates or value, you have to add them inside the <tt class="docutils literal">list</tt> node.</p>
<div class="section" id="example">
<h3><a class="toc-backref" href="#toc-entry-2">Example</a></h3>
<p>You need a data structure already filled with values. Lets 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 data model and point to it from our wizard. The
crucial part is that we fill the field in the default function:</p>
<pre class="code python literal-block">
<span class="kn">from</span><span class="w"> </span><span class="nn">odoo</span><span class="w"> </span><span class="kn">import</span> <span class="n">fields</span><span class="p">,</span> <span class="n">models</span><span class="w">
</span><span class="k">class</span><span class="w"> </span><span class="nc">MyWizard</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">TransientModel</span><span class="p">):</span><span class="w">
</span> <span class="n">_name</span> <span class="o">=</span> <span class="s1">'my.wizard'</span><span class="w">
</span> <span class="k">def</span><span class="w"> </span><span class="nf">_default_task_ids</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span><span class="w">
</span> <span class="c1"># your list of project should come from the context, some selection</span><span class="w">
</span> <span class="c1"># in a previous wizard or wherever else</span><span class="w">
</span> <span class="n">projects</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="p">[</span><span class="s1">'project.project'</span><span class="p">]</span><span class="o">.</span><span class="n">browse</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span><span class="w">
</span> <span class="c1"># same with users</span><span class="w">
</span> <span class="n">users</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="p">[</span><span class="s1">'res.users'</span><span class="p">]</span><span class="o">.</span><span class="n">browse</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span><span class="w">
</span> <span class="k">return</span> <span class="p">[</span><span class="w">
</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">{</span><span class="w">
</span> <span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Sample task name'</span><span class="p">,</span><span class="w">
</span> <span class="s1">'project_id'</span><span class="p">:</span> <span class="n">p</span><span class="o">.</span><span class="n">id</span><span class="p">,</span><span class="w">
</span> <span class="s1">'user_id'</span><span class="p">:</span> <span class="n">u</span><span class="o">.</span><span class="n">id</span><span class="p">,</span><span class="w">
</span> <span class="s1">'planned_hours'</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span><span class="w">
</span> <span class="s1">'message_needaction'</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span><span class="w">
</span> <span class="s1">'date_deadline'</span><span class="p">:</span> <span class="n">fields</span><span class="o">.</span><span class="n">Date</span><span class="o">.</span><span class="n">today</span><span class="p">(),</span><span class="w">
</span> <span class="p">})</span><span class="w">
</span> <span class="c1"># if the project doesn't have a task for the user,</span><span class="w">
</span> <span class="c1"># create a new one</span><span class="w">
</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="o">.</span><span class="n">task_ids</span><span class="o">.</span><span class="n">filtered</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">user_id</span> <span class="o">==</span> <span class="n">u</span><span class="p">)</span> <span class="k">else</span><span class="w">
</span> <span class="c1"># otherwise, return the task</span><span class="w">
</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">task_ids</span><span class="o">.</span><span class="n">filtered</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">user_id</span> <span class="o">==</span> <span class="n">u</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">id</span><span class="p">)</span><span class="w">
</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">projects</span><span class="w">
</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">users</span><span class="w">
</span> <span class="p">]</span><span class="w">
</span> <span class="n">task_ids</span> <span class="o">=</span> <span class="n">fields</span><span class="o">.</span><span class="n">Many2many</span><span class="p">(</span><span class="s1">'project.task'</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">_default_task_ids</span><span class="p">)</span>
</pre>
<p>Now in our wizard, we can use:</p>
<pre class="code xml literal-block">
<span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;task_ids&quot;</span><span class="w"> </span><span class="na">widget=</span><span class="s">&quot;x2many_2d_matrix&quot;</span><span class="w"> </span><span class="na">field_x_axis=</span><span class="s">&quot;project_id&quot;</span><span class="w"> </span><span class="na">field_y_axis=</span><span class="s">&quot;user_id&quot;</span><span class="w"> </span><span class="na">field_value=</span><span class="s">&quot;planned_hours&quot;</span><span class="nt">&gt;</span><span class="w">
</span><span class="nt">&lt;list&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;task_ids&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;project_id&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;user_id&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;planned_hours&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;/list&gt;</span><span class="w">
</span><span class="nt">&lt;/field&gt;</span>
</pre>
</div>
</div>
<div class="section" id="known-issues-roadmap">
<h2><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h2>
<ul class="simple">
<li>Support limit total records in the matrix. Ref:
<a class="reference external" href="https://github.com/OCA/web/issues/901">https://github.com/OCA/web/issues/901</a></li>
<li>Support cell traversal through keyboard arrows.</li>
<li>Entering the widget from behind by pressing <tt class="docutils literal">Shift+TAB</tt> in your
keyboard will enter into the 1st cell until
<a class="reference external" href="https://github.com/odoo/odoo/pull/26490">https://github.com/odoo/odoo/pull/26490</a> is merged.</li>
<li>Support kanban mode. Current behaviour forces list mode.</li>
</ul>
</div>
<div class="section" id="changelog">
<h2><a class="toc-backref" href="#toc-entry-4">Changelog</a></h2>
<div class="section" id="section-1">
<h3><a class="toc-backref" href="#toc-entry-5">12.0.1.0.1 (2018-12-07)</a></h3>
<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="section-2">
<h3><a class="toc-backref" href="#toc-entry-6">12.0.1.0.0 (2018-11-20)</a></h3>
<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">
<h2><a class="toc-backref" href="#toc-entry-7">Bug Tracker</a></h2>
<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 to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_widget_x2many_2d_matrix%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-8">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-9">Authors</a></h3>
<ul class="simple">
<li>Hunki Enterprises BV</li>
<li>Therp BV</li>
<li>Tecnativa</li>
<li>Camptocamp</li>
<li>CorporateHub</li>
<li>Onestein</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-10">Contributors</a></h3>
<ul class="simple">
<li>Holger Brunn &lt;<a class="reference external" href="mailto:mail&#64;hunki-enterprises.com">mail&#64;hunki-enterprises.com</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>
<li>Artem Kostyuk &lt;<a class="reference external" href="mailto:a.kostyuk&#64;mobilunity.com">a.kostyuk&#64;mobilunity.com</a>&gt;</li>
<li>Simone Orsi &lt;<a class="reference external" href="mailto:simone.orsi&#64;camptocamp.com">simone.orsi&#64;camptocamp.com</a>&gt;</li>
<li>Timon Tschanz &lt;<a class="reference external" href="mailto:timon.tschanz&#64;camptocamp.com">timon.tschanz&#64;camptocamp.com</a>&gt;</li>
<li>Jairo Llopis &lt;<a class="reference external" href="mailto:jairo.llopis&#64;tecnativa.com">jairo.llopis&#64;tecnativa.com</a>&gt;</li>
<li>Dennis Sluijk &lt;<a class="reference external" href="mailto:d.sluijk&#64;onestein.nl">d.sluijk&#64;onestein.nl</a>&gt;</li>
<li><a class="reference external" href="https://corporatehub.eu/">CorporateHub</a><ul>
<li>Alexey Pelykh &lt;<a class="reference external" href="mailto:alexey.pelykh&#64;corphub.eu">alexey.pelykh&#64;corphub.eu</a>&gt;</li>
</ul>
</li>
<li>Adrià Gil Sorribes &lt;<a class="reference external" href="mailto:adria.gil&#64;forgeflow.com">adria.gil&#64;forgeflow.com</a>&gt;</li>
<li>Christopher Ormaza &lt;<a class="reference external" href="mailto:chris.ormaza&#64;forgeflow.com">chris.ormaza&#64;forgeflow.com</a>&gt;</li>
<li>SodexisTeam &lt;<a class="reference external" href="mailto:dev&#64;sodexis.com">dev&#64;sodexis.com</a>&gt;</li>
<li>Jasmin Solanki <a class="reference external" href="mailto:jasmin.solanki&#64;forgeflow.com">jasmin.solanki&#64;forgeflow.com</a></li>
<li>David Jiménez <a class="reference external" href="mailto:david.jimenez&#64;forgeflow.com">david.jimenez&#64;forgeflow.com</a></li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-11">Maintainers</a></h3>
<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
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/JasminSForgeFlow"><img alt="JasminSForgeFlow" src="https://github.com/JasminSForgeFlow.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/DavidJForgeFlow"><img alt="DavidJForgeFlow" src="https://github.com/DavidJForgeFlow.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/hbrunn"><img alt="hbrunn" src="https://github.com/hbrunn.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/18.0/web_widget_x2many_2d_matrix">OCA/web</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -0,0 +1,64 @@
import {Component} from "@odoo/owl";
import {X2Many2DMatrixRenderer} from "@web_widget_x2many_2d_matrix/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm";
import {exprToBoolean} from "@web/core/utils/strings";
import {registry} from "@web/core/registry";
import {standardFieldProps} from "@web/views/fields/standard_field_props";
export class X2Many2DMatrixField extends Component {
setup() {
this.activeField = this.props.record.activeFields[this.props.name];
}
getList() {
return this.props.record.data[this.props.name];
}
get list() {
return this.getList();
}
getListView() {
return this.props.list_view;
}
get list_view() {
return this.getListView();
}
}
X2Many2DMatrixField.template = "web_widget_x2many_2d_matrix.X2Many2DMatrixField";
X2Many2DMatrixField.props = {
...standardFieldProps,
list_view: {type: Object, optional: false},
matrixFields: {type: Object, optional: false},
isXClickable: {type: Boolean, optional: true},
isYClickable: {type: Boolean, optional: true},
showRowTotals: {type: Boolean, optional: true},
showColumnTotals: {type: Boolean, optional: true},
};
X2Many2DMatrixField.components = {X2Many2DMatrixRenderer};
export const x2Many2DMatrixField = {
component: X2Many2DMatrixField,
extractProps({attrs, views}) {
return {
list_view: views.list,
matrixFields: {
value: attrs.field_value,
x: attrs.field_x_axis,
y: attrs.field_y_axis,
},
isXClickable: exprToBoolean(attrs.x_axis_clickable),
isYClickable: exprToBoolean(attrs.y_axis_clickable),
showRowTotals:
"show_row_totals" in attrs
? exprToBoolean(attrs.show_row_totals)
: true,
showColumnTotals:
"show_column_totals" in attrs
? exprToBoolean(attrs.show_column_totals)
: true,
};
},
};
registry.category("fields").add("x2many_2d_matrix", x2Many2DMatrixField);

View File

@@ -0,0 +1,71 @@
$x2many_2d_matrix_max_height: 450px;
.o_form_view .o_field_x2many_2d_matrix {
.table-responsive {
max-height: $x2many_2d_matrix_max_height;
overflow-y: auto;
}
.o_input {
padding: 1px 0px;
}
.table {
> thead > tr > th {
white-space: pre-line;
position: sticky;
top: 0;
z-index: 1;
&.total {
right: 0;
}
}
> tbody {
> tr {
&:nth-of-type(2n + 1) td.row-total,
&:nth-of-type(2n) td.row-total,
> td {
text-align: right;
.o_field_many2one_selection {
text-align: left;
}
&:first-child {
position: sticky;
left: 0;
text-align: left;
border-right-width: 1px;
border-right-color: $gray-300;
border-right-style: solid;
}
&.row-total {
padding: 0.5rem 0.75rem;
font-weight: bold;
position: sticky;
right: 0;
border-left-width: 1px;
border-left-color: $gray-300;
border-left-style: solid;
}
}
}
}
> tfoot > tr > th {
text-align: right;
position: sticky;
bottom: 0;
&.col-total {
padding: 0.75rem;
right: 0;
border-left-width: 1px;
border-left-color: $gray-300;
border-left-style: solid;
}
}
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="web_widget_x2many_2d_matrix.X2Many2DMatrixField">
<div class="table-responsive">
<X2Many2DMatrixRenderer
list="list"
list_view="list_view"
matrixFields="props.matrixFields"
showRowTotals="props.showRowTotals"
showColumnTotals="props.showColumnTotals"
readonly="props.readonly"
isXClickable="props.isXClickable"
isYClickable="props.isYClickable"
/>
</div>
</t>
</templates>

View File

@@ -0,0 +1,221 @@
import {Component, onWillUpdateProps} from "@odoo/owl";
import {evaluateBooleanExpr, evaluateExpr} from "@web/core/py_js/py";
import {Domain} from "@web/core/domain";
import {Record} from "@web/model/relational_model/record";
import {getFieldContext} from "@web/model/relational_model/utils";
export class X2Many2DMatrixRenderer extends Component {
setup() {
this.columns = this._getColumns();
this.rows = this._getRows();
this.matrix = this._getMatrix();
onWillUpdateProps((newProps) => {
this.columns = this._getColumns(newProps.list.records);
this.rows = this._getRows(newProps.list.records);
this.matrix = this._getMatrix(newProps.list.records);
});
}
_getColumns(records = this.list.records) {
const columns = [];
records.forEach((record) => {
const column = {
value: record.data[this.matrixFields.x],
text: record.data[this.matrixFields.x],
rawValue: record.data[this.matrixFields.x],
};
if (record.fields[this.matrixFields.x].type === "many2one") {
column.text = column.value[1];
column.value = column.value[0];
}
if (columns.findIndex((c) => c.value === column.value) !== -1) return;
columns.push(column);
});
return columns;
}
_getRows(records = this.list.records) {
const rows = [];
records.forEach((record) => {
const row = {
value: record.data[this.matrixFields.y],
text: record.data[this.matrixFields.y],
rawValue: record.data[this.matrixFields.y],
};
if (record.fields[this.matrixFields.y].type === "many2one") {
row.text = row.value[1];
row.value = row.value[0];
}
if (rows.findIndex((r) => r.value === row.value) !== -1) return;
rows.push(row);
});
return rows;
}
_getPointOfRecord(record) {
let xValue = record.data[this.matrixFields.x];
if (record.fields[this.matrixFields.x].type === "many2one") {
xValue = xValue[0];
}
let yValue = record.data[this.matrixFields.y];
if (record.fields[this.matrixFields.y].type === "many2one") {
yValue = yValue[0];
}
const x = this.columns.findIndex((c) => c.value === xValue);
const y = this.rows.findIndex((r) => r.value === yValue);
return {x, y};
}
_getMatrix(records = this.list.records) {
const matrix = this.rows.map(() =>
new Array(this.columns.length).fill(null).map(() => {
return {value: 0, records: []};
})
);
records.forEach((record) => {
const value = record.data[this.matrixFields.value];
const {x, y} = this._getPointOfRecord(record);
matrix[y][x].value += value;
matrix[y][x].records.push(record);
});
return matrix;
}
get list() {
return this.props.list;
}
get matrixFields() {
return this.props.matrixFields;
}
get valueFieldComponent() {
return this.props.list_view.fieldNodes[this.matrixFields.value + "_0"].field
.component;
}
get xFieldComponent() {
return this.props.list_view.fieldNodes[this.matrixFields.x + "_0"].field
.component;
}
get yFieldComponent() {
return this.props.list_view.fieldNodes[this.matrixFields.y + "_0"].field
.component;
}
_aggregateRow(row) {
const y = this.rows.findIndex((r) => r.value === row);
const total = this.matrix[y].map((r) => r.value).reduce((aggr, x) => aggr + x);
return total;
}
_aggregateColumn(column) {
const x = this.columns.findIndex((c) => c.value === column);
const total = this.matrix
.map((r) => r[x])
.map((r) => r.value)
.reduce((aggr, y) => aggr + y);
return total;
}
_aggregateAll() {
const total = this.matrix
.map((r) => r.map((x) => x.value).reduce((aggr, x) => aggr + x))
.reduce((aggr, y) => aggr + y);
return total;
}
_canAggregate() {
return ["integer", "float", "monetary"].includes(
this.list.fields[this.matrixFields.value].type
);
}
_getValueFieldProps(column, row) {
const x = this.columns.findIndex((c) => c.value === column);
const y = this.rows.findIndex((r) => r.value === row);
const record = this.matrix[y][x].records[0];
if (!record) {
return null;
}
return this._getMatrixFieldProps(record, "value");
}
_getAxisFieldProps(value, axis) {
const fieldName = this.matrixFields[axis];
const record = new Record(this.list.model, this.list._config, {
[fieldName]: value,
});
const props = this._getMatrixFieldProps(record, axis);
if (this.list.fields[fieldName].type === "many2one") {
props.canOpen =
axis === "x" ? this.props.isXClickable : this.props.isYClickable;
}
props.readonly = true;
return props;
}
_getAggregateProps(value) {
const record = new Record(this.list.model, this.list._config, {
[this.matrixFields.value]: value,
});
const props = this._getMatrixFieldProps(record, "value");
props.readonly = true;
return props;
}
_getMatrixFieldProps(record, fieldName) {
const fieldInfo =
this.props.list_view.fieldNodes[this.matrixFields[fieldName] + "_0"];
const dynamicInfo = {
get context() {
return getFieldContext(record, fieldInfo.name, fieldInfo.context);
},
domain() {
const evalContext = record.evalContext;
if (fieldInfo.domain) {
return new Domain(
evaluateExpr(fieldInfo.domain, evalContext)
).toList();
}
},
required: evaluateBooleanExpr(
fieldInfo.required,
record.evalContextWithVirtualIds
),
readonly:
this.props.readonly ||
evaluateBooleanExpr(
fieldInfo.readonly,
record.evalContextWithVirtualIds
),
};
const result = {
readonly: dynamicInfo.readonly,
record: record,
name: this.matrixFields[fieldName],
...(fieldInfo.field.extractProps || (() => ({}))).apply(fieldInfo.field, [
fieldInfo,
dynamicInfo,
]),
};
return result;
}
}
X2Many2DMatrixRenderer.template = "web_widget_x2many_2d_matrix.X2Many2DMatrixRenderer";
X2Many2DMatrixRenderer.props = {
list: {type: Object, optional: false},
list_view: {type: Object, optional: false},
matrixFields: {type: Object, optional: false},
readonly: {type: Boolean, optional: true},
domain: {type: [Array, Function], optional: true},
showRowTotals: {type: Boolean, optional: true},
showColumnTotals: {type: Boolean, optional: true},
isXClickable: {type: Boolean, optional: true},
isYClickable: {type: Boolean, optional: true},
};

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="web_widget_x2many_2d_matrix.X2Many2DMatrixRenderer">
<table
class="o_list_table table table-responsive table-sm table-hover position-relative mb-0 o_list_table_ungrouped table-striped"
t-if="rows.length > 0"
>
<thead>
<tr>
<th />
<th
t-foreach="columns"
t-as="column"
t-key="column.value"
class="text-center"
>
<t
t-component="xFieldComponent"
t-props="_getAxisFieldProps(column.rawValue, 'x')"
/>
</th>
<th t-if="props.showRowTotals" />
</tr>
</thead>
<tbody>
<tr t-foreach="rows" t-as="row" t-key="row.value">
<td>
<t
t-component="yFieldComponent"
t-props="_getAxisFieldProps(row.rawValue, 'y')"
/>
</td>
<td t-foreach="columns" t-as="column" t-key="column.value">
<t
t-set="value_field_props"
t-value="_getValueFieldProps(column.value, row.value)"
/>
<t
t-if="value_field_props"
t-component="valueFieldComponent"
t-props="value_field_props"
/>
</td>
<td
t-if="props.showRowTotals and _canAggregate()"
class="row-total"
>
<t
t-component="valueFieldComponent"
t-props="_getAggregateProps(_aggregateRow(row.value))"
/>
</td>
</tr>
</tbody>
<tfoot>
<tr t-if="props.showColumnTotals and _canAggregate()">
<th />
<th t-foreach="columns" t-as="column" t-key="column.value">
<t
t-component="valueFieldComponent"
t-props="_getAggregateProps(_aggregateColumn(column.value))"
/>
</th>
<th t-if="props.showRowTotals" class="col-total">
<t
t-component="valueFieldComponent"
t-props="_getAggregateProps(_aggregateAll())"
/>
</th>
</tr>
</tfoot>
</table>
<div t-else="" class="alert alert-info">
Nothing to display.
</div>
</t>
</templates>

View File

@@ -0,0 +1,179 @@
import {defineModels, fields, models, mountView} from "@web/../tests/web_test_helpers";
import {describe, expect, test} from "@odoo/hoot";
describe.current.tags("desktop");
class Main extends models.Model {
line_ids = fields.One2many({
string: "Matrix",
relation: "line",
relation_field: "main_id",
});
_records = [{id: 1, line_ids: [1, 2, 3, 4]}];
}
class Line extends models.Model {
main_id = fields.Many2one({
relation: "main",
});
x = fields.Integer({});
y = fields.Integer({});
value_float = fields.Float({});
value_char = fields.Char({});
value_many2one = fields.Many2one({relation: "main"});
_records = [
{
id: 1,
main_id: 1,
x: 0,
y: 0,
value_float: 42,
value_char: "0/0",
value_many2one: 1,
},
{
id: 2,
main_id: 1,
x: 0,
y: 1,
value_float: 42,
value_char: "0/1",
value_many2one: 1,
},
{
id: 3,
main_id: 1,
x: 1,
y: 0,
value_float: 42,
value_char: "1/0",
value_many2one: 1,
},
{
id: 4,
main_id: 1,
x: 1,
y: 1,
value_float: 42,
value_char: "1/1",
value_many2one: 1,
},
];
}
defineModels([Line, Main]);
test("matrix displaying float fields are rendered correctly", async () => {
await mountView({
type: "form",
resModel: "main",
resId: 1,
arch: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_float">
<list>
<field name="x" />
<field name="y" />
<field name="value_float" />
</list>
</field>
</form>`,
});
expect(".o_field_widget input").toHaveCount(4);
expect(".col-total").toHaveText("168.00");
});
test("matrix displaying float fields can be configured", async () => {
await mountView({
type: "form",
resModel: "main",
resId: 1,
arch: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_float">
<list>
<field name="x" />
<field name="y" />
<field name="value_float" digits="[16, 3]" />
</list>
</field>
</form>`,
});
expect(".o_field_widget input").toHaveValue("42.000");
});
test("matrix displaying char fields are rendered correctly", async () => {
await mountView({
type: "form",
resModel: "main",
resId: 1,
arch: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_char">
<list>
<field name="x" />
<field name="y" />
<field name="value_char" />
</list>
</field>
</form>`,
});
expect(".o_field_widget input").toHaveCount(4);
expect(".col-total").toHaveCount(0);
});
test("matrix displaying many2one fields are rendered correctly", async () => {
await mountView({
type: "form",
resModel: "main",
resId: 1,
arch: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_many2one">
<list>
<field name="x" />
<field name="y" />
<field name="value_many2one" />
</list>
</field>
</form>`,
});
expect(".o_field_many2one_selection").toHaveCount(4);
expect(".o_form_uri").toHaveCount(0);
});
test("matrix displaying many2one fields can be configured", async () => {
await mountView({
type: "form",
resModel: "main",
resId: 1,
arch: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="x" field_y_axis="y" field_value="value_many2one">
<list>
<field name="x" />
<field name="y" />
<field name="value_many2one" readonly="x == 1" option="{'no_open': true}" />
</list>
</field>
</form>`,
});
expect(".o_field_many2one_selection").toHaveCount(2);
expect(".o_form_uri").toHaveCount(2);
});
test("matrix axis can be clickable", async () => {
await mountView({
type: "form",
resModel: "main",
resId: 1,
arch: `
<form>
<field name="line_ids" widget="x2many_2d_matrix" field_x_axis="value_many2one" field_y_axis="value_many2one" field_value="value_float" x_axis_clickable="True" y_axis_clickable="True">
<list>
<field name="value_float" />
<field name="value_many2one" />
</list>
</field>
</form>`,
});
expect(".o_form_uri").toHaveCount(2);
});

View File

@@ -0,0 +1 @@
from . import test_web_widget_x2many_2d_matrix

View File

@@ -0,0 +1,15 @@
from odoo.tests import HttpCase, tagged
@tagged("post_install", "-at_install")
class TestWebWidgetX2Many2DMatrix(HttpCase):
def test_js(self):
self.browser_js(
"/web/tests?headless&loglevel=2&preset=desktop&timeout=15000&id=b42fa5f8",
"",
"",
login="admin",
timeout=1800,
success_signal="[HOOT] Test suite succeeded",
error_checker=lambda x: "[HOOT]" not in x,
)