[ADD] groundworks for advanced search

* Possible to add an advanced search domain
* Looks like shit
* The facet itself uses a hardcoded name
* Quite a few hacks

bzr revid: xmo@openerp.com-20120330154227-gw1640rbb3rs9x5m
This commit is contained in:
Xavier Morel 2012-03-30 17:42:27 +02:00
parent 1b0c140834
commit 93e70362e5
4 changed files with 195 additions and 206 deletions

View File

@ -136,6 +136,20 @@
-moz-box-shadow: 0 1px 2px rgba(255, 255, 255, 0.3) inset;
-webkit-box-shadow: 0 1px 2px rgba(255, 255, 255, 0.3) inset;
box-shadow: 0 1px 2px rgba(255, 255, 255, 0.3) inset; }
.openerp2 .oe_menu_more_container {
position: relative; }
.openerp2 .oe_menu_more_container .oe_menu_more {
position: absolute;
padding: 0;
background-color: #646060;
z-index: 1;
border: 1px solid black;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px; }
.openerp2 .oe_menu_more_container .oe_menu_more li {
float: none; }
.openerp2 .oe_menu_more_container .oe_menu_more li a {
white-space: nowrap; }
.openerp2 .oe_secondary_menu_section {
font-weight: bold;
margin-left: 8px;
@ -209,6 +223,22 @@
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #4c4c4c; }
.openerp2 .oe_dropdown {
position: relative; }
.openerp2 .oe_dropdown_toggle:after {
width: 0;
height: 0;
display: inline-block;
content: "&darr";
text-indent: -99999px;
vertical-align: top;
margin-top: 8px;
margin-left: 4px;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid white;
filter: alpha(opacity=50);
opacity: 0.5; }
.openerp2 .oe_user_menu {
float: right;
padding: 0;
@ -216,22 +246,6 @@
.openerp2 .oe_user_menu li {
list-style-type: none;
float: left; }
.openerp2 .oe_user_menu .oe_dropdown {
position: relative; }
.openerp2 .oe_user_menu .oe_dropdown_toggle:after {
width: 0;
height: 0;
display: inline-block;
content: "&darr";
text-indent: -99999px;
vertical-align: top;
margin-top: 8px;
margin-left: 4px;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid white;
filter: alpha(opacity=50);
opacity: 0.5; }
.openerp2 .oe_user_menu .oe_dropdown_options {
float: left;
background: #333333;
@ -356,35 +370,60 @@
color: #cccccc;
cursor: pointer; }
.openerp2 .oe_searchview .VS-search .oe_vs_unfold_drawer:before {
content: ""; }
content: ""; }
.openerp2 .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer {
display: table; }
display: block; }
.openerp2 .oe_searchview .oe_searchview_drawer {
position: absolute;
top: 100%;
right: 0;
background-color: white;
width: 432px;
width: 500px;
display: none;
border: 1px solid #cccccc; }
.openerp2 .oe_searchview .oe_searchview_drawer > div {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: table-cell;
width: 50%; }
.openerp2 .oe_searchview .oe_searchview_drawer h3 {
margin: 2px 4px 2px 8px;
color: #8786b7; }
.openerp2 .oe_searchview .oe_searchview_drawer ul {
margin: 0 12px 3px;
padding: 0;
list-style: none; }
.openerp2 .oe_searchview .oe_searchview_drawer li {
list-style: none;
padding: 3px 6px;
height: 14px;
color: inherit;
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_filters {
display: table;
width: 100%; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_filters > div {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: table-cell;
width: 50%; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_filters h3 {
margin: 2px 4px 2px 8px;
color: #8786b7; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_filters ul {
margin: 0 12px 3px;
padding: 0;
list-style: none; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_filters li {
list-style: none;
padding: 3px 6px;
height: 14px;
color: inherit;
cursor: pointer; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_filters li:hover {
background-color: #f0f0fa; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4 {
border-top: 1px solid #cccccc;
margin: 5px 0 3px;
cursor: pointer; }
.openerp2 .oe_searchview .oe_searchview_drawer li:hover {
background-color: #f0f0fa; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4:before {
content: "▸ "; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced div {
display: none; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced button.oe_add_condition:before {
content: "⊞ "; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced button.oe_apply:before {
content: "⚡ "; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced ul {
list-style: none;
padding: 0; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced li {
list-style: none;
margin: 0; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened h4:before {
content: "▾ "; }
.openerp2 .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened div {
display: block; }

View File

@ -436,44 +436,78 @@ $colour4: #8a89ba
color: #ccc
cursor: pointer
&:before
content: ""
content: ""
&.oe_searchview_open_drawer
.oe_searchview_drawer
display: table
display: block
.oe_searchview_drawer
position: absolute
top: 100%
right: 0
background-color: white
width: 432px
width: 500px
display: none
border: 1px solid #ccc
> div
@include unscrew-box
display: table-cell
width: 50%
.oe_searchview_filters
display: table
width: 100%
h3
margin: 2px 4px 2px 8px
color: $section-title-color
> div
@include unscrew-box
display: table-cell
width: 50%
ul
margin: 0 12px 3px
padding: 0
list-style: none
h3
margin: 2px 4px 2px 8px
color: $section-title-color
li
list-style: none
padding: 3px 6px
height: 14px
color: inherit
cursor: pointer
ul
margin: 0 12px 3px
padding: 0
list-style: none
&:hover
background-color: #f0f0fa
li
list-style: none
padding: 3px 6px
height: 14px
color: inherit
cursor: pointer
&:hover
background-color: #f0f0fa
.oe_searchview_advanced
h4
border-top: 1px solid #ccc
margin: 5px 0 3px
cursor: pointer
h4:before
content: ""
div
display: none
button.oe_add_condition:before
content: ""
button.oe_apply:before
content: ""
ul
list-style: none
padding: 0
li
list-style: none
margin: 0
&.oe_opened
h4:before
content: ""
div
display: block
// }}}
.openerp

View File

@ -174,6 +174,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
var self = this;
$('<div class="oe_vs_unfold_drawer">').appendTo(this.$element.find('.VS-search-box'));
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
@ -222,8 +223,9 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
});
return $.when(
this.render_column(col1, $('<div>').appendTo($drawer)),
this.render_column(col2, $('<div>').appendTo($drawer)));
this.render_column(col1, $('<div>').appendTo($filters)),
this.render_column(col2, $('<div>').appendTo($filters)),
(new openerp.web.search.Advanced(this).appendTo($drawer)));
},
render_column: function (column, $el) {
return $.when.apply(null, _(column).map(function (group) {
@ -1251,113 +1253,57 @@ openerp.web.search.ManyToOneField = openerp.web.search.CharField.extend({
}
});
openerp.web.search.ExtendedSearch = openerp.web.search.Input.extend({
template: 'SearchView.extended_search',
init: function (parent, model) {
this._super(parent);
this.model = model;
},
add_group: function() {
var group = new openerp.web.search.ExtendedSearchGroup(this, this.fields);
group.appendTo(this.$element.find('.searchview_extended_groups_list'));
this.check_last_element();
},
openerp.web.search.Advanced = openerp.web.search.Input.extend({
template: 'SearchView.advanced',
start: function () {
this._super();
this.$element.closest("table.oe-searchview-render-line").css("display", "none");
var self = this;
this.rpc("/web/searchview/fields_get",
{"model": this.model}, function(data) {
self.fields = data.fields;
if (!('id' in self.fields)) {
self.fields.id = {
string: 'ID',
type: 'id'
}
}
openerp.web.search.add_expand_listener(self.$element);
self.$element.find('.searchview_extended_add_group').click(function (e) {
self.add_group();
this.propositions = [];
this.$element
.on('keypress keydown keyup', function (e) { e.stopPropagation(); })
.on('click', 'h4', function () {
self.$element.toggleClass('oe_opened');
}).on('click', 'button.oe_add_condition', function () {
self.append_proposition();
}).on('click', 'button.oe_apply', function () {
self.commit_search();
});
return $.when(
this._super(),
this.rpc("/web/searchview/fields_get", {model: this.view.model}, function(data) {
self.fields = _.extend({
id: { string: 'ID', type: 'id' }
}, data.fields);
})).then(function () {
self.append_proposition();
});
},
get_context: function() {
return null;
append_proposition: function () {
return (new openerp.web.search.ExtendedSearchProposition(this, this.fields))
.appendTo(this.$element.find('ul'));
},
get_domain: function() {
if (!this.$element) {
return null; // not a logical state but sometimes it happens
commit_search: function () {
// Get domain sections from all propositions
var domain = _.invoke(this.getChildren(), 'get_proposition');
// OR all propositions in a single domain: prepend one | for each
// sliding pair of propositions
for(var i=domain.length; --i;) {
domain.unshift('|');
}
if(this.$element.closest("table.oe-searchview-render-line").css("display") == "none") {
return null;
}
return _.reduce(this.getChildren(),
function(mem, x) { return mem.concat(x.get_domain());}, []);
},
on_activate: function() {
this.add_group();
var table = this.$element.closest("table.oe-searchview-render-line");
table.css("display", "");
if(this.$element.hasClass("folded")) {
this.$element.toggleClass("folded expanded");
}
},
hide: function() {
var table = this.$element.closest("table.oe-searchview-render-line");
table.css("display", "none");
if(this.$element.hasClass("expanded")) {
this.$element.toggleClass("folded expanded");
}
},
check_last_element: function() {
_.each(this.getChildren(), function(x) {x.set_last_group(false);});
if (this.getChildren().length >= 1) {
this.getChildren()[this.getChildren().length - 1].set_last_group(true);
}
}
});
openerp.web.search.ExtendedSearchGroup = openerp.web.OldWidget.extend({
template: 'SearchView.extended_search.group',
init: function (parent, fields) {
this._super(parent);
this.fields = fields;
},
add_prop: function() {
var prop = new openerp.web.search.ExtendedSearchProposition(this, this.fields);
var render = prop.render({'index': this.getChildren().length - 1});
this.$element.find('.searchview_extended_propositions_list').append(render);
prop.start();
},
start: function () {
var _this = this;
this.add_prop();
this.$element.find('.searchview_extended_add_proposition').click(function () {
_this.add_prop();
});
this.$element.find('.searchview_extended_delete_group').click(function () {
_this.destroy();
});
},
get_domain: function() {
var props = _(this.getChildren()).chain().map(function(x) {
return x.get_proposition();
}).compact().value();
var choice = this.$element.find(".searchview_extended_group_choice").val();
var op = choice == "all" ? "&" : "|";
return choice == "none" ? ['!'] : [].concat(
_.map(_.range(_.max([0,props.length - 1])), function() { return op; }),
props);
},
destroy: function() {
var parent = this.getParent();
if (this.getParent().getChildren().length == 1)
this.getParent().hide();
this._super();
parent.check_last_element();
},
set_last_group: function(is_last) {
this.$element.toggleClass('last_group', is_last);
// Create Filter (& FilterGroup around it) with that domain
var f = new openerp.web.search.FilterGroup([
new openerp.web.search.Filter({attrs: {
string: 'bobuse',
domain: domain
}}, this.view)
], this.view);
// add FilterGroup to this.view.searchQuery
// FIXME: holy fucking crap shoot me now
f.toggle_filter({target: {parentNode: {}}});
// remove all propositions
_.invoke(this.getChildren(), 'destroy');
// add new empty proposition
this.append_proposition();
// ? close drawer?
}
});
@ -1380,7 +1326,6 @@ openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend(/**
this.value = null;
},
start: function () {
this.$element = $("#" + this.element_id);
this.select_field(this.fields.length > 0 ? this.fields[0] : null);
var _this = this;
this.$element.find(".searchview_extended_prop_field").change(function() {
@ -1390,14 +1335,6 @@ openerp.web.search.ExtendedSearchProposition = openerp.web.OldWidget.extend(/**
_this.destroy();
});
},
destroy: function() {
var parent;
if (this.getParent().getChildren().length == 1)
parent = this.getParent();
this._super();
if (parent)
parent.destroy();
},
changed: function() {
var nval = this.$element.find(".searchview_extended_prop_field").val();
if(this.attrs.selected == null || nval != this.attrs.selected.name) {
@ -1467,11 +1404,7 @@ openerp.web.search.ExtendedSearchProposition.Char = openerp.web.search.ExtendedS
{value: "ilike", text: _lt("contains")},
{value: "not ilike", text: _lt("doesn't contain")},
{value: "=", text: _lt("is equal to")},
{value: "!=", text: _lt("is not equal to")},
{value: ">", text: _lt("greater than")},
{value: "<", text: _lt("less than")},
{value: ">=", text: _lt("greater or equal than")},
{value: "<=", text: _lt("less or equal than")}
{value: "!=", text: _lt("is not equal to")}
],
get_value: function() {
return this.$element.val();

View File

@ -1377,8 +1377,7 @@
</div>
</t>
<t t-name="SearchView.util.expand">
<div t-att-class="'searchview_group ' + (expand == '0' ? 'folded' : 'expanded')"
t-att-id="element_id">
<div t-att-class="'searchview_group ' + (expand == '0' ? 'folded' : 'expanded')">
<a t-if="label" class="searchview_group_string" href="#">
<t t-esc="label"/>
</a>
@ -1396,34 +1395,18 @@
</t>
</t>
</t>
<t t-name="SearchView.extended_search">
<t t-call="SearchView.util.expand">
<t t-set="expand" t-value="false"/>
<t t-set="label">Advanced Filters</t>
<t t-set="content">
<div class="searchview_extended_groups_list">
</div>
</t>
</t>
</t>
<t t-name="SearchView.extended_search.group">
<div t-att-id="widget.element_id" class="searchview_extended_group">
<select class="searchview_extended_group_choice">
<option value="any">Any of the following conditions must match</option>
<option value="all">All the following conditions must match</option>
<option value="none">None of the following conditions must match</option>
</select>
<a class="searchview_extended_delete_group"
href="javascript:void(0)"><span></span></a>
<div class="searchview_extended_propositions_list">
</div>
<a class="searchview_extended_add_proposition" href="javascript:void(0)">
<span>Add condition</span></a>
<div class="oe_adv_filters_and"><span>and</span></div>
<div t-name="SearchView.advanced" class="oe_searchview_advanced">
<h4>Advanced Search...</h4>
<div>
<ul>
</ul>
<button class="oe_add_condition">Add a condition</button>
<button class="oe_apply">Apply</button>
</div>
</t>
</div>
<t t-name="SearchView.extended_search.proposition">
<div t-att-id="widget.element_id">
<li>
<select class="searchview_extended_prop_field">
<t t-foreach="widget.attrs.fields" t-as="field">
<option t-if="typeof field.store === 'undefined' || field.store || field.fnct_search"
@ -1437,7 +1420,7 @@
<span class="searchview_extended_prop_value"/>
<a class="searchview_extended_delete_prop"
href="javascript:void(0)"><span> </span></a>
</div>
</li>
</t>
<t t-name="SearchView.extended_search.proposition.char">
<input t-att-id="widget.element_id" class="field_char"/>