From e12862505cd00328acfae9c075d227b6981131f5 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Wed, 6 May 2015 17:29:46 +0200 Subject: [PATCH] [ADD] web_advanced_search_x2x --- web_advanced_search_x2x/README.rst | 53 +++ web_advanced_search_x2x/__init__.py | 20 ++ web_advanced_search_x2x/__openerp__.py | 45 +++ web_advanced_search_x2x/i18n/nl.po | 38 ++ .../i18n/web_advanced_search_x2x.pot | 53 +++ .../static/description/icon.png | Bin 0 -> 2053 bytes .../src/css/web_advanced_search_x2x.css | 36 ++ .../static/src/js/web_advanced_search_x2x.js | 329 ++++++++++++++++++ .../src/xml/web_advanced_search_x2x.xml | 12 + web_advanced_search_x2x/views/templates.xml | 11 + 10 files changed, 597 insertions(+) create mode 100644 web_advanced_search_x2x/README.rst create mode 100644 web_advanced_search_x2x/__init__.py create mode 100644 web_advanced_search_x2x/__openerp__.py create mode 100644 web_advanced_search_x2x/i18n/nl.po create mode 100644 web_advanced_search_x2x/i18n/web_advanced_search_x2x.pot create mode 100644 web_advanced_search_x2x/static/description/icon.png create mode 100644 web_advanced_search_x2x/static/src/css/web_advanced_search_x2x.css create mode 100644 web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js create mode 100644 web_advanced_search_x2x/static/src/xml/web_advanced_search_x2x.xml create mode 100644 web_advanced_search_x2x/views/templates.xml diff --git a/web_advanced_search_x2x/README.rst b/web_advanced_search_x2x/README.rst new file mode 100644 index 00000000..f9346d82 --- /dev/null +++ b/web_advanced_search_x2x/README.rst @@ -0,0 +1,53 @@ +Search for x2x records in advanced search +========================================= + +Standard behavior in advanced search for one2many, many2many and many2one fields is to do a `name_search`. This often is not satisfactionary as you might want to search for other properties. There might also be cases where you don't exactly know what you're searching for, then a list of possible options is necessary too. This module enables you to have a full search view to select the record in question, and either select specific records or select them using a search query of its own. + +Usage +===== + +To use this module, you need to: + +* open the advanced search options in a search view +* select a one2many, many2many or many2one field +* select operator `is equal to` or `is not equal to` +* the textfield changes to a many2one selection field where you can search for the record in question + +To search for properties of linked records (ie invoices for customers with a credit limit higher than X): + +* open the advanced search options in a search view +* select a one2many, many2many or many2one field +* select operator `is in selection` +* in the search view that pops up, select the criteria +* click `Use criteria` +* if you're only interested in certain records, mark them en click `Select` +* if you want to change your selection afterwards, click the search symbol right of the selection term + +In both cases, don't forget to click `Apply` to actually execute the search. + +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. + +For further information, please visit: + +* https://www.odoo.com/forum/help-1 + +Credits +======= + +Contributors +------------ + +* Holger Brunn + +Maintainer +---------- + +.. image:: http://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: http://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit http://odoo-community.org. diff --git a/web_advanced_search_x2x/__init__.py b/web_advanced_search_x2x/__init__.py new file mode 100644 index 00000000..faef9dac --- /dev/null +++ b/web_advanced_search_x2x/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 Therp BV . +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## diff --git a/web_advanced_search_x2x/__openerp__.py b/web_advanced_search_x2x/__openerp__.py new file mode 100644 index 00000000..86152e9d --- /dev/null +++ b/web_advanced_search_x2x/__openerp__.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2015 Therp BV . +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + "name": "Search x2x fields", + "version": "1.0", + "author": "Therp BV", + "license": "AGPL-3", + "category": "Usability", + "summary": "Use a search widget in advanced search for x2x fields", + "depends": [ + 'web', + ], + "data": [ + 'views/templates.xml', + ], + "qweb": [ + 'static/src/xml/web_advanced_search_x2x.xml', + ], + "test": [ + ], + "auto_install": False, + "installable": True, + "application": False, + "external_dependencies": { + 'python': [], + }, +} diff --git a/web_advanced_search_x2x/i18n/nl.po b/web_advanced_search_x2x/i18n/nl.po new file mode 100644 index 00000000..ff22583f --- /dev/null +++ b/web_advanced_search_x2x/i18n/nl.po @@ -0,0 +1,38 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-05-27 07:19+0000\n" +"PO-Revision-Date: 2015-05-27 07:19+0000\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_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:221 +#, python-format +msgid "Use criteria" +msgstr "Gebruik kenmerken" + +#. module: web_advanced_search_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:159 +#, python-format +msgid "invalid search domain" +msgstr "ongeldige zoekopdracht" + +#. module: web_advanced_search_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:47 +#, python-format +msgid "is in selection" +msgstr "is in selectie" + diff --git a/web_advanced_search_x2x/i18n/web_advanced_search_x2x.pot b/web_advanced_search_x2x/i18n/web_advanced_search_x2x.pot new file mode 100644 index 00000000..21cc9b37 --- /dev/null +++ b/web_advanced_search_x2x/i18n/web_advanced_search_x2x.pot @@ -0,0 +1,53 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_advanced_search_x2x +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-05-27 07:19+0000\n" +"PO-Revision-Date: 2015-05-27 07:19+0000\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_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:295 +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:322 +#, python-format +msgid "Advanced" +msgstr "" + +#. module: web_advanced_search_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/xml/web_advanced_search_x2x.xml:8 +#, python-format +msgid "Search" +msgstr "" + +#. module: web_advanced_search_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:221 +#, python-format +msgid "Use criteria" +msgstr "" + +#. module: web_advanced_search_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:159 +#, python-format +msgid "invalid search domain" +msgstr "" + +#. module: web_advanced_search_x2x +#. openerp-web +#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:47 +#, python-format +msgid "is in selection" +msgstr "" + diff --git a/web_advanced_search_x2x/static/description/icon.png b/web_advanced_search_x2x/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1ab5d1e101731ea66677d2dcf278b4c9dbd8ea43 GIT binary patch literal 2053 zcmb7_`#aPB8^_;63|Fzjl=Jd+YU=x;%t($aOKCK;B`I6jm_r+%kkcY%qauB262jLx zhqX$x`kF9{ib!(mQ>{!RvowXz`dn9k!1ssybzjf>dcE%Jb-nKUemyQ>d=G5Y*rovh zz(%yUm%qXjei>Lvv96~pDJz_MtT*l~0BCOcWgwu0rLPF8QPGD{YEv6jwRSjf(!Q9j z2yLaJj!`{hqN9lvD&QGUJVhlEOcNui5vB*whcQ7Jo1ltgX=pEZ?4NJGuwo7!#pyjB zQNVPBVHs9~bNR6o4Y#woX_%!3x&-6dc7}n1>|GeqO zz@fa93tqL`)f*%{b5zgvQtH+7gyn(lPh{_`s+yN^?M-fdwtGHeH}J*|DN@c@mWW-J z69dMM<#Q2DhDo+%sGF{^4v zXF-!*`)BAD6*SYcmGeP|z*!!2I{k8mdAPw=A0MCo!9lfjXxOLOQoZmR+@iNNc;D{8 zdEFvShV5_|fuK@g(+cOM$T$1R#R$Rc`%nnvy7}zTAT#Ov?XxcEULNwe_TigT}i@s!$SrPbTIzf%4|+I`*-g7U)}#g4TSHI?_m@|eu3 zkJi$*VRyg6`k>~gxLFSaY_pK7$VnoTQGN`k*CHvK!{M;m6CH`WM&PRSnX$I;79FrE zU3%u^cYG8q=yapitZMy9QCHH!Gzb_T8NoM>NFjYC62s`TVktvj0#l^LCb=!=M^-vHjw!b~CDl$1{NpmO4W%S-BP8 zmp&f_9I2nQVcEnF5?*JTe05#vr>n76Y5m%`@Q}A(;is*Sx@LNX!iI(h#J3tqb3c0gUQ<)kac?qs_cB`e3;XZw zp3su(+R#GhS%FwA-eF_&?aO$L4KpW|$GdZfKp>bS5S)gFxfhiO6b%yPF#m>4Rx~$| zXY7K<;c&shd!3w|TwItrj259#I8<{aKR-WtuW@d7{5!t7yLLPNOP-PQJ9sFGB#79Z zK&2|G+%prqw6p}ck;!5#wd|BmVWMpLE5cRtA zd~#S=<-=6jf0?_C^DXhafhp{B``xK8?{Uj#AR^bqF7I~*-uqroO*LE1Z?5P?eErwR z-E)-JBO~839=v>XX|g_q@Yn;vcpISeUUR#NNIhUwF*3JAdoH~f&vOTmQ;*I`FG5u> z2@S%4{oH zHNC_x_pRyg?^jMID(w@e$v&^J8D?(&2T6tIW8!f9MlZHW^+V#d4j2QJZa$DITkf3F zTxX73$ie*gxA`BPDl4YL%c6rj5|~&1$MAln~Y^rjd+cFV4!wJ>R+#kV}4?s!nOti;aQ`FK!J4>CVM zTzKO~&wLiV?%5Sgt_2ZQGvt!`^L}03<+GHQV}kyET~yqIU?P!N<6D~a*{GQ2Xc#m32nTmOg?@a^+}hQZ zS6%(FufUQX#q=R&)?yR)*gfGgLp2Vk)}wQ`WDt?foYRZT755b2M>0Kk?l zTbN9y!_8-k!Gagf&CPXJgM7MLhg*YXj+HO&M-El9SgZoeBYJvzbuQ}c&yJj6sXPUk zraEbAXk5gv|=1S`aFC7-K9+aSCj z5?VrnZ&DH-JC9-d_!aVZjODnbez$%*vAQH3TyH1%tI@`C>*Q%N!G%fMu?sROw$*5@ zOKTmS8C9#F%-h4g)Yie2i;4ReLlq%cH!wxY*6~3Q4!Z z6r98jX&$v->2cASR{y_o^^0m|rvD)BACQ3*yz46}1Awaak^fP{yA-?z&?sN8CXdj} FzX6;-%~SvY literal 0 HcmV?d00001 diff --git a/web_advanced_search_x2x/static/src/css/web_advanced_search_x2x.css b/web_advanced_search_x2x/static/src/css/web_advanced_search_x2x.css new file mode 100644 index 00000000..67c3e194 --- /dev/null +++ b/web_advanced_search_x2x/static/src/css/web_advanced_search_x2x.css @@ -0,0 +1,36 @@ +.openerp .searchview_extended_prop_value .oe_form_field_with_button +{ + position: relative; +} +.openerp .oe_searchview_drawer .web_advanced_search_x2x_domain +{ + max-width: 20em; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; +} +/* copy search view's button style */ +.openerp .oe_searchview_drawer .web_advanced_search_x2x_search:before +{ + font: 21px "mnmliconsRegular"; + content: "r"; + color: #a3a3a3; + margin-left: 5px; +} +.openerp .oe_searchview_drawer .web_advanced_search_x2x_search +{ + font-size: 1px; + letter-spacing: -1px; + color: transparent; + text-shadow: none; + font-weight: normal; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + padding: 0; + border: none; + background: transparent; +} diff --git a/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js b/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js new file mode 100644 index 00000000..dd226b8f --- /dev/null +++ b/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js @@ -0,0 +1,329 @@ +//-*- coding: utf-8 -*- +//############################################################################ +// +// OpenERP, Open Source Management Solution +// This module copyright (C) 2015 Therp BV . +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +//############################################################################ + +openerp.web_advanced_search_x2x = function(instance) +{ + instance.web_advanced_search_x2x.ExtendedSearchPropositionMany2One = + instance.web.search.ExtendedSearchProposition.Char.extend( + instance.web.form.FieldManagerMixin, + { + template: 'web_advanced_search_x2x.extended_search.proposition.many2one', + searchfield: null, + init: function() + { + this.operators = _.sortBy( + this.operators, + function(op) + { + switch(op.value) + { + case '=': + return -2; + case '!=': + return -1; + default: + return 0; + } + }); + this.operators.push({ + 'value': 'domain', 'text': instance.web._lt('is in selection'), + }); + return this._super.apply(this, arguments); + }, + start: function() + { + this.getParent().$('.searchview_extended_prop_op') + .on('change', this.proxy('operator_changed')); + return this._super.apply(this, arguments).then( + this.proxy(this.operator_changed)); + }, + get_field_desc: function() + { + return this.field; + }, + create_searchfield_node: function() + { + return { + attrs: { + name: this.field.name, + options: '{"no_create": true}', + }, + } + }, + create_searchfield: function() + { + if(this.searchfield) + { + this.searchfield.destroy(); + } + this.searchfield = new instance.web.form.FieldMany2One( + this, this.create_searchfield_node()); + return this.searchfield; + }, + operator_changed: function(e) + { + if(this.searchfield) + { + this.searchfield.destroy(); + } + this.renderElement(); + if(this.show_searchfield()) + { + this.create_searchfield().appendTo(this.$el.empty()); + } + if(this.show_domain_selection()) + { + this.$el.filter('input').remove(); + this.$el.filter('button.web_advanced_search_x2x_search').click( + this.proxy(this.popup_domain_selection)); + this.popup_domain_selection(); + } + }, + get_operator: function() + { + if(this.isDestroyed()) + { + return false; + } + return this.getParent().$('.searchview_extended_prop_op').val(); + }, + show_searchfield: function() + { + var operator = this.get_operator() + return operator == '=' || operator == '!='; + }, + show_domain_selection: function() + { + return this.get_operator() == 'domain'; + }, + get_value: function() + { + if(this.show_searchfield() && this.searchfield) + { + return this.searchfield.get_value(); + } + return this._super.apply(this, arguments); + }, + format_label: function(format, field, operator) + { + var value = null; + if(this.show_searchfield() && this.searchfield) + { + value = this.searchfield.display_value[ + String(this.searchfield.get_value())]; + } + if(this.show_domain_selection() && this.domain_representation) + { + value = this.domain_representation; + } + if(value) + { + return _.str.sprintf( + format, + { + field: field.string, + operator: operator.label || operator.text, + value: value, + } + ); + } + return this._super.apply(this, arguments); + }, + get_domain: function() + { + if(this.show_domain_selection()) + { + var self = this; + if(!this.domain || this.domain.length == 0) + { + throw new instance.web.search.Invalid( + this.field.string, this.domain_representation, + instance.web._lt('invalid search domain')); + } + return _.extend(new instance.web.CompoundDomain(), { + __domains: [ + _.map(this.domain, function(leaf) + { + if(_.isArray(leaf) && leaf.length == 3) + { + return [ + self.field.name + '.' + leaf[0], + leaf[1], + leaf[2] + ] + } + return leaf; + }), + ], + }) + } + return this._super.apply(this, arguments); + }, + popup_domain_selection: function() + { + var self = this, + popup = new instance.web_advanced_search_x2x.SelectCreatePopup(this); + popup.on('domain_selected', this, function(domain, domain_representation) + { + self.$el.filter('.web_advanced_search_x2x_domain').text( + domain_representation); + self.domain = domain; + self.domain_representation = domain_representation; + }); + popup.select_element( + this.field.relation, {}, this.field.domain, + this.field.context); + }, + }); + + instance.web.search.custom_filters.add( + 'one2many', + 'instance.web_advanced_search_x2x.ExtendedSearchPropositionMany2One'); + instance.web.search.custom_filters.add( + 'many2many', + 'instance.web_advanced_search_x2x.ExtendedSearchPropositionMany2One'); + instance.web.search.custom_filters.add( + 'many2one', + 'instance.web_advanced_search_x2x.ExtendedSearchPropositionMany2One'); + + instance.web_advanced_search_x2x.SelectCreatePopup = instance.web.form.SelectCreatePopup.extend({ + setup_search_view: function() + { + var self = this; + this._super.apply(this, arguments); + this.searchview.on("search_view_loaded", this, function() + { + self.view_list.on("list_view_loaded", self, function() + { + self.$buttonpane.find(".oe_selectcreatepopup-search-create").remove(); + self.$buttonpane.prepend( + jQuery(' + + + + diff --git a/web_advanced_search_x2x/views/templates.xml b/web_advanced_search_x2x/views/templates.xml new file mode 100644 index 00000000..29424680 --- /dev/null +++ b/web_advanced_search_x2x/views/templates.xml @@ -0,0 +1,11 @@ + + + + + +