[ADD] new implementation of saving current search to new filter

bzr revid: xmo@openerp.com-20120508162137-b3qu0os79zl5wz0w
This commit is contained in:
Xavier Morel 2012-05-08 18:21:37 +02:00
parent 84cae313d2
commit 6b2efcbeb9
5 changed files with 148 additions and 84 deletions

View File

@ -1287,25 +1287,6 @@ class SearchView(View):
del filter['domain']
return filters
@openerpweb.jsonrequest
def save_filter(self, req, model, name, context_to_save, domain):
Model = req.session.model("ir.filters")
ctx = common.nonliterals.CompoundContext(context_to_save)
ctx.session = req.session
ctx = ctx.evaluate()
domain = common.nonliterals.CompoundDomain(domain)
domain.session = req.session
domain = domain.evaluate()
uid = req.session._uid
context = req.session.eval_context(req.context)
to_return = Model.create_or_replace({"context": ctx,
"domain": domain,
"model_id": model,
"name": name,
"user_id": uid
}, context)
return to_return
@openerpweb.jsonrequest
def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''):
ctx = common.nonliterals.CompoundContext(context_to_save)

View File

@ -1175,6 +1175,17 @@
border: 1px solid #cccccc;
text-align: left;
}
.openerp .oe_searchview .oe_searchview_drawer button, .openerp .oe_searchview .oe_searchview_drawer .button {
border: none;
background: white;
padding: 0 2px;
-moz-box-shadow: none;
-webkit-box-shadow: none;
-box-shadow: none;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters {
display: table;
width: 100%;
@ -1205,6 +1216,17 @@
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li:hover {
background-color: #f0f0fa;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom .oe_searchview_custom_save {
font-size: 1px;
letter-spacing: -1px;
color: transparent;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom .oe_searchview_custom_save:before {
font-family: "mnmliconsRegular";
content: "S";
font-size: 20px;
color: #404040;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4 {
border-top: 1px solid #cccccc;
margin: 5px 0 3px;

View File

@ -932,6 +932,13 @@ $colour4: #8a89ba
border: 1px solid #ccc
text-align: left
button, .button
border: none
background: white
padding: 0 2px
@include box-shadow(none)
@include radius(0)
.oe_searchview_filters
display: table
width: 100%
@ -960,6 +967,17 @@ $colour4: #8a89ba
&:hover
background-color: #f0f0fa
.oe_searchview_custom
.oe_searchview_custom_save
font-size: 1px
letter-spacing: -1px
color: transparent
&:before
font-family: "mnmliconsRegular"
content: "S"
font-size: 20px
color: #404040
.oe_searchview_advanced
h4
border-top: 1px solid #ccc

View File

@ -221,8 +221,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
this.hidden = !!hidden;
this.headless = this.hidden && !this.has_defaults;
this.filter_data = {};
this.input_subviews = [];
this.ready = $.Deferred();
@ -246,13 +244,8 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
model: this.model,
view_id: this.view_id,
context: this.dataset.get_context() });
// FIXME: local eval of domain and context to get rid of special endpoint
var filters = this.rpc('/web/searchview/get_filters', {
model: this.model
}).then(function (filters) { self.custom_filters = filters; });
$.when(load_view, filters)
.pipe(function (load) { return load[0]; })
$.when(load_view)
.pipe(this.on_loaded)
.fail(function () {
self.ready.reject.apply(null, arguments);
@ -535,42 +528,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
limit : 80
});
break;
case 'save_filter':
var data = this.build_search_data();
var context = new instance.web.CompoundContext();
_.each(data.contexts, function(x) {
context.add(x);
});
var domain = new instance.web.CompoundDomain();
_.each(data.domains, function(x) {
domain.add(x);
});
var groupbys = _.pluck(data.groupbys, "group_by").join();
context.add({"group_by": groupbys});
var dial_html = QWeb.render("SearchView.managed-filters.add");
var $dial = $(dial_html);
instance.web.dialog($dial, {
modal: true,
title: _t("Filter Entry"),
buttons: [
{text: _t("Cancel"), click: function() {
$(this).dialog("close");
}},
{text: _t("OK"), click: function() {
$(this).dialog("close");
var name = $(this).find("input").val();
self.rpc('/web/searchview/save_filter', {
model: self.dataset.model,
context_to_save: context,
domain: domain,
name: name
}).then(function() {
self.reload_managed_filters();
});
}}
]
});
break;
case '':
this.do_clear();
}
@ -647,17 +604,23 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
});
},
/**
* Performs the search view collection of widget data.
* Extract search data from the view's facets.
*
* If the collection went well (all fields are valid), then triggers
* :js:func:`instance.web.SearchView.on_search`.
* Result is an object with 4 (own) properties:
*
* If at least one field failed its validation, triggers
* :js:func:`instance.web.SearchView.on_invalid` instead.
* errors
* An array of any error generated during data validation and
* extraction, contains the validation error objects
* domains
* Array of domains
* contexts
* Array of contexts
* groupbys
* Array of domains, in groupby order rather than view order
*
* @param e jQuery event object coming from the "Search" button
* @return {Object}
*/
do_search: function () {
build_search_data: function () {
var domains = [], contexts = [], groupbys = [], errors = [];
this.query.each(function (facet) {
@ -683,12 +646,30 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
}
}
});
if (!_.isEmpty(errors)) {
this.on_invalid(errors);
return {
domains: domains,
contexts: contexts,
groupbys: groupbys,
errors: errors
};
}, /**
* Performs the search view collection of widget data.
*
* If the collection went well (all fields are valid), then triggers
* :js:func:`instance.web.SearchView.on_search`.
*
* If at least one field failed its validation, triggers
* :js:func:`instance.web.SearchView.on_invalid` instead.
*
* @param e jQuery event object coming from the "Search" button
*/
do_search: function () {
var search = this.build_search_data();
if (!_.isEmpty(search.errors)) {
this.on_invalid(search.errors);
return;
}
return this.on_search(domains, contexts, groupbys);
return this.on_search(search.domains, search.contexts, search.groupbys);
},
/**
* Triggered after the SearchView has collected all relevant domains and
@ -1356,6 +1337,68 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({
}
});
instance.web.search.CustomFilters = instance.web.search.Input.extend({
template: 'SearchView.CustomFilters',
start: function () {
this.$element.on('submit', 'form', this.proxy('save_current'));
// FIXME: local eval of domain and context to get rid of special endpoint
return this.rpc('/web/searchview/get_filters', {
model: this.view.model
}).pipe(this.proxy('set_filters'));
},
set_filters: function (filters) {
var self = this;
var content = this.$element.find('.oe_searchview_custom_list');
return $.when.apply(null, _(filters).chain()
.map(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);
})
.invoke('appendTo', content)
.value());
},
save_current: function () {
var self = this;
var $name = this.$element.find('input');
var search = this.view.build_search_data();
this.rpc('/web/session/eval_domain_and_context', {
domains: search.domains,
contexts: search.contexts,
group_by_seq: search.groupbys || []
}).pipe(function (results) {
if (!_.isEmpty(results.group_by)) {
results.context.group_by = results.group_by;
}
var name = $name.val();
// FIXME: creates filter and group even if the call fails :/
var f = new instance.web.search.Filter({attrs: {
string: name,
context: results.context,
domain: results.domain
}}, self.view);
(new instance.web.search.FilterGroup([f], self.view))
.appendTo(self.$element.find('.oe_searchview_custom_list'));
// FIXME: current context?
return new instance.web.Model('ir.filters').call('create_or_replace', [{
name: name,
user_id: instance.connection.uid,
model_id: self.view.model,
context: results.context,
domain: results.domain
}]);
}).then(function () {
$name.val('');
});
return false;
}
});
instance.web.search.Filters = instance.web.search.Input.extend({
template: 'SearchView.Filters',
_in_drawer: true,
@ -1395,16 +1438,8 @@ instance.web.search.Filters = instance.web.search.Input.extend({
// 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
filters: [new instance.web.search.CustomFilters(self.view)],
length: 1
});
return $.when(
this.render_column(col1, $('<div>').appendTo(this.$element)),

View File

@ -1469,6 +1469,14 @@
</t>
<div t-name="SearchView.Filters" class="oe_searchview_filters">
</div>
<div t-name="SearchView.CustomFilters" class="oe_searchview_custom">
<div class="oe_searchview_custom_list"/>
<form>
<label for="oe_searchview_custom_input">Save current search:</label>
<input id="oe_searchview_custom_input"/>
<button class="oe_searchview_custom_save">Save</button>
</form>
</div>
<div t-name="SearchView.advanced" class="oe_searchview_advanced">
<h4>Advanced Search...</h4>