[TEST] rendering of drawer
bzr revid: xmo@openerp.com-20120427150436-3wxgyyp59l5vefr5
This commit is contained in:
parent
661eddb330
commit
1f0b1673e2
|
@ -249,69 +249,10 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
/**
|
||||
* Sets up thingie where all the mess is put?
|
||||
*/
|
||||
setup_stuff_drawer: function () {
|
||||
var self = this;
|
||||
$('<div class="oe_searchview_unfold_drawer">').appendTo(this.$element);
|
||||
var $drawer = $('<div class="oe_searchview_drawer">').appendTo(this.$element);
|
||||
var $filters = $('<div class="oe_searchview_filters">').appendTo($drawer);
|
||||
|
||||
var running_count = 0;
|
||||
// get total filters count
|
||||
var is_group = function (i) { return i instanceof instance.web.search.FilterGroup; };
|
||||
var filters_count = _(this.controls).chain()
|
||||
.flatten()
|
||||
.filter(is_group)
|
||||
.map(function (i) { return i.filters.length; })
|
||||
.sum()
|
||||
.value();
|
||||
|
||||
var col1 = [], col2 = _(this.controls).map(function (inputs, group) {
|
||||
var filters = _(inputs).filter(is_group);
|
||||
return {
|
||||
name: group === 'null' ? _t("Filters") : group,
|
||||
filters: filters,
|
||||
length: _(filters).chain().map(function (i) {
|
||||
return i.filters.length; }).sum().value()
|
||||
};
|
||||
select_for_drawer: function () {
|
||||
return _(this.inputs).filter(function (input) {
|
||||
return input.in_drawer();
|
||||
});
|
||||
|
||||
while (col2.length) {
|
||||
// col1 + group should be smaller than col2 + group
|
||||
if ((running_count + col2[0].length) <= (filters_count - running_count)) {
|
||||
running_count += col2[0].length;
|
||||
col1.push(col2.shift());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a Custom Filter FilterGroup for each custom filter read from
|
||||
// the db, add all of this as a group in the smallest column
|
||||
[].push.call(col1.length <= col2.length ? col1 : col2, {
|
||||
name: _t("Custom Filters"),
|
||||
filters: _.map(this.custom_filters, function (filter) {
|
||||
// FIXME: handling of ``disabled`` being set
|
||||
var f = new instance.web.search.Filter({attrs: {
|
||||
string: filter.name,
|
||||
context: filter.context,
|
||||
domain: filter.domain
|
||||
}}, self);
|
||||
return new instance.web.search.FilterGroup([f], self);
|
||||
}),
|
||||
length: 3
|
||||
});
|
||||
|
||||
return $.when(
|
||||
this.render_column(col1, $('<div>').appendTo($filters)),
|
||||
this.render_column(col2, $('<div>').appendTo($filters)),
|
||||
(new instance.web.search.Advanced(this).appendTo($drawer)));
|
||||
},
|
||||
render_column: function (column, $el) {
|
||||
return $.when.apply(null, _(column).map(function (group) {
|
||||
$('<h3>').text(group.name).appendTo($el);
|
||||
return $.when.apply(null,
|
||||
_(group.filters).invoke('appendTo', $el));
|
||||
}));
|
||||
},
|
||||
/**
|
||||
* Sets up search view's view-wide auto-completion widget
|
||||
|
@ -479,14 +420,24 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
|||
data.fields_view['arch'].children,
|
||||
data.fields_view.fields);
|
||||
|
||||
// add Filters to this.inputs, need view.controls filled
|
||||
var filters = new instance.web.search.Filters(this);
|
||||
// add Advanced to this.inputs
|
||||
var advanced = new instance.web.search.Advanced(this);
|
||||
|
||||
// build drawer
|
||||
var drawer_started = $.when.apply(
|
||||
null, _(this.select_for_drawer()).invoke(
|
||||
'appendTo', this.$element.find('.oe_searchview_drawer')));
|
||||
|
||||
// load defaults
|
||||
return $.when(
|
||||
this.setup_stuff_drawer(),
|
||||
$.when.apply(null, _(this.inputs).invoke('facet_for_defaults', this.defaults))
|
||||
.then(function () {
|
||||
self.query.reset(_(arguments).compact(), {silent: true});
|
||||
self.renderFacets();
|
||||
}))
|
||||
var defaults_fetched = $.when.apply(null, _(this.inputs).invoke(
|
||||
'facet_for_defaults', this.defaults)).then(function () {
|
||||
self.query.reset(_(arguments).compact(), {silent: true});
|
||||
self.renderFacets();
|
||||
});
|
||||
|
||||
return $.when(drawer_started, defaults_fetched)
|
||||
.then(function () { self.ready.resolve(); })
|
||||
},
|
||||
/**
|
||||
|
@ -779,6 +730,7 @@ instance.web.search.Group = instance.web.search.Widget.extend({
|
|||
});
|
||||
|
||||
instance.web.search.Input = instance.web.search.Widget.extend( /** @lends instance.web.search.Input# */{
|
||||
_in_drawer: false,
|
||||
/**
|
||||
* @constructs instance.web.search.Input
|
||||
* @extends instance.web.search.Widget
|
||||
|
@ -820,6 +772,9 @@ instance.web.search.Input = instance.web.search.Widget.extend( /** @lends instan
|
|||
}
|
||||
return this.facet_for(defaults[this.attrs.name]);
|
||||
},
|
||||
in_drawer: function () {
|
||||
return !!this._in_drawer;
|
||||
},
|
||||
get_context: function () {
|
||||
throw new Error(
|
||||
"get_context not implemented for widget " + this.attrs.type);
|
||||
|
@ -937,6 +892,7 @@ instance.web.search.FilterGroup = instance.web.search.Input.extend(/** @lends in
|
|||
var self = this, fs;
|
||||
var facet = this.view.query.detect(function (f) {
|
||||
return f.get('field') === self; });
|
||||
// just toggle the bloody thing
|
||||
if (facet) {
|
||||
fs = facet.get('values');
|
||||
|
||||
|
@ -1304,8 +1260,71 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
|
|||
}
|
||||
});
|
||||
|
||||
instance.web.search.Filters = instance.web.search.Input.extend({
|
||||
template: 'SearchView.Filters',
|
||||
_in_drawer: true,
|
||||
start: function () {
|
||||
var self = this;
|
||||
var running_count = 0;
|
||||
// get total filters count
|
||||
var is_group = function (i) { return i instanceof instance.web.search.FilterGroup; };
|
||||
var filters_count = _(this.view.controls).chain()
|
||||
.flatten()
|
||||
.filter(is_group)
|
||||
.map(function (i) { return i.filters.length; })
|
||||
.sum()
|
||||
.value();
|
||||
|
||||
var col1 = [], col2 = _(this.view.controls).map(function (inputs, group) {
|
||||
var filters = _(inputs).filter(is_group);
|
||||
return {
|
||||
name: group === 'null' ? _t("Filters") : group,
|
||||
filters: filters,
|
||||
length: _(filters).chain().map(function (i) {
|
||||
return i.filters.length; }).sum().value()
|
||||
};
|
||||
});
|
||||
|
||||
while (col2.length) {
|
||||
// col1 + group should be smaller than col2 + group
|
||||
if ((running_count + col2[0].length) <= (filters_count - running_count)) {
|
||||
running_count += col2[0].length;
|
||||
col1.push(col2.shift());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a Custom Filter FilterGroup for each custom filter read from
|
||||
// the db, add all of this as a group in the smallest column
|
||||
(col1.length <= col2.length ? col1 : col2).push({
|
||||
name: _t("Custom Filters"),
|
||||
filters: _.map(this.view.custom_filters, function (filter) {
|
||||
// FIXME: handling of ``disabled`` being set
|
||||
var f = new instance.web.search.Filter({attrs: {
|
||||
string: filter.name,
|
||||
context: filter.context,
|
||||
domain: filter.domain
|
||||
}}, self.view);
|
||||
return new instance.web.search.FilterGroup([f], self.view);
|
||||
}),
|
||||
length: this.view.custom_filters.length
|
||||
});
|
||||
return $.when(
|
||||
this.render_column(col1, $('<div>').appendTo(this.$element)),
|
||||
this.render_column(col2, $('<div>').appendTo(this.$element)));
|
||||
},
|
||||
render_column: function (column, $el) {
|
||||
return $.when.apply(null, _(column).map(function (group) {
|
||||
$('<h3>').text(group.name).appendTo($el);
|
||||
return $.when.apply(null,
|
||||
_(group.filters).invoke('appendTo', $el));
|
||||
}));
|
||||
}
|
||||
});
|
||||
instance.web.search.Advanced = instance.web.search.Input.extend({
|
||||
template: 'SearchView.advanced',
|
||||
_in_drawer: true,
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.$element
|
||||
|
|
|
@ -1291,6 +1291,8 @@
|
|||
|
||||
<div t-name="SearchView" class="oe_searchview">
|
||||
<div class="oe_searchview_facets"/>
|
||||
<div class="oe_searchview_unfold_drawer"/>
|
||||
<div class="oe_searchview_drawer"/>
|
||||
</div>
|
||||
|
||||
<div t-name="SearchView.InputView"
|
||||
|
@ -1458,6 +1460,9 @@
|
|||
</t>
|
||||
</t>
|
||||
</t>
|
||||
<div t-name="SearchView.Filters" class="oe_searchview_filters">
|
||||
|
||||
</div>
|
||||
<div t-name="SearchView.advanced" class="oe_searchview_advanced">
|
||||
<h4>Advanced Search...</h4>
|
||||
<form>
|
||||
|
|
|
@ -170,12 +170,24 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Builds a basic search view with a single "dummy" field. The dummy
|
||||
* extends `instance.web.search.Field`, it does not add any (class)
|
||||
* attributes beyond what is provided through ``dummy_widget_attributes``.
|
||||
*
|
||||
* The view is returned un-started, it is the caller's role to start it
|
||||
* (or use DOM-insertion methods to start it indirectly).
|
||||
*
|
||||
* @param [dummy_widget_attributes={}]
|
||||
* @param [defaults={}]
|
||||
* @return {instance.web.SearchView}
|
||||
*/
|
||||
function makeSearchView(dummy_widget_attributes, defaults) {
|
||||
instance.web.search.fields.add(
|
||||
'dummy', 'instance.dummy.DummyWidget');
|
||||
instance.dummy = {};
|
||||
instance.dummy.DummyWidget = instance.web.search.Field.extend(
|
||||
dummy_widget_attributes);
|
||||
dummy_widget_attributes || {});
|
||||
instance.connection.responses['/web/searchview/load'] = function () {
|
||||
return {result: {fields_view: {
|
||||
type: 'search',
|
||||
|
@ -642,6 +654,42 @@ $(document).ready(function () {
|
|||
});
|
||||
});
|
||||
|
||||
// TODO: test drawer rendering
|
||||
module('drawer', {
|
||||
setup: function () {
|
||||
instance = window.openerp.init([]);
|
||||
window.openerp.web.corelib(instance);
|
||||
window.openerp.web.coresetup(instance);
|
||||
window.openerp.web.chrome(instance);
|
||||
window.openerp.web.data(instance);
|
||||
window.openerp.web.search(instance);
|
||||
|
||||
instance.web.qweb.add_template(doc);
|
||||
|
||||
instance.connection.responses = {};
|
||||
instance.connection.rpc_function = function (url, payload) {
|
||||
if (!(url.url in this.responses)) {
|
||||
return $.Deferred().reject(
|
||||
{}, 'failed',
|
||||
_.str.sprintf("Url %s not found in mock responses",
|
||||
url.url)).promise();
|
||||
}
|
||||
return $.when(this.responses[url.url](payload));
|
||||
};
|
||||
}
|
||||
});
|
||||
asyncTest('is-drawn', 2, function () {
|
||||
var view = makeSearchView();
|
||||
var $fix = $('#qunit-fixture');
|
||||
view.appendTo($fix)
|
||||
.always(start)
|
||||
.fail(function (error) { ok(false, error.message); })
|
||||
.done(function () {
|
||||
ok($fix.find('.oe_searchview_filters').length,
|
||||
"filters drawer control has been drawn");
|
||||
ok($fix.find('.oe_searchview_advanced').length,
|
||||
"filters advanced search has been drawn");
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: UI tests?
|
||||
});
|
||||
|
|
|
@ -122,12 +122,18 @@ rendered inside the drawer.
|
|||
second more usual calendar widget in the drawer for more
|
||||
obvious/precise interactions)
|
||||
|
||||
Any input can note its desire to be rendered in the drawer by setting
|
||||
its :js:attr:`~openerp.web.search.Input.in_drawer` attribute to
|
||||
``true``, either on its class or on its instance.
|
||||
Any input can note its desire to be rendered in the drawer by
|
||||
returning a truthy value from
|
||||
:js:func:`~openerp.web.search.Input.in_drawer`.
|
||||
|
||||
It will be rendered in the full width of the drawer, and instantiated
|
||||
only once.
|
||||
By default, :js:func:`~openerp.web.search.Input.in_drawer` returns the
|
||||
value of :js:attr:`~openerp.web.search.Input._in_drawer`, which is
|
||||
``false``. The behavior can be toggled either by redefining the
|
||||
attribute to ``true`` (either on the class or on the input), or by
|
||||
overriding :js:func:`~openerp.web.search.Input.in_drawer` itself.
|
||||
|
||||
The input will be rendered in the full width of the drawer, it will be
|
||||
started only once (per view).
|
||||
|
||||
.. todo:: drawer API (if a widget wants to close the drawer in some
|
||||
way), part of the low-level SearchView API/interactions?
|
||||
|
|
Loading…
Reference in New Issue