|
|
|
@@ -393,6 +393,90 @@ openerp.base.DataRecord = openerp.base.Controller.extend({
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Base class for widgets. Handle rendering (based on a QWeb template), identifier
|
|
|
|
|
* generation, parenting and destruction of the widget.
|
|
|
|
|
*/
|
|
|
|
|
openerp.base.BaseWidget = openerp.base.Controller.extend({
|
|
|
|
|
/**
|
|
|
|
|
* The name of the QWeb template that will be used for rendering. Must be redifined
|
|
|
|
|
* in subclasses or the render() method can not be used.
|
|
|
|
|
*
|
|
|
|
|
* @type string
|
|
|
|
|
*/
|
|
|
|
|
template: null,
|
|
|
|
|
/**
|
|
|
|
|
* The prefix used to generate an id automatically. Should be redifined in subclasses.
|
|
|
|
|
* If it is not defined, a default identifier will be used.
|
|
|
|
|
*
|
|
|
|
|
* @type string
|
|
|
|
|
*/
|
|
|
|
|
identifier_prefix: 'generic-identifier',
|
|
|
|
|
/**
|
|
|
|
|
* Contructor. Also initialize the identifier.
|
|
|
|
|
*
|
|
|
|
|
* @params {openerp.base.search.BaseWidget} parent The parent widget.
|
|
|
|
|
*/
|
|
|
|
|
init: function (parent) {
|
|
|
|
|
this.children = [];
|
|
|
|
|
this.parent = parent;
|
|
|
|
|
if(parent != null) {
|
|
|
|
|
parent.children.push(this);
|
|
|
|
|
}
|
|
|
|
|
this.make_id(this.identifier_prefix);
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* Sets and returns a globally unique identifier for the widget.
|
|
|
|
|
*
|
|
|
|
|
* If a prefix is appended, the identifier will be appended to it.
|
|
|
|
|
*
|
|
|
|
|
* @params sections prefix sections, empty/falsy sections will be removed
|
|
|
|
|
*/
|
|
|
|
|
make_id: function () {
|
|
|
|
|
this.element_id = _.uniqueId(_.toArray(arguments).join('_'));
|
|
|
|
|
return this.element_id;
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* "Starts" the widgets. Called at the end of the rendering, this allows
|
|
|
|
|
* to get a jQuery object referring to the DOM ($element attribute).
|
|
|
|
|
*/
|
|
|
|
|
start: function () {
|
|
|
|
|
this._super();
|
|
|
|
|
var tmp = document.getElementById(this.element_id)
|
|
|
|
|
this.$element = tmp != null ? $(tmp) : null;
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* "Stops" the widgets. Called when the view destroys itself, this
|
|
|
|
|
* lets the widgets clean up after themselves.
|
|
|
|
|
*/
|
|
|
|
|
stop: function () {
|
|
|
|
|
var tmp_children = this.children;
|
|
|
|
|
this.children = [];
|
|
|
|
|
_.each(tmp_children, function(x) {
|
|
|
|
|
x.stop();
|
|
|
|
|
});
|
|
|
|
|
if(this.$element != null) {
|
|
|
|
|
this.$element.remove();
|
|
|
|
|
}
|
|
|
|
|
if(this.parent != null) {
|
|
|
|
|
var _this = this;
|
|
|
|
|
this.parent.children = _.reject(this.parent.children, function(x) { return x === _this;});
|
|
|
|
|
this.parent = null;
|
|
|
|
|
}
|
|
|
|
|
this._super();
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* Render the widget. This.template must be defined.
|
|
|
|
|
* The content of the current object is passed as context to the template.
|
|
|
|
|
*
|
|
|
|
|
* @param {object} additional Additional context arguments to pass to the template.
|
|
|
|
|
*/
|
|
|
|
|
render: function (additional) {
|
|
|
|
|
return QWeb.render(this.template, _.extend({}, this,
|
|
|
|
|
additional != null ? additional : {}));
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
openerp.base.SearchView = openerp.base.Controller.extend({
|
|
|
|
|
init: function(session, element_id, dataset, view_id, defaults) {
|
|
|
|
|
this._super(session, element_id);
|
|
|
|
@@ -514,6 +598,11 @@ openerp.base.SearchView = openerp.base.Controller.extend({
|
|
|
|
|
data.fields_view['arch'].children,
|
|
|
|
|
data.fields_view.fields);
|
|
|
|
|
|
|
|
|
|
// for extended search view
|
|
|
|
|
var ext = new openerp.base.search.ExtendedSearch(null, data.fields_view.fields);
|
|
|
|
|
lines.push([ext]);
|
|
|
|
|
this.inputs.push(ext);
|
|
|
|
|
|
|
|
|
|
var render = QWeb.render("SearchView", {
|
|
|
|
|
'view': data.fields_view['arch'],
|
|
|
|
|
'lines': lines,
|
|
|
|
@@ -714,6 +803,13 @@ openerp.base.search.FilterGroup = openerp.base.search.Widget.extend({
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
openerp.base.search.add_expand_listener = function($root) {
|
|
|
|
|
$root.find('a.searchview_group_string').click(function (e) {
|
|
|
|
|
$root.toggleClass('folded expanded');
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
openerp.base.search.Group = openerp.base.search.Widget.extend({
|
|
|
|
|
template: 'SearchView.group',
|
|
|
|
|
// TODO: contain stuff
|
|
|
|
@@ -731,14 +827,185 @@ openerp.base.search.Group = openerp.base.search.Widget.extend({
|
|
|
|
|
.chain()
|
|
|
|
|
.flatten()
|
|
|
|
|
.each(function (widget) { widget.start(); });
|
|
|
|
|
var $root = this.$element;
|
|
|
|
|
$root.find('a.searchview_group_string').click(function (e) {
|
|
|
|
|
$root.toggleClass('folded expanded');
|
|
|
|
|
openerp.base.search.add_expand_listener(this.$element);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
openerp.base.search.ExtendedSearch = openerp.base.BaseWidget.extend({
|
|
|
|
|
template: 'SearchView.extended_search',
|
|
|
|
|
identifier_prefix: 'extended-search',
|
|
|
|
|
init: function (parent, fields) {
|
|
|
|
|
this._super(parent);
|
|
|
|
|
this.fields = fields;
|
|
|
|
|
},
|
|
|
|
|
add_group: function(group) {
|
|
|
|
|
var group = new openerp.base.search.ExtendedSearchGroup(this, this.fields);
|
|
|
|
|
var render = group.render({});
|
|
|
|
|
this.$element.find('.searchview_extended_groups_list').append(render);
|
|
|
|
|
group.start();
|
|
|
|
|
},
|
|
|
|
|
start: function () {
|
|
|
|
|
this._super();
|
|
|
|
|
var _this = this;
|
|
|
|
|
openerp.base.search.add_expand_listener(this.$element);
|
|
|
|
|
this.add_group();
|
|
|
|
|
this.$element.find('.searchview_extended_add_group').click(function (e) {
|
|
|
|
|
_this.add_group();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
get_context: function() {
|
|
|
|
|
return null;
|
|
|
|
|
},
|
|
|
|
|
get_domain: function() {
|
|
|
|
|
if(this.$element.hasClass("folded")) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
var domain = _.reduce(this.children,
|
|
|
|
|
function(mem, x) { return mem.concat(x.get_domain());}, []);
|
|
|
|
|
return domain;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
openerp.base.search.ExtendedSearchGroup = openerp.base.BaseWidget.extend({
|
|
|
|
|
template: 'SearchView.extended_search.group',
|
|
|
|
|
identifier_prefix: 'extended-search-group',
|
|
|
|
|
init: function (parent, fields) {
|
|
|
|
|
this._super(parent);
|
|
|
|
|
this.fields = fields;
|
|
|
|
|
},
|
|
|
|
|
add_prop: function() {
|
|
|
|
|
var prop = new openerp.base.search.ExtendedSearchProposition(this, this.fields);
|
|
|
|
|
var render = prop.render({});
|
|
|
|
|
this.$element.find('.searchview_extended_propositions_list').append(render);
|
|
|
|
|
prop.start();
|
|
|
|
|
},
|
|
|
|
|
start: function () {
|
|
|
|
|
this._super();
|
|
|
|
|
var _this = this;
|
|
|
|
|
this.add_prop();
|
|
|
|
|
this.$element.find('.searchview_extended_add_proposition').click(function (e) {
|
|
|
|
|
_this.add_prop();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
var delete_btn = this.$element.find('.searchview_extended_delete_group');
|
|
|
|
|
delete_btn.click(function (e) {
|
|
|
|
|
_this.stop();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
get_domain: function() {
|
|
|
|
|
var props = _(this.children).chain().map(function(x) {
|
|
|
|
|
return x.get_proposition();
|
|
|
|
|
}).compact().value();
|
|
|
|
|
var choice = this.$element.find(".searchview_extended_group_choice").val();
|
|
|
|
|
var op = choice == "all" ? "&" : "|";
|
|
|
|
|
var domain = [].concat(choice == "none" ? ['!'] : [],
|
|
|
|
|
_.map(_.range(_.max([0,props.length - 1])), function(x) { return op; }),
|
|
|
|
|
props);
|
|
|
|
|
return domain;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
openerp.base.search.extended_filters_types = {
|
|
|
|
|
char: {
|
|
|
|
|
operators: [
|
|
|
|
|
{value: "ilike", text: "contains"},
|
|
|
|
|
{value: "not like", text: "doesn't contain"},
|
|
|
|
|
{value: "=", text: "is equal to"},
|
|
|
|
|
{value: "!=", text: "is not equal to"},
|
|
|
|
|
{value: ">", text: "greater than"},
|
|
|
|
|
{value: "<", text: "less than"},
|
|
|
|
|
{value: ">=", text: "greater or equal than"},
|
|
|
|
|
{value: "<=", text: "less or equal than"},
|
|
|
|
|
],
|
|
|
|
|
build_component: function(parent) {
|
|
|
|
|
return new openerp.base.search.ExtendedSearchProposition.Char(parent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
openerp.base.search.ExtendedSearchProposition = openerp.base.BaseWidget.extend({
|
|
|
|
|
template: 'SearchView.extended_search.proposition',
|
|
|
|
|
identifier_prefix: 'extended-search-proposition',
|
|
|
|
|
init: function (parent, fields) {
|
|
|
|
|
this._super(parent);
|
|
|
|
|
this.fields = _(fields).chain()
|
|
|
|
|
.map(function(val,key) {return {name:key, obj:val};})
|
|
|
|
|
.sortBy(function(x) {return x.obj.string;}).value();
|
|
|
|
|
this.attrs = {_: _, fields: this.fields, selected: null};
|
|
|
|
|
this.value_component = null;
|
|
|
|
|
},
|
|
|
|
|
start: function () {
|
|
|
|
|
this._super();
|
|
|
|
|
this.set_selected(this.fields.length > 0 ? this.fields[0] : null);
|
|
|
|
|
var _this = this;
|
|
|
|
|
this.$element.find(".searchview_extended_prop_field").change(function(e) {
|
|
|
|
|
_this.changed();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
var delete_btn = this.$element.find('.searchview_extended_delete_prop');
|
|
|
|
|
delete_btn.click(function (e) {
|
|
|
|
|
_this.stop();
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
changed: function() {
|
|
|
|
|
var nval = this.$element.find(".searchview_extended_prop_field").val();
|
|
|
|
|
if(this.attrs.selected == null || nval != this.attrs.selected.name) {
|
|
|
|
|
this.set_selected(_.detect(this.fields, function(x) {return x.name == nval;}));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
set_selected: function(selected) {
|
|
|
|
|
var _this = this;
|
|
|
|
|
if(this.attrs.selected != null) {
|
|
|
|
|
this.value_component.stop();
|
|
|
|
|
this.value_component = null;
|
|
|
|
|
this.$element.find('.searchview_extended_prop_op').html('');
|
|
|
|
|
}
|
|
|
|
|
this.attrs.selected = selected;
|
|
|
|
|
if(selected == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var type = selected.obj.type;
|
|
|
|
|
var extended_filters_types = openerp.base.search.extended_filters_types;
|
|
|
|
|
type = type in extended_filters_types ? type : "char";
|
|
|
|
|
_.each(extended_filters_types[type].operators, function(operator) {
|
|
|
|
|
option = jQuery('<option/>');
|
|
|
|
|
option.attr('value', operator.value);
|
|
|
|
|
option.text(operator.text);
|
|
|
|
|
option.appendTo(_this.$element.find('.searchview_extended_prop_op'));
|
|
|
|
|
});
|
|
|
|
|
this.value_component = extended_filters_types[type].build_component(this);
|
|
|
|
|
var render = this.value_component.render({});
|
|
|
|
|
this.$element.find('.searchview_extended_prop_value').html(render);
|
|
|
|
|
this.value_component.start();
|
|
|
|
|
},
|
|
|
|
|
get_proposition: function() {
|
|
|
|
|
if ( this.attrs.selected == null)
|
|
|
|
|
return null;
|
|
|
|
|
var field = this.attrs.selected.name;
|
|
|
|
|
var op = this.$element.find('.searchview_extended_prop_op').val();
|
|
|
|
|
var value = this.value_component.get_value();
|
|
|
|
|
return [field, op, value];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
openerp.base.search.ExtendedSearchProposition.Char = openerp.base.BaseWidget.extend({
|
|
|
|
|
template: 'SearchView.extended_search.proposition.char',
|
|
|
|
|
identifier_prefix: 'extended-search-proposition-char',
|
|
|
|
|
|
|
|
|
|
get_value: function() {
|
|
|
|
|
var val = this.$element.val();
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
openerp.base.search.Input = openerp.base.search.Widget.extend({
|
|
|
|
|
init: function (view) {
|
|
|
|
|
this._super(view);
|
|
|
|
@@ -1073,6 +1340,8 @@ openerp.base.ListView = openerp.base.Controller.extend({
|
|
|
|
|
openerp.base.TreeView = openerp.base.Controller.extend({
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openerp.base.Widget = openerp.base.Controller.extend({
|
|
|
|
|
// TODO Change this to init: function(view, node) { and use view.session and a new element_id for the super
|
|
|
|
|
// it means that widgets are special controllers
|
|
|
|
|