summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2018-05-18 10:02:04 +0200
committerGéry Debongnie <ged@odoo.com>2018-05-23 10:48:36 +0200
commitd01787c19d4631a1de56f9873586e44ae06318f1 (patch)
treed212f930156e4aa076308e3c33aaef4e9c968666 /addons/web/static/src
parent4232eb7bcd4dd895b86db728a2b689ae9568f951 (diff)
[IMP] web,mail: improve search view for mobile devices
With this commit, we introduce a better screen to manipulate the search view in a mobile device. Note: most of this work was initially done by suh-odoo, then was adapted and moved to community by myself. task 31464
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/chrome/search_menus.js6
-rw-r--r--addons/web/static/src/js/chrome/search_view.js34
-rw-r--r--addons/web/static/src/js/chrome/search_view_mobile.js96
-rw-r--r--addons/web/static/src/scss/control_panel.scss2
-rw-r--r--addons/web/static/src/scss/search_view.scss128
-rw-r--r--addons/web/static/src/scss/search_view_mobile.scss88
-rw-r--r--addons/web/static/src/xml/base.xml27
7 files changed, 307 insertions, 74 deletions
diff --git a/addons/web/static/src/js/chrome/search_menus.js b/addons/web/static/src/js/chrome/search_menus.js
index d33cdce6500..a6548b051f4 100644
--- a/addons/web/static/src/js/chrome/search_menus.js
+++ b/addons/web/static/src/js/chrome/search_menus.js
@@ -1,6 +1,7 @@
odoo.define('web.FavoriteMenu', function (require) {
"use strict";
+var config = require('web.config');
var core = require('web.core');
var data_manager = require('web.data_manager');
var pyeval = require('web.pyeval');
@@ -38,6 +39,7 @@ return Widget.extend({
this.action = action;
this.action_id = action.id;
this.filters = {};
+ this.isMobile = config.device.isMobile;
_.each(filters, this.add_filter.bind(this));
},
start: function () {
@@ -305,6 +307,7 @@ return Widget.extend({
odoo.define('web.FilterMenu', function (require) {
"use strict";
+var config = require('web.config');
var search_filters = require('web.search_filters');
var search_inputs = require('web.search_inputs');
var Widget = require('web.Widget');
@@ -333,6 +336,7 @@ return Widget.extend({
},
init: function (parent, filters, fields) {
this._super(parent);
+ this.isMobile = config.device.isMobile;
this.filters = filters || [];
this.searchview = parent;
this.propositions = [];
@@ -409,6 +413,7 @@ return Widget.extend({
odoo.define('web.GroupByMenu', function (require) {
"use strict";
+var config = require('web.config');
var core = require('web.core');
var search_inputs = require('web.search_inputs');
var Widget = require('web.Widget');
@@ -433,6 +438,7 @@ return Widget.extend({
var self = this;
this._super(parent);
this.searchview = parent;
+ this.isMobile = config.device.isMobile;
this.groups = groups || [];
this.groupableFields = [];
var groupable_types = ['many2one', 'char', 'boolean', 'selection', 'date', 'datetime'];
diff --git a/addons/web/static/src/js/chrome/search_view.js b/addons/web/static/src/js/chrome/search_view.js
index 94087c999b6..8fc3cd73a2b 100644
--- a/addons/web/static/src/js/chrome/search_view.js
+++ b/addons/web/static/src/js/chrome/search_view.js
@@ -326,18 +326,19 @@ var SearchView = Widget.extend({
.toggleClass('fa-search-plus', !this.visible_filters);
var menu_defs = [];
this.prepare_search_inputs();
- if (this.$buttons) {
+ var $buttons = this._getButtonsElement();
+ if ($buttons) {
if (!this.options.disable_filters) {
this.filter_menu = new FilterMenu(this, this.filters, this.fields);
- menu_defs.push(this.filter_menu.appendTo(this.$buttons));
+ menu_defs.push(this.filter_menu.appendTo($buttons));
}
if (!this.options.disable_groupby) {
this.groupby_menu = new GroupByMenu(this, this.groupbys, this.fields);
- menu_defs.push(this.groupby_menu.appendTo(this.$buttons));
+ menu_defs.push(this.groupby_menu.appendTo($buttons));
}
if (!this.options.disable_favorites) {
this.favorite_menu = new FavoriteMenu(this, this.query, this.dataset.model, this.action, this.favorite_filters);
- menu_defs.push(this.favorite_menu.appendTo(this.$buttons));
+ menu_defs.push(this.favorite_menu.appendTo($buttons));
}
}
return $.when.apply($, menu_defs).then(this.set_default_filters.bind(this));
@@ -454,7 +455,7 @@ var SearchView = Widget.extend({
return self.$('.o_searchview_input').val().trim();
},
});
- this.autocomplete.appendTo(this.$el);
+ this.autocomplete.appendTo(this.$('.o_searchview_input_container'));
},
/**
* Provide auto-completion result for req.term (an array to `resp`)
@@ -528,11 +529,11 @@ var SearchView = Widget.extend({
this.query.each(function (facet) {
var f = new FacetView(this, facet);
- started.push(f.appendTo(self.$el));
+ started.push(f.appendTo(self.$('.o_searchview_input_container')));
self.input_subviews.push(f);
}, this);
var i = new InputView(this);
- started.push(i.appendTo(self.$el));
+ started.push(i.appendTo(self.$('.o_searchview_input_container')));
self.input_subviews.push(i);
_.each(this.input_subviews, function (childView) {
childView.on('focused', self, self.proxy('childFocused'));
@@ -540,7 +541,12 @@ var SearchView = Widget.extend({
});
$.when.apply(null, started).then(function () {
- _.last(self.input_subviews).$el.focus();
+ if (!config.device.isMobile) {
+ // in mobile mode, we would rathor not focusing manually the
+ // input, because it opens up the integrated keyboard, which is
+ // not what you expect when you just selected a filter.
+ _.last(self.input_subviews).$el.focus();
+ }
});
},
childFocused: function () {
@@ -666,6 +672,18 @@ var SearchView = Widget.extend({
// Private
//--------------------------------------------------------------------------
+
+ /**
+ * Will return $element where Filters, Group By and Favorite buttons are
+ * going to be pushed. This method is overriden by the mobile search view
+ * to add these buttons somewhere else in the dom.
+ *
+ * @private
+ * @returns {jQueryElement}
+ */
+ _getButtonsElement: function () {
+ return this.$buttons;
+ },
/**
* Processes a fieldsView in place. In particular, parses its arch.
*
diff --git a/addons/web/static/src/js/chrome/search_view_mobile.js b/addons/web/static/src/js/chrome/search_view_mobile.js
new file mode 100644
index 00000000000..852a65c0a37
--- /dev/null
+++ b/addons/web/static/src/js/chrome/search_view_mobile.js
@@ -0,0 +1,96 @@
+ odoo.define('web.SearchViewMobile', function (require) {
+"use strict";
+
+var config = require('web.config');
+var SearchView = require('web.SearchView');
+
+if (!config.device.isMobile) {
+ return;
+}
+
+SearchView.include({
+ template:'SearchViewMobile',
+ events:_.extend({}, SearchView.prototype.events, {
+ 'click .o_mobile_search_close, .o_mobile_search_show_result, .o_enable_searchview': '_toggleMobileSearchView',
+ 'click': '_onOpenMobileSearchView',
+ 'click .o_mobile_search_clear_facets': '_onEmptyAll',
+ 'show.bs.dropdown .o_mobile_search_filter .o_dropdown': '_onDropdownToggle',
+ 'hide.bs.dropdown .o_mobile_search_filter .o_dropdown': '_onDropdownToggle',
+ }),
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ renderFacets: function () {
+ this._super.apply(this, arguments);
+ this.$('.o_mobile_search_clear_facets')
+ .toggleClass('o_hidden', !this.query.length);
+ },
+ /**
+ * @override
+ */
+ toggle_visibility: function (is_visible) {
+ // Do not do anything, toggling visibility of searchview is handled
+ // explicitly for mobile
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ _getButtonsElement: function () {
+ return this.$('.o_mobile_search_filter');
+ },
+ /**
+ * Toggle mobile search view screen
+ *
+ * @private
+ */
+ _toggleMobileSearchView: function () {
+ this.$('.o_enable_searchview').toggleClass('btn-default', !!this.query.length);
+ this.$('.o_mobile_search').toggleClass('o_hidden');
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Toggle the little arrow in main buttons
+ *
+ * @private
+ * @param {BootstrapEvent} ev
+ */
+ _onDropdownToggle: function (ev) {
+ $(ev.currentTarget).find('.fa-chevron-right').toggleClass('fa-chevron-down');
+ },
+ /**
+ * Clears all filters from the search view
+ *
+ * @private
+ * @param {MouseEvent} event
+ */
+ _onEmptyAll: function () {
+ this.query.reset();
+ },
+ /**
+ * Open the mobile search view screen
+ *
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onOpenMobileSearchView: function (ev) {
+ if (ev.target === this.el) {
+ this._toggleMobileSearchView();
+ }
+ },
+});
+
+}); \ No newline at end of file
diff --git a/addons/web/static/src/scss/control_panel.scss b/addons/web/static/src/scss/control_panel.scss
index f883631c713..ef94b4c0f17 100644
--- a/addons/web/static/src/scss/control_panel.scss
+++ b/addons/web/static/src/scss/control_panel.scss
@@ -30,9 +30,9 @@
}
.btn.o_enable_searchview {
- width: 10%;
margin-left: 2%;
padding: 0px;
+ background: white;
}
> .o_cp_left {
diff --git a/addons/web/static/src/scss/search_view.scss b/addons/web/static/src/scss/search_view.scss
index f2b0f7fd14f..be6cb0b3f5b 100644
--- a/addons/web/static/src/scss/search_view.scss
+++ b/addons/web/static/src/scss/search_view.scss
@@ -5,84 +5,90 @@
}
.o_searchview {
- @include o-flex-display;
- @include o-flex-flow(row, wrap);
@include o-align-items(flex-end);
position: relative;
padding: 0 20px 1px 0;
- .o_searchview_facet {
- $o-searchview-facet-remove-width: 18px;
+ .o_searchview_more {
+ font-size: 16px;
+ cursor: pointer;
+ }
- @include o-flex(0, 0, auto);
- max-width: 100%;
+ .o_searchview_input_container {
@include o-flex-display;
- position: relative;
- margin: 1px 3px 0 0;
+ @include o-flex-flow(row, wrap);
- .o_searchview_facet_label {
+ .o_searchview_facet {
+ $o-searchview-facet-remove-width: 18px;
@include o-flex(0, 0, auto);
- @include o-text-overflow;
- padding: 0 3px;
- color: white;
-
+ max-width: 100%;
@include o-flex-display;
- @include o-align-items(center);
- }
+ position: relative;
+ margin: 1px 3px 0 0;
- .o_facet_values {
- padding: 0 $o-searchview-facet-remove-width 0 5px;
- .o_facet_values_sep {
- font-style: italic;
+ .o_searchview_facet_label {
+ @include o-flex(0, 0, auto);
+ @include o-text-overflow;
+ padding: 0 3px;
+ color: white;
+
+ @include o-flex-display;
+ @include o-align-items(center);
+ }
+
+ .o_facet_values {
+ padding: 0 $o-searchview-facet-remove-width 0 5px;
+ .o_facet_values_sep {
+ font-style: italic;
+ }
+ }
+ .o_facet_remove {
+ @include o-flex(0, 0, auto);
+ @include o-flex-display;
+ @include o-justify-content(center);
+ @include o-align-items(center);
+ @include o-position-absolute(0, 0, 0);
+ width: $o-searchview-facet-remove-width;
+ cursor: pointer;
}
}
- .o_facet_remove {
- @include o-flex(0, 0, auto);
- @include o-flex-display;
- @include o-justify-content(center);
- @include o-align-items(center);
- @include o-position-absolute(0, 0, 0);
- width: $o-searchview-facet-remove-width;
- cursor: pointer;
+ .o_searchview_input {
+ width: 100px;
+ @include o-flex(1, 0, auto);
}
- }
-
- .o_searchview_input {
- width: 100px;
- @include o-flex(1, 0, auto);
- }
- .o_searchview_more {
- font-size: 16px;
- cursor: pointer;
- }
+ .o_searchview_more {
+ font-size: 16px;
+ cursor: pointer;
+ }
- .o_searchview_autocomplete {
- @include o-position-absolute(100%, $left: auto);
- width: 100%;
+ .o_searchview_autocomplete {
+ @include o-position-absolute(100%, $left: auto);
+ width: 100%;
- li {
- padding-left: 25px;
- position: relative;
- &.o-indent {
- padding-left: 50px;
- }
- a {
- display: inline-block;
- padding-left: 0px;
- padding-right: 0px;
- &:hover {
- background-color: inherit;
- }
- &.o-expand, &.o-expanded { // caret
- @include o-position-absolute($left: 6px);
- padding: 3px;
- }
- &.o-expand:before {
- @include o-caret-right;
+ li {
+ padding-left: 25px;
+ position: relative;
+ &.o-indent {
+ padding-left: 50px;
}
- &.o-expanded:before {
- @include o-caret-down;
+ a {
+ display: inline-block;
+ padding-left: 0px;
+ padding-right: 0px;
+ &:hover {
+ background-color: inherit;
+ }
+ &.o-expand, &.o-expanded { // caret
+ @include o-position-absolute($left: 6px);
+ padding: 3px;
+ }
+ &.o-expand:before {
+ @include o-caret-right;
+ }
+ &.o-expanded:before {
+ @include o-caret-down;
+ }
}
}
}
diff --git a/addons/web/static/src/scss/search_view_mobile.scss b/addons/web/static/src/scss/search_view_mobile.scss
new file mode 100644
index 00000000000..2f0a3c3fc90
--- /dev/null
+++ b/addons/web/static/src/scss/search_view_mobile.scss
@@ -0,0 +1,88 @@
+.o_web_client.o_touch_device {
+ .o_mobile_search {
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ padding: 0;
+ width: 100%;
+ background-color: white;
+ z-index: 1000;
+ overflow: auto;
+ .o_mobile_search_header {
+ height: 46px;
+ margin-bottom: 10px;
+ width: 100%;
+ background-color: $o-brand-primary;
+ color: white;
+ span:active {
+ background-color: darken($o-brand-primary, 10%);
+ }
+ }
+ .o_searchview_input_container {
+ display: flex;
+ padding: 15px 20px 0 20px;
+ position: relative;
+ .o_searchview_input {
+ width: 100%;
+ margin-bottom: 15px;
+ border-bottom: 1px solid $o-brand-secondary;
+ }
+ .o_searchview_facet {
+ border-radius: 10px;
+ display: inline-flex;
+ order:1;
+ .o_searchview_facet_label {
+ border-radius: 2em 0em 0em 2em;
+ }
+ }
+ .o_searchview_autocomplete {
+ top:100%;
+ > li {
+ margin: 5px 0px;
+ }
+ }
+ }
+ .o_mobile_search_filter {
+ padding-bottom: 15%;
+ .o_dropdown {
+ width: 100%;
+ margin: 15px 5px 0px 5px;
+ border: solid 1px darken($gray-lighter, 20%);
+
+ }
+ .o_dropdown_toggler_btn {
+ width: 100%;
+ text-align: left;
+ }
+
+ // We disable the backdrop in this case because it prevents any
+ // interaction outside of a dropdown while it is open.
+ .dropdown-backdrop {
+ z-index: -1;
+ }
+ ul {
+ position: relative;
+ width: 100%;
+ box-shadow: none;
+ border: none;
+ color: $gray-light;
+ .divider {
+ margin: 0px;
+ }
+ > li > a {
+ padding: 10px 26px;
+ }
+ }
+ }
+ .o_mobile_search_show_result {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 15px;
+ font-size: 17px;
+ z-index: 1000;
+ }
+ }
+} \ No newline at end of file
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 20fee925a0f..0debc65dc54 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1013,7 +1013,26 @@
</div>
<div t-name="SearchView" class="o_searchview">
<span class="o_searchview_more fa" title="Advanced Search..."/>
+ <div class="o_searchview_input_container"/>
</div>
+<t t-name="SearchViewMobile">
+ <div class="o_searchview">
+ <button class="o_enable_searchview btn btn-sm fa fa-search"/>
+ <div class="o_mobile_search o_hidden">
+ <div class="o_mobile_search_header">
+ <span class="o_mobile_search_close pull-left mt16 mb16 mr8 ml16">
+ <i class="fa fa-arrow-left"/>
+ <strong class="pull-right ml8">FILTER</strong>
+ </span>
+ <span class="pull-right o_mobile_search_clear_facets mt16 mr16">CLEAR</span>
+ </div>
+ <div class="o_searchview_input_container"/>
+ <div class="o_mobile_search_filter o_search_options mb8 mt8 ml16 mr16"/>
+ <div class="btn btn-primary o_mobile_search_show_result">SEE RESULT</div>
+ </div>
+ </div>
+</t>
+
<input t-name="SearchView.InputView" type="text" class="o_searchview_input" accesskey="Q" placeholder="Search..."/>
<div t-name="SearchView.FacetView" tabindex="0" class="o_searchview_facet">
<span t-if="widget.model.has('icon')" t-att-class="'fa ' + widget.model.get('icon') + ' o_searchview_facet_label'"/>
@@ -1031,7 +1050,7 @@
</t>
<div t-name="SearchView.FilterMenu" class="btn-group o_dropdown">
<button class="o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
- <span class="fa fa-filter"/> Filters <span class="caret"/>
+ <span class="fa fa-filter"/> Filters <span t-attf-class="#{widget.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'}"/>
</button>
<ul class="dropdown-menu o_filters_menu" role="menu">
<li class="o_add_filter o_closed_menu">
@@ -1141,9 +1160,9 @@
</option>
</select>
</t>
-<div t-name="SearchView.GroupByMenu" class="btn-group hidden-xs o_dropdown">
+<div t-name="SearchView.GroupByMenu" class="btn-group o_dropdown">
<button class="o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
- <span class="fa fa-bars"/> Group By <span class="caret"/>
+ <span class="fa fa-bars"/> Group By <span t-attf-class="#{widget.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'}"/>
</button>
<ul class="dropdown-menu o_group_by_menu" role="menu">
<li class="divider"/>
@@ -1164,7 +1183,7 @@
</t>
<div t-name="SearchView.FavoriteMenu" class="btn-group o_dropdown">
<button class="o_dropdown_toggler_btn btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false" tabindex="-1">
- <span class="fa fa-star"/> Favorites <span class="caret"/>
+ <span class="fa fa-star"/> Favorites <span t-attf-class="#{widget.isMobile ? 'fa fa-chevron-right pull-right mt4' : 'caret'}"/>
</button>
<ul class="dropdown-menu o_favorites_menu" role="menu">
<li class="divider user_filter"/>