|
@ -1,30 +1,45 @@ |
|
|
/* Copyright 2015 Therp BV <http://therp.nl> |
|
|
/* Copyright 2015 Therp BV <http://therp.nl> |
|
|
* Copyright 2017 Jairo Llopis <jairo.llopis@tecnativa.com> |
|
|
* Copyright 2017 Jairo Llopis <jairo.llopis@tecnativa.com> |
|
|
|
|
|
* Copyright 2018 Jose Mª Bernet <josemaria.bernet@guadaltech.es> |
|
|
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
|
|
|
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
|
|
|
|
|
|
|
|
|
odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
|
|
|
|
|
|
odoo.define('web_advanced_search_x2x', function (require) { |
|
|
"use strict"; |
|
|
"use strict"; |
|
|
|
|
|
|
|
|
require('web.form_relational'); |
|
|
|
|
|
require('web.form_widgets'); |
|
|
|
|
|
var search_filters = require('web.search_filters'); |
|
|
|
|
|
var form_common = require('web.form_common'); |
|
|
|
|
|
var SearchView = require('web.SearchView'); |
|
|
|
|
|
var data = require('web.data'); |
|
|
|
|
|
var core = require('web.core'); |
|
|
var core = require('web.core'); |
|
|
var pyeval = require('web.pyeval'); |
|
|
|
|
|
|
|
|
var DomainSelector = require('web.DomainSelector'); |
|
|
|
|
|
var Domain = require("web.Domain"); |
|
|
|
|
|
var FieldManagerMixin = require('web.FieldManagerMixin'); |
|
|
|
|
|
var Char = core.search_filters_registry.get("char"); |
|
|
|
|
|
|
|
|
var X2XAdvancedSearchPropositionMixin = { |
|
|
var X2XAdvancedSearchPropositionMixin = { |
|
|
template: "web_advanced_search_x2x.proposition", |
|
|
template: "web_advanced_search_x2x.proposition", |
|
|
|
|
|
events: { |
|
|
|
|
|
// If click on the node add or delete button, notify the parent and let
|
|
|
|
|
|
// it handle the addition/removal
|
|
|
|
|
|
"click .o_domain_tree_operator_caret": "_openCaret" |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
init: function () { |
|
|
|
|
|
|
|
|
_openCaret: function (e) { |
|
|
|
|
|
var selectorClass = $('.o_domain_tree_operator_selector'); |
|
|
|
|
|
if (selectorClass.hasClass('open')) { |
|
|
|
|
|
selectorClass.removeClass('open'); |
|
|
|
|
|
} else { |
|
|
|
|
|
selectorClass.addClass('open'); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
init: function (parent, options) { |
|
|
// Make equal and not equal appear 1st and 2nd
|
|
|
// Make equal and not equal appear 1st and 2nd
|
|
|
|
|
|
this.relation = options.relation; |
|
|
|
|
|
this.type = options.type; |
|
|
|
|
|
this.field_name = options.name; |
|
|
|
|
|
this.name = parent.name; |
|
|
|
|
|
|
|
|
this.operators = _.sortBy( |
|
|
this.operators = _.sortBy( |
|
|
this.operators, |
|
|
this.operators, |
|
|
function(op) |
|
|
|
|
|
{ |
|
|
|
|
|
switch(op.value) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
function (op) { |
|
|
|
|
|
switch (op.value) { |
|
|
case '=': |
|
|
case '=': |
|
|
return -2; |
|
|
return -2; |
|
|
case '!=': |
|
|
case '!=': |
|
@ -33,6 +48,7 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
// Append domain operator
|
|
|
// Append domain operator
|
|
|
this.operators.push({ |
|
|
this.operators.push({ |
|
|
'value': 'domain', 'text': core._lt('is in selection'), |
|
|
'value': 'domain', 'text': core._lt('is in selection'), |
|
@ -41,27 +57,22 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
this.events = $.extend({}, this.events, { |
|
|
this.events = $.extend({}, this.events, { |
|
|
click: function (event) { |
|
|
click: function (event) { |
|
|
event.stopPropagation(); |
|
|
event.stopPropagation(); |
|
|
}, |
|
|
|
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
return this._super.apply(this, arguments); |
|
|
return this._super.apply(this, arguments); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
get_field_desc: function() |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
get_field_desc: function () { |
|
|
return this.field; |
|
|
return this.field; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Add x2x widget after rendering. |
|
|
* Add x2x widget after rendering. |
|
|
*/ |
|
|
*/ |
|
|
renderElement: function() { |
|
|
|
|
|
|
|
|
renderElement: function () { |
|
|
var result = this._super.apply(this, arguments); |
|
|
var result = this._super.apply(this, arguments); |
|
|
if (this.x2x_widget_name()) { |
|
|
if (this.x2x_widget_name()) { |
|
|
this.x2x_field().appendTo(this.$el); |
|
|
this.x2x_field().appendTo(this.$el); |
|
|
this._x2x_field.$el.on( |
|
|
|
|
|
"autocompleteopen", |
|
|
|
|
|
this.proxy('x2x_autocomplete_open') |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
} |
|
|
return result; |
|
|
return result; |
|
|
}, |
|
|
}, |
|
@ -86,44 +97,12 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
} |
|
|
} |
|
|
var widget = this.x2x_widget(); |
|
|
var widget = this.x2x_widget(); |
|
|
if (!widget) return; |
|
|
if (!widget) return; |
|
|
|
|
|
|
|
|
var field_domain = this.field.domain; |
|
|
|
|
|
if (typeof field_domain === 'string') { |
|
|
|
|
|
try { |
|
|
|
|
|
pyeval.eval('domain', field_domain); |
|
|
|
|
|
} catch(e) { |
|
|
|
|
|
this.field.domain = "[]"; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._x2x_field = new widget( |
|
|
|
|
|
this, |
|
|
|
|
|
this.x2x_field_create_options() |
|
|
|
|
|
); |
|
|
|
|
|
this._x2x_field.on( |
|
|
|
|
|
"domain_selected", |
|
|
|
|
|
this, |
|
|
|
|
|
this.proxy("x2x_value_changed") |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
this._x2x_field = new DomainSelector(this, this.relation, [], {readonly: false}); |
|
|
return this._x2x_field; |
|
|
return this._x2x_field; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
x2x_field_create_options: function () { |
|
|
|
|
|
return { |
|
|
|
|
|
attrs: { |
|
|
|
|
|
name: this.field.name, |
|
|
|
|
|
options: JSON.stringify({ |
|
|
|
|
|
no_create: true, |
|
|
|
|
|
no_open: true, |
|
|
|
|
|
model: this.field.relation, |
|
|
|
|
|
}), |
|
|
|
|
|
}, |
|
|
|
|
|
}; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
x2x_value_changed: function () { |
|
|
x2x_value_changed: function () { |
|
|
switch (this.x2x_widget_name()) { |
|
|
switch (this.x2x_widget_name()) { |
|
|
case "char_domain": |
|
|
|
|
|
|
|
|
case "char": |
|
|
// Apply domain when selected
|
|
|
// Apply domain when selected
|
|
|
this.getParent().getParent().commit_search(); |
|
|
this.getParent().getParent().commit_search(); |
|
|
break; |
|
|
break; |
|
@ -132,7 +111,7 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
|
|
|
|
|
|
x2x_widget: function () { |
|
|
x2x_widget: function () { |
|
|
var name = this.x2x_widget_name(); |
|
|
var name = this.x2x_widget_name(); |
|
|
return name && core.form_widget_registry.get(name); |
|
|
|
|
|
|
|
|
return name && core.search_filters_registry.get(name); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -141,41 +120,29 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
* If it returns `undefined`, it means you should use a simple |
|
|
* If it returns `undefined`, it means you should use a simple |
|
|
* `<input type="text"/>`. |
|
|
* `<input type="text"/>`. |
|
|
*/ |
|
|
*/ |
|
|
|
|
|
|
|
|
x2x_widget_name: function () { |
|
|
x2x_widget_name: function () { |
|
|
switch (this.get_operator()) { |
|
|
switch (this.get_operator()) { |
|
|
case "=": |
|
|
case "=": |
|
|
case "!=": |
|
|
case "!=": |
|
|
return "many2one"; |
|
|
|
|
|
|
|
|
return undefined; |
|
|
case "domain": |
|
|
case "domain": |
|
|
return "char_domain"; |
|
|
|
|
|
|
|
|
return "many2one"; |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
x2x_autocomplete_open: function() |
|
|
|
|
|
{ |
|
|
|
|
|
var widget = this._x2x_field.$input.autocomplete("widget"); |
|
|
|
|
|
widget.on('click', 'li', function(event) { |
|
|
|
|
|
event.stopPropagation(); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
get_domain: function () { |
|
|
get_domain: function () { |
|
|
// Special way to get domain if user chose "domain" filter
|
|
|
// Special way to get domain if user chose "domain" filter
|
|
|
if (this.get_operator() == "domain") { |
|
|
if (this.get_operator() == "domain") { |
|
|
var value = this._x2x_field.get_value(); |
|
|
|
|
|
var domain = new data.CompoundDomain(), |
|
|
|
|
|
name = this.field.name; |
|
|
|
|
|
$.map(value, function (el) { |
|
|
|
|
|
var leaf = el; |
|
|
|
|
|
if (typeof el !== "string") { |
|
|
|
|
|
leaf = [ |
|
|
|
|
|
_.str.sprintf("%s.%s", name, el[0]), |
|
|
|
|
|
el[1], |
|
|
|
|
|
el[2], |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
var domain = this._x2x_field.getDomain(); |
|
|
|
|
|
var field_name = this.field_name; |
|
|
|
|
|
|
|
|
|
|
|
$.each(domain, function (index, value) { |
|
|
|
|
|
if (domain[index].constructor == Array) { |
|
|
|
|
|
domain[index][0] = field_name + '.' + domain[index][0] |
|
|
} |
|
|
} |
|
|
domain.add([leaf]); |
|
|
|
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
return domain; |
|
|
return domain; |
|
|
} else { |
|
|
} else { |
|
|
return this._super.apply(this, arguments); |
|
|
return this._super.apply(this, arguments); |
|
@ -192,37 +159,17 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
if (!this.x2x_widget_name()) { |
|
|
if (!this.x2x_widget_name()) { |
|
|
throw "No x2x widget, fallback to default"; |
|
|
throw "No x2x widget, fallback to default"; |
|
|
} |
|
|
} |
|
|
return this._x2x_field.get_value(); |
|
|
|
|
|
|
|
|
var domain = this._x2x_field.getDomain(); |
|
|
|
|
|
return Domain.prototype.arrayToString(domain) |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
return this._super.apply(this, arguments); |
|
|
return this._super.apply(this, arguments); |
|
|
} |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
format_label: function (format, field, operator) { |
|
|
|
|
|
if (this.x2x_widget()) { |
|
|
|
|
|
var value = String(this._x2x_field.get_value()); |
|
|
|
|
|
if (this._x2x_field.display_value) { |
|
|
|
|
|
value = this._x2x_field.display_value[value]; |
|
|
|
|
|
} |
|
|
} |
|
|
return _.str.sprintf( |
|
|
|
|
|
format, |
|
|
|
|
|
{ |
|
|
|
|
|
field: field.string, |
|
|
|
|
|
operator: operator.label || operator.text, |
|
|
|
|
|
value: value, |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
} else { |
|
|
|
|
|
return this._super.apply(this, arguments); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
var ExtendedSearchProposition = search_filters.ExtendedSearchProposition, |
|
|
|
|
|
Char = ExtendedSearchProposition.Char, |
|
|
|
|
|
affected_types = ["one2many", "many2one", "many2many"], |
|
|
|
|
|
|
|
|
var affected_types = ["one2many", "many2one", "many2many"], |
|
|
X2XAdvancedSearchProposition = Char.extend( |
|
|
X2XAdvancedSearchProposition = Char.extend( |
|
|
form_common.FieldManagerMixin, |
|
|
|
|
|
|
|
|
FieldManagerMixin, |
|
|
X2XAdvancedSearchPropositionMixin |
|
|
X2XAdvancedSearchPropositionMixin |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
@ -231,50 +178,6 @@ odoo.define('web_advanced_search_x2x.search_filters', function (require) { |
|
|
core.search_filters_registry.add(value, X2XAdvancedSearchProposition); |
|
|
core.search_filters_registry.add(value, X2XAdvancedSearchProposition); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
SearchView.include({ |
|
|
|
|
|
build_search_data: function() |
|
|
|
|
|
{ |
|
|
|
|
|
//Advanced.commit_search can only cope with propositions
|
|
|
|
|
|
//(=domain leaves),
|
|
|
|
|
|
//so we need to rebuild the domain if one of our CompoundDomains
|
|
|
|
|
|
//is involved
|
|
|
|
|
|
var result = this._super.apply(this, arguments); |
|
|
|
|
|
_.each(result.domains, function(domain, index) |
|
|
|
|
|
{ |
|
|
|
|
|
if(!_.isArray(domain)) |
|
|
|
|
|
{ |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
var compound_domains = [], leaves = []; |
|
|
|
|
|
_.each(domain, function(leaf) |
|
|
|
|
|
{ |
|
|
|
|
|
if(leaf instanceof data.CompoundDomain) |
|
|
|
|
|
{ |
|
|
|
|
|
compound_domains.push(leaf); |
|
|
|
|
|
} |
|
|
|
|
|
if(_.isArray(leaf)) |
|
|
|
|
|
{ |
|
|
|
|
|
leaves.push(leaf); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
if(compound_domains.length) |
|
|
|
|
|
{ |
|
|
|
|
|
var combined = new data.CompoundDomain(); |
|
|
|
|
|
_.each(compound_domains, function(domain) |
|
|
|
|
|
{ |
|
|
|
|
|
combined.add(domain.eval()); |
|
|
|
|
|
}); |
|
|
|
|
|
_.each(leaves, function(leaf) |
|
|
|
|
|
{ |
|
|
|
|
|
combined.add([leaf]); |
|
|
|
|
|
}); |
|
|
|
|
|
result.domains[index] = combined; |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
return result; |
|
|
|
|
|
}, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
|
X2XAdvancedSearchPropositionMixin: X2XAdvancedSearchPropositionMixin, |
|
|
X2XAdvancedSearchPropositionMixin: X2XAdvancedSearchPropositionMixin, |
|
|
X2XAdvancedSearchProposition: X2XAdvancedSearchProposition, |
|
|
X2XAdvancedSearchProposition: X2XAdvancedSearchProposition, |
|
|