diff --git a/web_widget_x2many_2d_matrix/README.rst b/web_widget_x2many_2d_matrix/README.rst new file mode 100644 index 000000000000..78d07082b70e --- /dev/null +++ b/web_widget_x2many_2d_matrix/README.rst @@ -0,0 +1,247 @@ +=========================== +2D matrix for x2many fields +=========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:d7c8ad17385abb55574b0135c2b9bcf91cdccc82964a136b4c14754bd7975d43 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/licence-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/17.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-17-0/web-17-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=17.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: + +:: + + + +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 + + + + + + + + + + +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 + +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 + + + + + + + + + + +Known issues / Roadmap +====================== + +- Support extra attributes on each field cell via field_extra_attrs + param. We could set a cell as not editable, required or readonly for + instance. The readonly case will also give the ability to click on + m2o to open related records. +- 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 extra invisible fields inside each cell. +- 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 `__) + +12.0.1.0.0 (2018-11-20) +----------------------- + +- [12.0][MIG] web_widget_x2many_2d_matrix + (`#1101 `__) + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Therp BV +* Tecnativa +* Camptocamp +* CorporateHub +* Onestein + +Contributors +------------ + +- Holger Brunn +- Pedro M. Baeza +- Artem Kostyuk +- Simone Orsi +- Timon Tschanz +- Jairo Llopis +- Dennis Sluijk +- `CorporateHub `__ + + - Alexey Pelykh + +- Adrià Gil Sorribes +- Christopher Ormaza +- SodexisTeam + +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-ChrisOForgeFlow| image:: https://github.com/ChrisOForgeFlow.png?size=40px + :target: https://github.com/ChrisOForgeFlow + :alt: ChrisOForgeFlow + +Current `maintainer `__: + +|maintainer-ChrisOForgeFlow| + +This module is part of the `OCA/web `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_widget_x2many_2d_matrix/__init__.py b/web_widget_x2many_2d_matrix/__init__.py new file mode 100644 index 000000000000..ef5ae3587f59 --- /dev/null +++ b/web_widget_x2many_2d_matrix/__init__.py @@ -0,0 +1 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). diff --git a/web_widget_x2many_2d_matrix/__manifest__.py b/web_widget_x2many_2d_matrix/__manifest__.py new file mode 100644 index 000000000000..4a8c40b578d2 --- /dev/null +++ b/web_widget_x2many_2d_matrix/__manifest__.py @@ -0,0 +1,40 @@ +# Copyright 2015 Holger Brunn +# Copyright 2016 Pedro M. Baeza +# Copyright 2018 Simone Orsi +# 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": "17.0.1.0.0", + "maintainers": ["ChrisOForgeFlow"], + "development_status": "Production/Stable", + "author": ( + "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"], + "data": [], + "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", + ], + }, +} diff --git a/web_widget_x2many_2d_matrix/i18n/ar.po b/web_widget_x2many_2d_matrix/i18n/ar.po new file mode 100644 index 000000000000..afce2b3e0301 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/ar.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# SaFi J. , 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. \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, fuzzy, python-format +#~ msgid "Sum Total" +#~ msgstr "المجموع الاجمالي" diff --git a/web_widget_x2many_2d_matrix/i18n/de.po b/web_widget_x2many_2d_matrix/i18n/de.po new file mode 100644 index 000000000000..745ac5118d44 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/de.po @@ -0,0 +1,40 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# Rudolf Schnapka , 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "Nichts zu zeigen." + +#, 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" diff --git a/web_widget_x2many_2d_matrix/i18n/es.po b/web_widget_x2many_2d_matrix/i18n/es.po new file mode 100644 index 000000000000..f994793b23c1 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/es.po @@ -0,0 +1,31 @@ +# 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "Nada que mostrar." + +#, fuzzy, python-format +#~ msgid "Sum Total" +#~ msgstr "Total" diff --git a/web_widget_x2many_2d_matrix/i18n/fi.po b/web_widget_x2many_2d_matrix/i18n/fi.po new file mode 100644 index 000000000000..e7e8c9e8d2f9 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/fi.po @@ -0,0 +1,31 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# Jarmo Kortetjärvi , 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, fuzzy, python-format +#~ msgid "Sum Total" +#~ msgstr "Yhteensä" diff --git a/web_widget_x2many_2d_matrix/i18n/fr.po b/web_widget_x2many_2d_matrix/i18n/fr.po new file mode 100644 index 000000000000..05d3cbcaf679 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/fr.po @@ -0,0 +1,39 @@ +# 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +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" diff --git a/web_widget_x2many_2d_matrix/i18n/hr.po b/web_widget_x2many_2d_matrix/i18n/hr.po new file mode 100644 index 000000000000..7100a5dea31c --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/hr.po @@ -0,0 +1,41 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# Ana-Maria Olujić , 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +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" diff --git a/web_widget_x2many_2d_matrix/i18n/it.po b/web_widget_x2many_2d_matrix/i18n/it.po new file mode 100644 index 000000000000..00364e97ab9a --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/it.po @@ -0,0 +1,39 @@ +# 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: 2023-11-27 11:33+0000\n" +"Last-Translator: mymage \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 4.17\n" + +#. 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 +#, python-format +msgid "Nothing to display." +msgstr "Niente da visualizzare." + +#, 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" diff --git a/web_widget_x2many_2d_matrix/i18n/lt.po b/web_widget_x2many_2d_matrix/i18n/lt.po new file mode 100644 index 000000000000..0ed7cf859c76 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/lt.po @@ -0,0 +1,31 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# Viktoras Norkus , 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 , 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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, fuzzy, python-format +#~ msgid "Sum Total" +#~ msgstr "Suma" diff --git a/web_widget_x2many_2d_matrix/i18n/nl.po b/web_widget_x2many_2d_matrix/i18n/nl.po new file mode 100644 index 000000000000..26dbeacfc515 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/nl.po @@ -0,0 +1,36 @@ +# 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +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" diff --git a/web_widget_x2many_2d_matrix/i18n/nl_NL.po b/web_widget_x2many_2d_matrix/i18n/nl_NL.po new file mode 100644 index 000000000000..75b939e4caf0 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/nl_NL.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# Peter Hageman , 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, python-format +#~ msgid "Sum Total" +#~ msgstr "Totaal" diff --git a/web_widget_x2many_2d_matrix/i18n/pt_BR.po b/web_widget_x2many_2d_matrix/i18n/pt_BR.po new file mode 100644 index 000000000000..67be4e335815 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/pt_BR.po @@ -0,0 +1,39 @@ +# 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +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" diff --git a/web_widget_x2many_2d_matrix/i18n/sl.po b/web_widget_x2many_2d_matrix/i18n/sl.po new file mode 100644 index 000000000000..adf32601c93a --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/sl.po @@ -0,0 +1,31 @@ +# 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č \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, fuzzy, python-format +#~ msgid "Sum Total" +#~ msgstr "Skupaj" diff --git a/web_widget_x2many_2d_matrix/i18n/tr.po b/web_widget_x2many_2d_matrix/i18n/tr.po new file mode 100644 index 000000000000..c96be83379b0 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/tr.po @@ -0,0 +1,31 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_widget_x2many_2d_matrix +# +# Translators: +# Ahmet Altınışık , 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 \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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, fuzzy, python-format +#~ msgid "Sum Total" +#~ msgstr "Toplam" diff --git a/web_widget_x2many_2d_matrix/i18n/web_widget_x2many_2d_matrix.pot b/web_widget_x2many_2d_matrix/i18n/web_widget_x2many_2d_matrix.pot new file mode 100644 index 000000000000..5c1a838400cc --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/web_widget_x2many_2d_matrix.pot @@ -0,0 +1,21 @@ +# 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 16.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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" diff --git a/web_widget_x2many_2d_matrix/i18n/zh_CN.po b/web_widget_x2many_2d_matrix/i18n/zh_CN.po new file mode 100644 index 000000000000..5cd558660c42 --- /dev/null +++ b/web_widget_x2many_2d_matrix/i18n/zh_CN.po @@ -0,0 +1,36 @@ +# 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 +#. odoo-javascript +#: code:addons/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml:0 +#, python-format +msgid "Nothing to display." +msgstr "" + +#, python-format +#~ msgid "Sorry no matrix data to display." +#~ msgstr "抱歉没有要显示的矩阵数据。" + +#, python-format +#~ msgid "Sum" +#~ msgstr "总和" + +#, python-format +#~ msgid "Sum Total" +#~ msgstr "总和" diff --git a/web_widget_x2many_2d_matrix/pyproject.toml b/web_widget_x2many_2d_matrix/pyproject.toml new file mode 100644 index 000000000000..4231d0cccb3d --- /dev/null +++ b/web_widget_x2many_2d_matrix/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/web_widget_x2many_2d_matrix/readme/CONTRIBUTORS.md b/web_widget_x2many_2d_matrix/readme/CONTRIBUTORS.md new file mode 100644 index 000000000000..abfc17c881fb --- /dev/null +++ b/web_widget_x2many_2d_matrix/readme/CONTRIBUTORS.md @@ -0,0 +1,12 @@ +- Holger Brunn \<\> +- Pedro M. Baeza \<\> +- Artem Kostyuk \<\> +- Simone Orsi \<\> +- Timon Tschanz \<\> +- Jairo Llopis \<\> +- Dennis Sluijk \<\> +- [CorporateHub](https://corporatehub.eu/) + - Alexey Pelykh \<\> +- Adrià Gil Sorribes \<\> +- Christopher Ormaza \<\> +- SodexisTeam \<\> diff --git a/web_widget_x2many_2d_matrix/readme/DESCRIPTION.md b/web_widget_x2many_2d_matrix/readme/DESCRIPTION.md new file mode 100644 index 000000000000..bad2cb4719f9 --- /dev/null +++ b/web_widget_x2many_2d_matrix/readme/DESCRIPTION.md @@ -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. diff --git a/web_widget_x2many_2d_matrix/readme/HISTORY.md b/web_widget_x2many_2d_matrix/readme/HISTORY.md new file mode 100644 index 000000000000..8edfd5190aba --- /dev/null +++ b/web_widget_x2many_2d_matrix/readme/HISTORY.md @@ -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)) diff --git a/web_widget_x2many_2d_matrix/readme/ROADMAP.md b/web_widget_x2many_2d_matrix/readme/ROADMAP.md new file mode 100644 index 000000000000..234aa7cd5246 --- /dev/null +++ b/web_widget_x2many_2d_matrix/readme/ROADMAP.md @@ -0,0 +1,12 @@ +- Support extra attributes on each field cell via field_extra_attrs + param. We could set a cell as not editable, required or readonly for + instance. The readonly case will also give the ability to click on m2o + to open related records. +- Support limit total records in the matrix. Ref: + +- 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 + is merged. +- Support extra invisible fields inside each cell. +- Support kanban mode. Current behaviour forces list mode. diff --git a/web_widget_x2many_2d_matrix/readme/USAGE.md b/web_widget_x2many_2d_matrix/readme/USAGE.md new file mode 100644 index 000000000000..d85bd6fed973 --- /dev/null +++ b/web_widget_x2many_2d_matrix/readme/USAGE.md @@ -0,0 +1,91 @@ +Use this widget by saying: + + + +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 + + + + + + + + +``` + +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 + +## 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 + + + + + + + + +``` diff --git a/web_widget_x2many_2d_matrix/static/description/icon.png b/web_widget_x2many_2d_matrix/static/description/icon.png new file mode 100644 index 000000000000..a501fbf835ea Binary files /dev/null and b/web_widget_x2many_2d_matrix/static/description/icon.png differ diff --git a/web_widget_x2many_2d_matrix/static/description/index.html b/web_widget_x2many_2d_matrix/static/description/index.html new file mode 100644 index 000000000000..470e355613e9 --- /dev/null +++ b/web_widget_x2many_2d_matrix/static/description/index.html @@ -0,0 +1,595 @@ + + + + + + +2D matrix for x2many fields + + + +
+

2D matrix for x2many fields

+ + +

Production/Stable License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

+

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.

+

Table of contents

+ +
+

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:

+
+<field name="my_field" widget="x2many_2d_matrix" field_x_axis="my_field1" field_y_axis="my_field2" field_value="my_field3">
+    <tree>
+        <field name="my_field"/>
+        <field name="my_field1"/>
+        <field name="my_field2"/>
+        <field name="my_field3"/>
+    </tree>
+</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

+
+

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:

+
+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:

+
+<field name="task_ids" widget="x2many_2d_matrix" field_x_axis="project_id" field_y_axis="user_id" field_value="planned_hours">
+    <tree>
+        <field name="task_ids"/>
+        <field name="project_id"/>
+        <field name="user_id"/>
+        <field name="planned_hours"/>
+    </tree>
+</field>
+
+
+
+
+

Known issues / Roadmap

+
    +
  • Support extra attributes on each field cell via field_extra_attrs +param. We could set a cell as not editable, required or readonly for +instance. The readonly case will also give the ability to click on +m2o to open related records.
  • +
  • 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 extra invisible fields inside each cell.
  • +
  • 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)
  • +
+
+
+

12.0.1.0.0 (2018-11-20)

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

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Therp BV
  • +
  • Tecnativa
  • +
  • Camptocamp
  • +
  • CorporateHub
  • +
  • Onestein
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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.

+

Current maintainer:

+

ChrisOForgeFlow

+

This module is part of the OCA/web project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/web_widget_x2many_2d_matrix/static/description/screenshot.png b/web_widget_x2many_2d_matrix/static/description/screenshot.png new file mode 100644 index 000000000000..4b75baa8aa91 Binary files /dev/null and b/web_widget_x2many_2d_matrix/static/description/screenshot.png differ diff --git a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.esm.js b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.esm.js new file mode 100644 index 000000000000..40ca3ac50d0d --- /dev/null +++ b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.esm.js @@ -0,0 +1,57 @@ +/** @odoo-module **/ + +import {Component} from "@odoo/owl"; +import {X2Many2DMatrixRenderer} from "@web_widget_x2many_2d_matrix/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm"; +import {archParseBoolean} from "@web/views/utils"; +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(); + } +} + +X2Many2DMatrixField.template = "web_widget_x2many_2d_matrix.X2Many2DMatrixField"; +X2Many2DMatrixField.props = { + ...standardFieldProps, + list: {type: Object, optional: true}, + matrixFields: {type: Object, optional: true}, + 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}) { + return { + matrixFields: { + value: attrs.field_value, + x: attrs.field_x_axis, + y: attrs.field_y_axis, + }, + isXClickable: archParseBoolean(attrs.x_axis_clickable), + isYClickable: archParseBoolean(attrs.y_axis_clickable), + showRowTotals: + "show_row_totals" in attrs + ? archParseBoolean(attrs.show_row_totals) + : true, + showColumnTotals: + "show_column_totals" in attrs + ? archParseBoolean(attrs.show_column_totals) + : true, + }; + }, +}; +registry.category("fields").add("x2many_2d_matrix", x2Many2DMatrixField); diff --git a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.scss b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.scss new file mode 100644 index 000000000000..65e600333701 --- /dev/null +++ b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.scss @@ -0,0 +1,83 @@ +$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; + background-color: $o-list-footer-bg-color; + + &.total { + right: 0; + } + } + + > tbody { + > tr { + &:nth-of-type(2n + 1) td.row-total, + &:nth-of-type(2n + 1) td:first-child { + background-color: mix(#000, #fff, 1%); + } + &:nth-of-type(2n) td.row-total, + &:nth-of-type(2n) td:first-child { + background-color: white; + } + + > 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; + box-shadow: -1px 5px 10px $gray-300; + } + &.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; + box-shadow: -1px 5px 10px $gray-300; + } + } + } + } + + > tfoot > tr > th { + text-align: right; + background-color: $o-list-footer-bg-color; + position: sticky; + bottom: 0; + + &.col-total { + padding: 0.75rem; + right: 0; + border-left-width: 1px; + border-left-color: $gray-300; + border-left-style: solid; + background-color: white; + } + } + } +} diff --git a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.xml b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.xml new file mode 100644 index 000000000000..c6b02aea6ba9 --- /dev/null +++ b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_field/x2many_2d_matrix_field.xml @@ -0,0 +1,14 @@ + + + +
+ +
+
+
diff --git a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js new file mode 100644 index 000000000000..56cb698ddc43 --- /dev/null +++ b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.esm.js @@ -0,0 +1,179 @@ +/** @odoo-module **/ + +import {Component, onWillUpdateProps} from "@odoo/owl"; +import {registry} from "@web/core/registry"; +const fieldRegistry = registry.category("fields"); + +export class X2Many2DMatrixRenderer extends Component { + setup() { + this.ValueFieldComponent = this._getValueFieldComponent(); + this.columns = this._getColumns(); + this.rows = this._getRows(); + this.matrix = this._getMatrix(); + this.ValueFieldType = this._getValueFieldType(); + + 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], + }; + 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], + }; + 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; + } + + _getValueFieldComponent() { + const field = this.list.fields[this.matrixFields.value]; + if (!field.widget) { + return fieldRegistry.get(field.type).component; + } + return fieldRegistry.get(field.widget).component; + } + + _getValueFieldType() { + const field = this.list.fields[this.matrixFields.value]; + return field.type; + } + + _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); + if (this.ValueFieldType === "integer") { + return total; + } + return Number(total).toFixed(2); + } + + _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); + if (this.ValueFieldType === "integer") { + return total; + } + return Number(total).toFixed(2); + } + + _aggregateAll() { + const total = this.matrix + .map((r) => r.map((x) => x.value).reduce((aggr, x) => aggr + x)) + .reduce((aggr, y) => aggr + y); + if (this.ValueFieldType === "integer") { + return total; + } + return Number(total).toFixed(2); + } + + _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); + let record = null; + let value = null; + if ( + this.matrix[y] && + this.matrix[y][x] && + (record = this.matrix[y][x].records[0]) + ) { + record = this.matrix[y][x].records[0]; + value = this.matrix[y][x].value; + } + value = record ? record.data[this.matrixFields.value] : value; + this.matrix[y][x].value = value; + const result = { + readonly: this.props.readonly, + record: record, + name: this.matrixFields.value, + }; + if (value === null) { + result.readonly = true; + } + return result; + } +} + +X2Many2DMatrixRenderer.template = "web_widget_x2many_2d_matrix.X2Many2DMatrixRenderer"; +X2Many2DMatrixRenderer.props = { + list: {type: Object, optional: true}, + matrixFields: {type: Object, optional: true}, + readonly: {type: Boolean, optional: true}, + showRowTotals: {type: Boolean, optional: true}, + showColumnTotals: {type: Boolean, optional: true}, +}; diff --git a/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml new file mode 100644 index 000000000000..562d565d299b --- /dev/null +++ b/web_widget_x2many_2d_matrix/static/src/components/x2many_2d_matrix_renderer/x2many_2d_matrix_renderer.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ + + + +
+
+ Nothing to display. +
+
+