Pedro M. Baeza
7 years ago
21 changed files with 763 additions and 0 deletions
-
68web_advanced_search/README.rst
-
0web_advanced_search/__init__.py
-
27web_advanced_search/__openerp__.py
-
26web_advanced_search/i18n/de.po
-
26web_advanced_search/i18n/es.po
-
26web_advanced_search/i18n/fr.po
-
27web_advanced_search/i18n/hr.po
-
26web_advanced_search/i18n/nl.po
-
27web_advanced_search/i18n/nl_NL.po
-
28web_advanced_search/i18n/pt_BR.po
-
22web_advanced_search/i18n/web_advanced_search.pot
-
5web_advanced_search/readme/CONTRIBUTORS.rst
-
1web_advanced_search/readme/DESCRIPTION.rst
-
14web_advanced_search/readme/ROADMAP.rst
-
21web_advanced_search/readme/USAGE.rst
-
BINweb_advanced_search/static/description/icon.png
-
13web_advanced_search/static/src/css/web_advanced_search.less
-
86web_advanced_search/static/src/js/human_domain.js
-
293web_advanced_search/static/src/js/web_advanced_search.js
-
13web_advanced_search/static/src/xml/web_advanced_search.xml
-
14web_advanced_search/views/templates.xml
@ -0,0 +1,68 @@ |
|||
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
========================================= |
|||
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 |
|||
* click *Apply* |
|||
|
|||
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 |
|||
* select the records you want, or select the top corner box to select all matching records with that criteria |
|||
* click *Select* |
|||
|
|||
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. |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/162/10.0 |
|||
|
|||
Known issues / Roadmap |
|||
====================== |
|||
|
|||
* When you use *is in selection* search system and choose a domain, it gets |
|||
immediately applied, so to add a new condition, you will have to use again |
|||
the *Filters* menu. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Holger Brunn <hbrunn@therp.nl> |
|||
* Vicent Cubells <vicent.cubells@tecnativa.com> |
|||
* Jairo Llopis <jairo.llopis@tecnativa.com> |
|||
* Rami Alwafaie <rami.alwafaie@initos.com> |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://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 https://odoo-community.org. |
@ -0,0 +1,27 @@ |
|||
# Copyright 2015 Therp BV <http://therp.nl> |
|||
# 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": "11.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, |
|||
} |
@ -0,0 +1,26 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# Rudolf Schnapka <rs@techno-flex.de>, 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 <rs@techno-flex.de>, 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_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "Ist in Auswahl" |
@ -0,0 +1,26 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 2017\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" |
|||
|
|||
#. module: web_advanced_search_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "está en la selección" |
@ -0,0 +1,26 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 2017\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" |
|||
|
|||
#. module: web_advanced_search_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "parmi la sélection" |
@ -0,0 +1,27 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# Bole <bole@dajmi5.com>, 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: Bole <bole@dajmi5.com>, 2017\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" |
|||
|
|||
#. module: web_advanced_search_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "je u odabiru" |
@ -0,0 +1,26 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# OCA Transbot <transbot@odoo-community.org>, 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 <transbot@odoo-community.org>, 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_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "is in selectie" |
@ -0,0 +1,27 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# Peter Hageman <hageman.p@gmail.com>, 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 <hageman.p@gmail.com>, 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_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "Is in selectie" |
@ -0,0 +1,28 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
# Translators: |
|||
# Rodrigo de Almeida Sottomaior Macedo <rmsolucoeseminformatic4@gmail.com>, 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: Rodrigo de Almeida Sottomaior Macedo " |
|||
"<rmsolucoeseminformatic4@gmail.com>, 2017\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" |
|||
|
|||
#. module: web_advanced_search_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "Está em seleção" |
@ -0,0 +1,22 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * web_advanced_search_x2x |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 10.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_x2x |
|||
#. openerp-web |
|||
#: code:addons/web_advanced_search_x2x/static/src/js/web_advanced_search_x2x.js:38 |
|||
#, python-format |
|||
msgid "is in selection" |
|||
msgstr "" |
|||
|
@ -0,0 +1,5 @@ |
|||
* Holger Brunn <hbrunn@therp.nl> |
|||
* Vicent Cubells <vicent.cubells@tecnativa.com> |
|||
* Jairo Llopis <jairo.llopis@tecnativa.com> |
|||
* Rami Alwafaie <rami.alwafaie@initos.com> |
|||
* Jose Mª Bernet <josemaria.bernet@guadaltech.es> |
@ -0,0 +1 @@ |
|||
More powerful and easy to use search, especially for related fields. |
@ -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 |
|||
* Allow to edit individually any facet from current search using the |
|||
advanced domain editor |
|||
* Beautiful, human-readable, domain representation when adding an |
|||
advanced filter |
@ -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. |
After Width: 100 | Height: 100 | Size: 2.0 KiB |
@ -0,0 +1,13 @@ |
|||
.o_search_options { |
|||
.o_filters_menu { |
|||
.o_filter_condition { |
|||
max-width: inherit; |
|||
|
|||
.o_searchview_extended_prop_value { |
|||
.o_field_domain { |
|||
min-width: 30vw; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,86 @@ |
|||
/* Copyright 2018 Tecnativa - Jairo Llopis |
|||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
|
|||
|
|||
odoo.define("web_advanced_search.human_domain", function (require) { |
|||
"use strict"; |
|||
|
|||
var DomainSelector = require("web.DomainSelector"); |
|||
|
|||
var join_mapping = { |
|||
"&": _(" and "), |
|||
"|": _(" or "), |
|||
"!": _(" is not "), |
|||
}; |
|||
|
|||
// HACK I should extend classes, but they are not exposed
|
|||
// TODO Remove file when merged https://github.com/odoo/odoo/pull/25922
|
|||
var human_domain_methods = { |
|||
DomainTree: function () { |
|||
var human_domains = []; |
|||
_.each(this.children, function (child) { |
|||
human_domains.push( |
|||
human_domain_methods[child.template].apply(child) |
|||
); |
|||
}); |
|||
return _.str.sprintf( |
|||
"(%s)", |
|||
human_domains.join(join_mapping[this.operator]) |
|||
); |
|||
}, |
|||
|
|||
DomainSelector: function () { |
|||
var result = human_domain_methods.DomainTree.apply(this, arguments); |
|||
// Remove surrounding parenthesis
|
|||
return result.slice(1, -1); |
|||
}, |
|||
|
|||
DomainLeaf: function () { |
|||
var chain = [], |
|||
operator = this.operator_mapping[this.operator], |
|||
value = _.str.sprintf('"%s"', this.value); |
|||
// Humanize chain
|
|||
this.chain.split(".").forEach(function (element, index) { |
|||
chain.push( |
|||
_.findWhere( |
|||
this.fieldSelector.pages[index], |
|||
{name: element} |
|||
).string || element |
|||
); |
|||
}, this); |
|||
// 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 = _.str.sprintf('["%s"]', this.value.join('", "')); |
|||
} |
|||
return _.str.sprintf( |
|||
"%s %s %s", |
|||
chain.join("→"), |
|||
operator || this.operator, |
|||
value |
|||
).trim(); |
|||
}, |
|||
}; |
|||
|
|||
function getHumanDomain (parent, model, domain, options) { |
|||
var domain_selector = new DomainSelector( |
|||
parent, |
|||
model, |
|||
domain, |
|||
options |
|||
); |
|||
var dummy_parent = $("<div>"); |
|||
domain_selector.appendTo(dummy_parent); |
|||
var result = human_domain_methods.DomainSelector.apply( |
|||
domain_selector |
|||
); |
|||
domain_selector.destroy(); |
|||
dummy_parent.destroy(); |
|||
return result; |
|||
} |
|||
|
|||
return { |
|||
getHumanDomain: getHumanDomain, |
|||
}; |
|||
}); |
@ -0,0 +1,293 @@ |
|||
/* Copyright 2015 Therp BV <http://therp.nl> |
|||
* Copyright 2017-2018 Jairo Llopis <jairo.llopis@tecnativa.com> |
|||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
|
|||
|
|||
odoo.define("web_advanced_search", function (require) { |
|||
"use strict"; |
|||
|
|||
var core = require("web.core"); |
|||
var Domain = require("web.Domain"); |
|||
var DomainSelectorDialog = require("web.DomainSelectorDialog"); |
|||
var field_registry = require("web.field_registry"); |
|||
var FieldManagerMixin = require("web.FieldManagerMixin"); |
|||
var FilterMenu = require("web.FilterMenu"); |
|||
var human_domain = require("web_advanced_search.human_domain"); |
|||
var SearchView = require("web.SearchView"); |
|||
var Widget = require("web.Widget"); |
|||
var Char = core.search_filters_registry.get("char"); |
|||
|
|||
SearchView.include({ |
|||
custom_events: _.extend({}, SearchView.prototype.custom_events, { |
|||
"get_dataset": "_on_get_dataset", |
|||
}), |
|||
|
|||
/** |
|||
* Add or update a `dataset` attribute in event target |
|||
* |
|||
* The search view dataset includes things such as the model, which |
|||
* is required to make some parts of search views smarter. |
|||
* |
|||
* @param {OdooEvent} event The target will get the dataset. |
|||
*/ |
|||
_on_get_dataset: function (event) { |
|||
event.target.dataset = this.dataset; |
|||
event.stopPropagation(); |
|||
}, |
|||
}); |
|||
|
|||
/** |
|||
* An almost dummy search proposition, to use with domain widget |
|||
*/ |
|||
var AdvancedSearchProposition = Widget.extend({ |
|||
init: function (parent, model, domain) { |
|||
this._super(parent); |
|||
this.model = model; |
|||
this.domain = new Domain(domain); |
|||
}, |
|||
|
|||
get_filter: function () { |
|||
var domain_array = this.domain.toArray(); |
|||
return { |
|||
attrs: { |
|||
domain: domain_array, |
|||
// TODO Remove when merged
|
|||
// https://github.com/odoo/odoo/pull/25922
|
|||
string: human_domain.getHumanDomain( |
|||
this, |
|||
this.model, |
|||
domain_array |
|||
), |
|||
}, |
|||
children: [], |
|||
tag: "filter", |
|||
}; |
|||
}, |
|||
}); |
|||
|
|||
// 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", |
|||
}), |
|||
|
|||
init: function () { |
|||
this._super.apply(this, arguments); |
|||
this.trigger_up("get_dataset"); |
|||
}, |
|||
|
|||
/** |
|||
* Open advanced search dialog |
|||
* |
|||
* @returns {$.Deferred} The opening dialog itself. |
|||
*/ |
|||
advanced_search_open: function () { |
|||
var domain_selector_dialog = new DomainSelectorDialog( |
|||
this, |
|||
this.dataset.model, |
|||
"[]", |
|||
{ |
|||
debugMode: core.debug, |
|||
readonly: false, |
|||
} |
|||
); |
|||
// 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"); |
|||
var proposition = new AdvancedSearchProposition( |
|||
this, |
|||
this.dataset.model, |
|||
event.data.domain |
|||
); |
|||
this.propositions = [proposition]; |
|||
this.commit_search(); |
|||
}, |
|||
}); |
|||
|
|||
/** |
|||
* 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. |
|||
*/ |
|||
var Relational = Char.extend(FieldManagerMixin, { |
|||
tagName: "div", |
|||
className: "x2x_container", |
|||
attributes: {}, |
|||
|
|||
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, |
|||
function(op) { |
|||
switch(op.value) { |
|||
case "=": |
|||
return -2; |
|||
case "!=": |
|||
return -1; |
|||
default: |
|||
return 0; |
|||
} |
|||
}); |
|||
// Create dummy record with only the field the user is searching
|
|||
var params = { |
|||
fieldNames: [this.field.name], |
|||
modelName: this.dataset.model, |
|||
context: this.dataset.context, |
|||
// res_id: "virtual_0",
|
|||
fields: {}, |
|||
type: "record", |
|||
viewType: "default", |
|||
fieldsInfo: { |
|||
default: {}, |
|||
}, |
|||
}; |
|||
// See https://stackoverflow.com/a/11508530/1468388
|
|||
params.fields[this.field.name] = _.omit(this.field, "onChange"); |
|||
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; |
|||
}, |
|||
|
|||
start: function () { |
|||
var result = this._super.apply(this, arguments); |
|||
// Render the initial widget
|
|||
result.done($.proxy(this, "show_inputs", $("<input value='='/>"))); |
|||
return result; |
|||
}, |
|||
|
|||
destroy: function () { |
|||
if (this._field_widget) { |
|||
this._field_widget.destroy(); |
|||
} |
|||
this.model.destroy(); |
|||
delete this.record; |
|||
return this._super.apply(this, arguments); |
|||
}, |
|||
|
|||
_get_record: function () { |
|||
return this.model.get(this.datapoint_id); |
|||
}, |
|||
|
|||
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"; |
|||
} |
|||
var _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
|
|||
var 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); |
|||
}, |
|||
|
|||
_applyChanges: function (dataPointID, changes, event) { |
|||
// 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); |
|||
}, |
|||
|
|||
_confirmChange: function (id, fields, event) { |
|||
this.datapoint_id = id; |
|||
return this._field_widget.reset(this._get_record(), event); |
|||
}, |
|||
|
|||
get_value: function () { |
|||
try { |
|||
switch (this._field_widget_name) { |
|||
case "many2one": |
|||
return this._field_widget.value.res_id; |
|||
default: |
|||
return this._field_widget.value.data.display_name; |
|||
} |
|||
} catch (error) { |
|||
if (error.name === "TypeError") { |
|||
return false; |
|||
} |
|||
} |
|||
}, |
|||
|
|||
toString: function () { |
|||
try { |
|||
switch (this._field_widget_name) { |
|||
case "many2one": |
|||
return this._field_widget.value.data.display_name; |
|||
} |
|||
return this._super.apply(this, arguments); |
|||
} catch (error) { |
|||
if (error.name === "TypeError") { |
|||
return ""; |
|||
} |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
// Register search filter widgets
|
|||
core.search_filters_registry |
|||
.add("many2many", Relational) |
|||
.add("many2one", Relational) |
|||
.add("one2many", Relational); |
|||
|
|||
return { |
|||
AdvancedSearchProposition: AdvancedSearchProposition, |
|||
Relational: Relational, |
|||
}; |
|||
}); |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- Copyright 2017-2018 Jairo Llopis <jairo.llopis@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
|||
<templates> |
|||
<t t-extend="SearchView.FilterMenu"> |
|||
<t t-jquery=".o_filters_menu" t-operation="append"> |
|||
<li class="divider"/> |
|||
<li> |
|||
<a class="o_add_advanced_search">Add Advanced Filter</a> |
|||
</li> |
|||
</t> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!-- Copyright 2017-2018 Jairo Llopis <jairo.llopis@tecnativa.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
|||
<odoo> |
|||
|
|||
<template id="assets_backend" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<link rel="stylesheet" href="/web_advanced_search/static/src/css/web_advanced_search.less"/> |
|||
<script type="text/javascript" src="/web_advanced_search/static/src/js/human_domain.js"/> |
|||
<script type="text/javascript" src="/web_advanced_search/static/src/js/web_advanced_search.js"/> |
|||
</xpath> |
|||
</template> |
|||
|
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue