diff --git a/web_advanced_search/README.rst b/web_advanced_search/README.rst new file mode 100644 index 000000000..631fb9945 --- /dev/null +++ b/web_advanced_search/README.rst @@ -0,0 +1,170 @@ +=============== +Advanced search +=============== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |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/13.0/web_advanced_search + :alt: OCA/web +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/web-13-0/web-13-0-web_advanced_search + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/162/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +More powerful and easy to use search, especially for related fields. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +* Open *Filters* in a search view +* Select any relational field +* Select operator `is equal to` or `is not equal to` +* The text field changes to a relational selection field where you + can search for the record in question +* Click *Apply* + +To search for properties of linked records (ie invoices for customers +with a credit limit higher than X): + +* Open *Filters* in a search view +* Select *Add Advanced Filter* +* Edit the advanced filter +* Click *Save* + +Note that you can stack searching for properties: Simply add another +advanced search in the selection search window. You can do +this indefinetely, so it is possible to search for moves belonging +to a journal which has a user who is member of a certain group etc. + +Known issues / Roadmap +====================== + +Improvements to the ``domain`` widget, not exclusively related to this addon: + +* Use relational widgets when filtering a relational field +* Allow to filter field names + +Improvements to the search view in this addon: + +* Use widgets ``one2many_tags`` when searching ``one2many`` fields +* Use widgets ``many2many_tags`` when searching ``many2many`` fields +* Allow to edit current full search using the advanced domain editor + +Issues: + +* Grouped totals can show incorrect values. See https://github.com/odoo/odoo/issues/47950 + +Changelog +========= + +11.0.1.0.2 (2018-10-31) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix initialization of 1st domain node + + Sometime the dialog is not ready yet, like on EE version. + Hence when you inject the 1st domain node + the dialog must be already opened. + + [simahawk] + + +11.0.1.0.1 (2018-09-18) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix `undefined` in x2m fields + + Before this patch, when searching with the "equals to" operator in any + x2many field, the searched parameter was always `undefined`. + + The problem was that the underlying field manager implementation was + treating those fields as x2many, while the widget used was the `one2many` + one. + + This patch simply mocks the underlying fake record to make think that + any relational field is always a `one2many`. This sets all pieces in + place and makes the field manager work as expected, and thus you can + search as expected too. + +* Make linter happy + + [Yajo] + + +11.0.1.0.0 (2018-07-20) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Rename, refactor, migrate to v11 + + [Yajo] + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Therp BV +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* Holger Brunn +* Rami Alwafaie +* Jose Mª Bernet +* Simone Orsi +* Dennis Sluijk +* `Tecnativa `_: + + * Vicent Cubells + * Jairo Llopis + * Alexandre Díaz + +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. + +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_advanced_search/__init__.py b/web_advanced_search/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/web_advanced_search/__manifest__.py b/web_advanced_search/__manifest__.py new file mode 100644 index 000000000..46710e36f --- /dev/null +++ b/web_advanced_search/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2015 Therp BV +# Copyright 2017 Tecnativa - Vicent Cubells +# Copyright 2018 Tecnativa - Jairo Llopis +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Advanced search", + "version": "13.0.1.0.0", + "author": "Therp BV, " "Tecnativa, " "Odoo Community Association (OCA)", + "license": "AGPL-3", + "category": "Usability", + "summary": "Easier and more powerful searching tools", + "website": "https://github.com/OCA/web", + "depends": ["web"], + "data": ["views/templates.xml"], + "qweb": ["static/src/xml/web_advanced_search.xml"], + "installable": True, + "application": False, +} diff --git a/web_advanced_search/i18n/da.po b/web_advanced_search/i18n/da.po new file mode 100644 index 000000000..b03a0e7fe --- /dev/null +++ b/web_advanced_search/i18n/da.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2018-09-01 05:03+0000\n" +"Last-Translator: Hans Henrik Gabelgaard \n" +"Language-Team: none\n" +"Language: da\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.1.1\n" + +#. module: web_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "Tilføj avanceret filter" diff --git a/web_advanced_search/i18n/de.po b/web_advanced_search/i18n/de.po new file mode 100644 index 000000000..456152108 --- /dev/null +++ b/web_advanced_search/i18n/de.po @@ -0,0 +1,29 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# Rudolf Schnapka , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2018-01-03 03:49+0000\n" +"Last-Translator: Rudolf Schnapka , 2018\n" +"Language-Team: German (https://www.transifex.com/oca/teams/23907/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" + +#. module: web_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "" + +#~ msgid "is in selection" +#~ msgstr "Ist in Auswahl" diff --git a/web_advanced_search/i18n/es.po b/web_advanced_search/i18n/es.po new file mode 100644 index 000000000..e557e80e6 --- /dev/null +++ b/web_advanced_search/i18n/es.po @@ -0,0 +1,30 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2019-08-04 17:44+0000\n" +"Last-Translator: eduardgm \n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/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 3.7.1\n" + +#. module: web_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "Añadir un Filtro Avanzado" + +#~ msgid "is in selection" +#~ msgstr "está en la selección" diff --git a/web_advanced_search/i18n/fr.po b/web_advanced_search/i18n/fr.po new file mode 100644 index 000000000..8d2fc1b6d --- /dev/null +++ b/web_advanced_search/i18n/fr.po @@ -0,0 +1,30 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2019-05-27 13:20+0000\n" +"Last-Translator: Kévin Allard \n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/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.6.1\n" + +#. module: web_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "Ajouter un filtre avancé" + +#~ msgid "is in selection" +#~ msgstr "parmi la sélection" diff --git a/web_advanced_search/i18n/hr.po b/web_advanced_search/i18n/hr.po new file mode 100644 index 000000000..ed37f7b08 --- /dev/null +++ b/web_advanced_search/i18n/hr.po @@ -0,0 +1,31 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# Bole , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2019-11-14 10:34+0000\n" +"Last-Translator: Bole \n" +"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/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_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "Dodaj napredni filter" + +#~ msgid "is in selection" +#~ msgstr "je u odabiru" diff --git a/web_advanced_search/i18n/nl.po b/web_advanced_search/i18n/nl.po new file mode 100644 index 000000000..7e2dfadef --- /dev/null +++ b/web_advanced_search/i18n/nl.po @@ -0,0 +1,29 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2018-01-03 03:49+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Dutch (https://www.transifex.com/oca/teams/23907/nl/)\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" + +#. module: web_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "" + +#~ msgid "is in selection" +#~ msgstr "is in selectie" diff --git a/web_advanced_search/i18n/nl_NL.po b/web_advanced_search/i18n/nl_NL.po new file mode 100644 index 000000000..9fcd77d25 --- /dev/null +++ b/web_advanced_search/i18n/nl_NL.po @@ -0,0 +1,30 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# Peter Hageman , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2018-01-03 03:49+0000\n" +"Last-Translator: Peter Hageman , 2017\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" + +#. module: web_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "" + +#~ msgid "is in selection" +#~ msgstr "Is in selectie" diff --git a/web_advanced_search/i18n/pt.po b/web_advanced_search/i18n/pt.po new file mode 100644 index 000000000..505377c12 --- /dev/null +++ b/web_advanced_search/i18n/pt.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-08-12 11:44+0000\n" +"Last-Translator: Pedro Castro Silva \n" +"Language-Team: none\n" +"Language: pt\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_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "Adicionar Filtro Avançado" diff --git a/web_advanced_search/i18n/pt_BR.po b/web_advanced_search/i18n/pt_BR.po new file mode 100644 index 000000000..9383bf8ee --- /dev/null +++ b/web_advanced_search/i18n/pt_BR.po @@ -0,0 +1,31 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +# Translators: +# Rodrigo de Almeida Sottomaior Macedo , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-03 03:49+0000\n" +"PO-Revision-Date: 2019-08-30 15:23+0000\n" +"Last-Translator: Rodrigo Macedo \n" +"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/teams/" +"23907/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_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "Adicionar filtro avançado" + +#~ msgid "is in selection" +#~ msgstr "Está em seleção" diff --git a/web_advanced_search/i18n/web_advanced_search.pot b/web_advanced_search/i18n/web_advanced_search.pot new file mode 100644 index 000000000..5179bdfc6 --- /dev/null +++ b/web_advanced_search/i18n/web_advanced_search.pot @@ -0,0 +1,22 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.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_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "" + diff --git a/web_advanced_search/i18n/zh_CN.po b/web_advanced_search/i18n/zh_CN.po new file mode 100644 index 000000000..c28780c3c --- /dev/null +++ b/web_advanced_search/i18n/zh_CN.po @@ -0,0 +1,24 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2019-09-01 12:52+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_advanced_search +#. openerp-web +#: code:addons/web_advanced_search/static/src/xml/web_advanced_search.xml:8 +#, python-format +msgid "Add Advanced Filter" +msgstr "添加高级过滤器" diff --git a/web_advanced_search/readme/CONTRIBUTORS.rst b/web_advanced_search/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..d0917fc03 --- /dev/null +++ b/web_advanced_search/readme/CONTRIBUTORS.rst @@ -0,0 +1,10 @@ +* Holger Brunn +* Rami Alwafaie +* Jose Mª Bernet +* Simone Orsi +* Dennis Sluijk +* `Tecnativa `_: + + * Vicent Cubells + * Jairo Llopis + * Alexandre Díaz diff --git a/web_advanced_search/readme/DESCRIPTION.rst b/web_advanced_search/readme/DESCRIPTION.rst new file mode 100644 index 000000000..bd4c29fdd --- /dev/null +++ b/web_advanced_search/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +More powerful and easy to use search, especially for related fields. diff --git a/web_advanced_search/readme/HISTORY.rst b/web_advanced_search/readme/HISTORY.rst new file mode 100644 index 000000000..7b791ed95 --- /dev/null +++ b/web_advanced_search/readme/HISTORY.rst @@ -0,0 +1,40 @@ +11.0.1.0.2 (2018-10-31) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix initialization of 1st domain node + + Sometime the dialog is not ready yet, like on EE version. + Hence when you inject the 1st domain node + the dialog must be already opened. + + [simahawk] + + +11.0.1.0.1 (2018-09-18) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Fix `undefined` in x2m fields + + Before this patch, when searching with the "equals to" operator in any + x2many field, the searched parameter was always `undefined`. + + The problem was that the underlying field manager implementation was + treating those fields as x2many, while the widget used was the `one2many` + one. + + This patch simply mocks the underlying fake record to make think that + any relational field is always a `one2many`. This sets all pieces in + place and makes the field manager work as expected, and thus you can + search as expected too. + +* Make linter happy + + [Yajo] + + +11.0.1.0.0 (2018-07-20) +~~~~~~~~~~~~~~~~~~~~~~~ + +* Rename, refactor, migrate to v11 + + [Yajo] diff --git a/web_advanced_search/readme/ROADMAP.rst b/web_advanced_search/readme/ROADMAP.rst new file mode 100644 index 000000000..b71b3c344 --- /dev/null +++ b/web_advanced_search/readme/ROADMAP.rst @@ -0,0 +1,14 @@ +Improvements to the ``domain`` widget, not exclusively related to this addon: + +* Use relational widgets when filtering a relational field +* Allow to filter field names + +Improvements to the search view in this addon: + +* Use widgets ``one2many_tags`` when searching ``one2many`` fields +* Use widgets ``many2many_tags`` when searching ``many2many`` fields +* Allow to edit current full search using the advanced domain editor + +Issues: + +* Grouped totals can show incorrect values. See https://github.com/odoo/odoo/issues/47950 diff --git a/web_advanced_search/readme/USAGE.rst b/web_advanced_search/readme/USAGE.rst new file mode 100644 index 000000000..b8e6f2778 --- /dev/null +++ b/web_advanced_search/readme/USAGE.rst @@ -0,0 +1,21 @@ +To use this module, you need to: + +* Open *Filters* in a search view +* Select any relational field +* Select operator `is equal to` or `is not equal to` +* The text field changes to a relational selection field where you + can search for the record in question +* Click *Apply* + +To search for properties of linked records (ie invoices for customers +with a credit limit higher than X): + +* Open *Filters* in a search view +* Select *Add Advanced Filter* +* Edit the advanced filter +* Click *Save* + +Note that you can stack searching for properties: Simply add another +advanced search in the selection search window. You can do +this indefinetely, so it is possible to search for moves belonging +to a journal which has a user who is member of a certain group etc. diff --git a/web_advanced_search/static/description/icon.png b/web_advanced_search/static/description/icon.png new file mode 100644 index 000000000..1ab5d1e10 Binary files /dev/null and b/web_advanced_search/static/description/icon.png differ diff --git a/web_advanced_search/static/description/index.html b/web_advanced_search/static/description/index.html new file mode 100644 index 000000000..cb77eb4f1 --- /dev/null +++ b/web_advanced_search/static/description/index.html @@ -0,0 +1,521 @@ + + + + + + +Advanced search + + + + + + diff --git a/web_advanced_search/static/src/js/human_domain.js b/web_advanced_search/static/src/js/human_domain.js new file mode 100644 index 000000000..53772d791 --- /dev/null +++ b/web_advanced_search/static/src/js/human_domain.js @@ -0,0 +1,61 @@ +/* Copyright 2018 Tecnativa - Jairo Llopis + * Copyright 2020 Tecnativa - Alexandre Díaz + * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */ + +odoo.define("web_advanced_search.human_domain", function() { + "use strict"; + + const join_mapping = { + "&": _(" and "), + "|": _(" or "), + "!": _(" is not "), + }; + + const human_domain_methods = { + DomainTree: function() { + const human_domains = []; + _.each(this.children, child => { + human_domains.push(human_domain_methods[child.template].apply(child)); + }); + return `(${human_domains.join(join_mapping[this.operator])})`; + }, + + DomainSelector: function() { + const result = human_domain_methods.DomainTree.apply(this, arguments); + // Remove surrounding parenthesis + return result.slice(1, -1); + }, + + DomainLeaf: function() { + const chain = []; + let operator = this.operator_mapping[this.operator], + value = `"${this.value}"`; + // Humanize chain + const chain_splitted = this.chain.split("."); + const len = chain_splitted.length; + for (let x = 0; x < len; ++x) { + const element = chain_splitted[x]; + chain.push( + _.findWhere(this.fieldSelector.pages[x], {name: element}).string || + element + ); + } + // Special beautiness for some values + if (this.operator === "=" && _.isBoolean(this.value)) { + operator = this.operator_mapping[this.value ? "set" : "not set"]; + value = ""; + } else if (_.isArray(this.value)) { + value = `["${this.value.join('", "')}"]`; + } + return `${chain.join("→")} ${operator || this.operator} ${value}`.trim(); + }, + }; + + function getHumanDomain(domain_selector) { + return human_domain_methods.DomainSelector.apply(domain_selector); + } + + return { + getHumanDomain: getHumanDomain, + }; +}); diff --git a/web_advanced_search/static/src/js/web_advanced_search.js b/web_advanced_search/static/src/js/web_advanced_search.js new file mode 100644 index 000000000..15724b0c0 --- /dev/null +++ b/web_advanced_search/static/src/js/web_advanced_search.js @@ -0,0 +1,350 @@ +/* Copyright 2015 Therp BV + * Copyright 2017-2018 Jairo Llopis + * Copyright 2020 Alexandre Díaz + * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */ + +odoo.define("web_advanced_search", function(require) { + "use strict"; + + const config = require("web.config"); + const Domain = require("web.Domain"); + const DomainSelector = require("web.DomainSelector"); + const DomainSelectorDialog = require("web.DomainSelectorDialog"); + const field_registry = require("web.field_registry"); + const FieldManagerMixin = require("web.FieldManagerMixin"); + const FilterMenu = require("web.FilterMenu"); + const human_domain = require("web_advanced_search.human_domain"); + const Widget = require("web.Widget"); + const search_filters_registry = require("web.search_filters_registry"); + const Char = search_filters_registry.get("char"); + + /** + * An almost dummy search proposition, to use with domain widget + */ + const AdvancedSearchProposition = Widget.extend({ + /** + * @override + */ + init: function(parent, model, domain) { + this._super(parent); + this.model = model; + this.domain = new Domain(domain); + this.domain_array = domain; + this._createDomainSelector(); + }, + + /** + * Produce a filter descriptor for advanced searches. + * + * @returns {Object} In the format expected by `web.FilterMenu`. + */ + get_filter: function() { + return { + attrs: { + domain: this.domain_array, + string: human_domain.getHumanDomain(this.domain_selector), + }, + children: [], + tag: "filter", + }; + }, + + _createDomainSelector: function() { + this.domain_selector = new DomainSelector( + this, + this.model, + this.domain_array + ); + this.dummy_parent = $("
"); + return this.domain_selector.appendTo(this.dummy_parent); + }, + + destroy: function() { + this.domain_selector.destroy(); + this.dummy_parent.remove(); + return this._super.apply(this, arguments); + }, + }); + + // Add advanced search features + FilterMenu.include({ + custom_events: _.extend({}, FilterMenu.prototype.custom_events, { + domain_selected: "advanced_search_commit", + }), + + events: _.extend({}, FilterMenu.prototype.events, { + "click .o_add_advanced_search": "advanced_search_open", + }), + + /** + * @override + */ + init: function() { + this._super.apply(this, arguments); + + this._context = this.getParent().context; + this._modelName = this.getParent().getParent().modelName; + }, + + /** + * Open advanced search dialog + * + * @returns {$.Deferred} The opening dialog itself. + */ + advanced_search_open: function() { + const domain_selector_dialog = new DomainSelectorDialog( + this, + this._modelName, + "[]", + { + debugMode: config.debug, + readonly: false, + } + ); + domain_selector_dialog.opened(() => { + // Add 1st domain node by default + domain_selector_dialog.domainSelector._onAddFirstButtonClick(); + }); + return domain_selector_dialog.open(); + }, + + /** + * Apply advanced search on dialog save + * + * @param {OdooEvent} event A `domain_selected` event from the dialog. + */ + advanced_search_commit: function(event) { + _.invoke(this.propositions, "destroy"); + const proposition = new AdvancedSearchProposition( + this, + this._modelName, + event.data.domain + ); + // Necessary to ensure that the porposition have the 'fieldSelector' + // is filled + _.defer( + function() { + this.propositions = [proposition]; + this._commitSearch(); + }.bind(this) + ); + }, + }); + + /** + * A search field for relational fields. + * + * It implements and extends the `FieldManagerMixin`, and acts as if it + * were a reduced dummy controller. Some actions "mock" the underlying + * model, since sometimes we use a char widget to fill related fields + * (which is not supported by that widget), and fields need an underlying + * model implementation, which can only hold fake data, given a search view + * has no data on it by definition. + */ + const Relational = Char.extend(FieldManagerMixin, { + tagName: "div", + className: "x2x_container", + attributes: {}, + + /** + * @override + */ + init: function() { + this._super.apply(this, arguments); + // To make widgets work, we need a model and an empty record + FieldManagerMixin.init.call(this); + this.trigger_up("get_dataset"); + // Make equal and not equal appear 1st and 2nd + this.operators = _.sortBy(this.operators, op => { + switch (op.value) { + case "=": + return -2; + case "!=": + return -1; + default: + return 0; + } + }); + // Create dummy record with only the field the user is searching + const params = { + fieldNames: [this.field.name], + modelName: this.dataset.model, + context: this.dataset.context, + type: "record", + viewType: "default", + fieldsInfo: { + default: {}, + }, + fields: { + [this.field.name]: _.omit( + this.field, + // User needs all records, to actually produce a new domain + "domain", + // Onchanges make no sense in this context, there's no record + "onChange" + ), + }, + }; + if (this.field.type.endsWith("2many")) { + // X2many fields behave like m2o in the search context + params.fields[this.field.name].type = "many2one"; + } + params.fieldsInfo.default[this.field.name] = {}; + // Emulate `model.load()`, without RPC-calling `default_get()` + this.datapoint_id = this.model._makeDataPoint(params).id; + this.model.applyDefaultValues(this.datapoint_id, {}, params.fieldNames); + // To generate a new fake ID + this._fake_id = -1; + }, + + /** + * @override + */ + start: function() { + const result = this._super.apply(this, arguments); + // Render the initial widget + result.done($.proxy(this, "show_inputs", $(""))); + return result; + }, + + /** + * @override + */ + destroy: function() { + if (this._field_widget) { + this._field_widget.destroy(); + } + this.model.destroy(); + delete this.record; + return this._super.apply(this, arguments); + }, + + /** + * Get record object for current datapoint. + * + * @returns {Object} + */ + _get_record: function() { + return this.model.get(this.datapoint_id); + }, + + /** + * @override + */ + show_inputs: function($operator) { + // Get widget class to be used + switch ($operator.val()) { + case "=": + case "!=": + this._field_widget_name = "many2one"; + break; + default: + this._field_widget_name = "char"; + } + const _Widget = field_registry.get(this._field_widget_name); + // Destroy previous widget, if any + if (this._field_widget) { + this._field_widget.destroy(); + delete this._field_widget; + } + // Create new widget + const options = { + mode: "edit", + attrs: { + options: { + no_create_edit: true, + no_create: true, + no_open: true, + no_quick_create: true, + }, + }, + }; + this._field_widget = new _Widget( + this, + this.field.name, + this._get_record(), + options + ); + this._field_widget.appendTo(this.$el); + return this._super.apply(this, arguments); + }, + + /** + * @override + */ + _applyChanges: function(dataPointID, changes, event) { + if (this._field_widget_name === "many2one") { + // Make char updates look like valid x2one updates + if (_.isNaN(changes[this.field.name].id)) { + changes[this.field.name] = { + id: this._fake_id--, + display_name: event.target.lastSetValue, + }; + } + return FieldManagerMixin._applyChanges.apply(this, arguments); + } + + return new Promise(resolve => { + resolve(); + }); + }, + + /** + * @override + */ + _confirmChange: function(id, fields, event) { + this.datapoint_id = id; + return this._field_widget.reset(this._get_record(), event); + }, + + /** + * @override + */ + get_value: function() { + try { + switch (this._field_widget_name) { + case "many2one": + return this._field_widget.value.res_id; + default: + return this._field_widget.$el.val(); + } + } catch (error) { + if (error.name === "TypeError") { + return false; + } + } + }, + + /** + * Extract the field's value in a human-readable format. + * + * @override + */ + toString: function() { + try { + switch (this._field_widget_name) { + case "many2one": + return this._field_widget.value.data.display_name; + default: + return this._field_widget.$el.val(); + } + } catch (error) { + if (error.name === "TypeError") { + return ""; + } + } + return this._super.apply(this, arguments); + }, + }); + + // Register search filter widgets + search_filters_registry + .add("many2many", Relational) + .add("many2one", Relational) + .add("one2many", Relational); + + return { + AdvancedSearchProposition: AdvancedSearchProposition, + Relational: Relational, + }; +}); diff --git a/web_advanced_search/static/src/xml/web_advanced_search.xml b/web_advanced_search/static/src/xml/web_advanced_search.xml new file mode 100644 index 000000000..67f0f6468 --- /dev/null +++ b/web_advanced_search/static/src/xml/web_advanced_search.xml @@ -0,0 +1,20 @@ + + + + + +