[IMP] web: add more filtering and sorting options on ModelFieldSelector
A new `filter` option has been added to filter fields with an optional function. A new `order` option has been added to sort displayed fields. The `followRelations` options have also been extended to take a function.
This commit is contained in:
@@ -53,7 +53,11 @@ var ModelFieldSelector = Widget.extend({
|
||||
* @param {string} model - the model name (e.g. "res.partner")
|
||||
* @param {string[]} chain - list of the initial field chain parts
|
||||
* @param {Object} [options] - some key-value options
|
||||
* @param {string} [options.order='string']
|
||||
* an ordering key for displayed fields
|
||||
* @param {boolean} [options.readonly=true] - true if should be readonly
|
||||
* @param {function} [options.filter]
|
||||
* a function to filter the fetched fields
|
||||
* @param {Object} [options.filters]
|
||||
* some key-value options to filter the fetched fields
|
||||
* @param {boolean} [options.filters.searchable=true]
|
||||
@@ -62,7 +66,7 @@ var ModelFieldSelector = Widget.extend({
|
||||
* the list of fields info to use when no relation has
|
||||
* been followed (null indicates the widget has to request
|
||||
* the fields itself)
|
||||
* @param {boolean} [options.followRelations=true]
|
||||
* @param {boolean|function} [options.followRelations=true]
|
||||
* true if can follow relation when building the chain
|
||||
* @param {boolean} [options.debugMode=false]
|
||||
* true if the widget is in debug mode, false otherwise
|
||||
@@ -73,9 +77,11 @@ var ModelFieldSelector = Widget.extend({
|
||||
this.model = model;
|
||||
this.chain = chain;
|
||||
this.options = _.extend({
|
||||
order: 'string',
|
||||
readonly: true,
|
||||
filters: {},
|
||||
fields: null,
|
||||
filter: function () {return true;},
|
||||
followRelations: true,
|
||||
debugMode: false,
|
||||
}, options || {});
|
||||
@@ -83,6 +89,12 @@ var ModelFieldSelector = Widget.extend({
|
||||
searchable: true,
|
||||
}, this.options.filters);
|
||||
|
||||
if (typeof this.options.followRelations !== 'function') {
|
||||
this.options.followRelations = this.options.followRelations ?
|
||||
function () {return true;} :
|
||||
function () {return false;};
|
||||
}
|
||||
|
||||
this.pages = [];
|
||||
this.dirty = false;
|
||||
|
||||
@@ -192,6 +204,7 @@ var ModelFieldSelector = Widget.extend({
|
||||
* non-technical names
|
||||
*/
|
||||
_getModelFieldsFromCache: function (model, filters) {
|
||||
var self = this;
|
||||
var def = modelFieldsCache.cacheDefs[model];
|
||||
if (!def) {
|
||||
def = modelFieldsCache.cacheDefs[model] = this._rpc({
|
||||
@@ -204,12 +217,12 @@ var ModelFieldSelector = Widget.extend({
|
||||
context: this.getSession().user_context,
|
||||
})
|
||||
.then((function (fields) {
|
||||
modelFieldsCache.cache[model] = sortFields(fields, model);
|
||||
modelFieldsCache.cache[model] = sortFields(fields, model, self.options.order);
|
||||
}).bind(this));
|
||||
}
|
||||
return def.then((function () {
|
||||
return _.filter(modelFieldsCache.cache[model], function (f) {
|
||||
return !filters.searchable || f.searchable;
|
||||
return (!filters.searchable || f.searchable) && self.options.filter(f);
|
||||
});
|
||||
}).bind(this));
|
||||
},
|
||||
@@ -299,7 +312,7 @@ var ModelFieldSelector = Widget.extend({
|
||||
_pushPageData: function (model) {
|
||||
var def;
|
||||
if (this.model === model && this.options.fields) {
|
||||
def = $.when(sortFields(this.options.fields, model));
|
||||
def = $.when(sortFields(this.options.fields, model, this.options.order));
|
||||
} else {
|
||||
def = this._getModelFieldsFromCache(model, this.options.filters);
|
||||
}
|
||||
@@ -345,7 +358,7 @@ var ModelFieldSelector = Widget.extend({
|
||||
}
|
||||
this.$(".o_field_selector_popover_header .o_field_selector_title").text(title);
|
||||
this.$(".o_field_selector_page").replaceWith(core.qweb.render(this.template + ".page", {
|
||||
lines: page,
|
||||
lines: _.filter(page, this.options.filter),
|
||||
followRelations: this.options.followRelations,
|
||||
debug: this.options.debugMode,
|
||||
}));
|
||||
@@ -544,16 +557,18 @@ return ModelFieldSelector;
|
||||
* contain additional keys "model" and "name" with the field
|
||||
* name)
|
||||
*/
|
||||
function sortFields(fields, model) {
|
||||
return _.chain(fields)
|
||||
function sortFields(fields, model, order) {
|
||||
var array = _.chain(fields)
|
||||
.pairs()
|
||||
.sortBy(function (p) { return p[1].string; })
|
||||
.map(function (p) {
|
||||
.sortBy(function (p) { return p[1].string; });
|
||||
if (order !== 'string') {
|
||||
array = array.sortBy(function (p) {return p[1][order]; });
|
||||
}
|
||||
return array.map(function (p) {
|
||||
return _.extend({
|
||||
name: p[0],
|
||||
model: model,
|
||||
}, p[1]);
|
||||
})
|
||||
.value();
|
||||
}).value();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -771,7 +771,7 @@
|
||||
</t>
|
||||
<ul t-name="ModelFieldSelector.page" class="o_field_selector_page">
|
||||
<t t-foreach="lines" t-as="line">
|
||||
<t t-set="relationToFollow" t-value="followRelations && line.relation"/>
|
||||
<t t-set="relationToFollow" t-value="followRelations(line) && line.relation"/>
|
||||
<li t-attf-class="o_field_selector_item #{relationToFollow and 'o_field_selector_next_page' or 'o_field_selector_select_button'}#{line_index == 0 and ' active' or ''}"
|
||||
t-att-data-name="line.name">
|
||||
<t t-esc="line.string"/>
|
||||
|
||||
@@ -167,6 +167,30 @@ QUnit.module('ModelFieldSelector', {
|
||||
}).join(" -> ");
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test("use the filter option", function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
var $target = $("#qunit-fixture");
|
||||
|
||||
// Create the field selector and its mock environment
|
||||
var fieldSelector = new ModelFieldSelector(null, "partner", [], {
|
||||
readonly: false,
|
||||
filter: function (field) {
|
||||
return field.type === 'many2one';
|
||||
},
|
||||
});
|
||||
testUtils.addMockEnvironment(fieldSelector, {data: this.data});
|
||||
fieldSelector.appendTo($target);
|
||||
|
||||
fieldSelector.$el.trigger('focusin');
|
||||
var $fieldSelectorPopover = fieldSelector.$(".o_field_selector_popover:visible");
|
||||
var $lis = $fieldSelectorPopover.find("li");
|
||||
assert.strictEqual($lis.length, 1, "there should only be one element");
|
||||
assert.strictEqual($lis.text().trim(), "Product", "the available field should be the many2one");
|
||||
|
||||
fieldSelector.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user