[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
This commit is contained in:
@@ -14,7 +14,6 @@ if (!config.device.isMobile) {
|
||||
|
||||
Discuss.include({
|
||||
template: 'mail.discuss_mobile',
|
||||
need_control_panel: false, // in mobile, we use a custom control panel
|
||||
events: _.extend(Discuss.prototype.events, {
|
||||
'click .o_mail_mobile_tab': '_onMobileTabClicked',
|
||||
'click .o_channel_inbox_item': '_onMobileInboxButtonClicked',
|
||||
@@ -122,14 +121,6 @@ Discuss.include({
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_toggleSearchView: function () {
|
||||
this.searchviewDisplayed = !this.searchviewDisplayed;
|
||||
this.searchview.$el.toggleClass('o_hidden', !this.searchviewDisplayed);
|
||||
this.$buttons.toggleClass('o_hidden', this.searchviewDisplayed);
|
||||
},
|
||||
/**
|
||||
* Overrides to toggle the visibility of the tabs when a message is unselected
|
||||
*
|
||||
@@ -198,10 +189,6 @@ Discuss.include({
|
||||
self.$buttons.find('.o_mail_chat_button_' + type).removeClass('o_hidden');
|
||||
self.$buttons.find('.o_mail_chat_button_mark_read').toggleClass('o_hidden', type !== 'channel_inbox');
|
||||
self.$buttons.find('.o_mail_chat_button_unstar_all').toggleClass('o_hidden', type !== 'channel_starred');
|
||||
self.$('.o_enable_searchview').toggleClass('o_hidden', !inInbox);
|
||||
if (!inInbox && self.searchviewDisplayed) {
|
||||
self._toggleSearchView(); // close the searchview when leaving Inbox
|
||||
}
|
||||
|
||||
// update Inbox page buttons
|
||||
if (inInbox) {
|
||||
@@ -219,17 +206,6 @@ Discuss.include({
|
||||
self.$('.o_mail_mobile_tab[data-type=' + type + ']').addClass('active');
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_updateControlPanel: function () {
|
||||
this.$buttons.appendTo(this.$('.o_mail_chat_mobile_control_panel'));
|
||||
this.searchview.$el.appendTo(this.$('.o_mail_chat_mobile_control_panel'));
|
||||
var $enable_searchview = $('<button/>', {type: 'button'})
|
||||
.addClass('o_enable_searchview btn fa fa-search')
|
||||
.on('click', this._toggleSearchView.bind(this));
|
||||
$enable_searchview.insertAfter(this.searchview.$el);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
|
||||
@@ -271,35 +271,6 @@
|
||||
@include o-flex-flow(column, nowrap);
|
||||
background: white;
|
||||
|
||||
.o_mail_chat_mobile_control_panel {
|
||||
@include o-flex(0, 0, auto);
|
||||
padding: 5px;
|
||||
min-height: 44px;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
box-shadow: 0px 0px 10px #afafaf;
|
||||
z-index: 1; // so that box shaddow is above thread's images
|
||||
.o_searchview {
|
||||
border: none;
|
||||
padding: 5px 5px 0px 5px;
|
||||
.o_searchview_input {
|
||||
font-size: 15px;
|
||||
}
|
||||
.o_searchview_more {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.o_enable_searchview, .o_enable_searchview:focus,
|
||||
.o_enable_searchview:hover, .o_enable_searchview:active {
|
||||
@include o-position-absolute($right: 5px, $top: 5px);
|
||||
color: gray;
|
||||
background: none;
|
||||
font-size: 15px;
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.o_mail_chat_mobile_inbox_buttons {
|
||||
@include o-flex-display;
|
||||
@include o-flex(0, 0, auto);
|
||||
|
||||
@@ -149,7 +149,6 @@
|
||||
<!-- Mobile templates -->
|
||||
<t t-name="mail.discuss_mobile">
|
||||
<div class="o_mail_chat">
|
||||
<div class="o_mail_chat_mobile_control_panel"/>
|
||||
<div class="o_mail_chat_mobile_inbox_buttons">
|
||||
<button type="button" class="btn btn-primary btn-sm visible-xs-inline o_channel_inbox_item" title="Inbox" data-type="channel_inbox">
|
||||
Inbox
|
||||
|
||||
@@ -26,7 +26,7 @@ QUnit.test('mobile basic rendering', function (assert) {
|
||||
// /mail/client_action route is always called when the test suite is
|
||||
// launched), and we must wait for this RPC to be done before starting to
|
||||
// test the interface. This should be refactored to facilitate the testing.
|
||||
assert.expect(9);
|
||||
assert.expect(8);
|
||||
var done = assert.async();
|
||||
|
||||
createDiscuss({
|
||||
@@ -37,8 +37,6 @@ QUnit.test('mobile basic rendering', function (assert) {
|
||||
services: this.services,
|
||||
}).then(function (discuss) {
|
||||
// test basic rendering in mobile
|
||||
assert.strictEqual(discuss.$('.o_mail_chat_mobile_control_panel').length, 1,
|
||||
"should have rendered a control panel");
|
||||
assert.strictEqual(discuss.$('.o_mail_chat_content .o_mail_no_content').length, 1,
|
||||
"should display the no content message");
|
||||
assert.strictEqual(discuss.$('.o_mail_mobile_tabs').length, 1,
|
||||
@@ -56,7 +54,7 @@ QUnit.test('mobile basic rendering', function (assert) {
|
||||
"should be in DMs tab");
|
||||
assert.strictEqual(discuss.$('.o_mail_chat_content .o_mail_no_content').length, 0,
|
||||
"should display the no content message");
|
||||
discuss.$('.o_mail_chat_button_dm').click(); // click to add a channel
|
||||
$('.o_mail_chat_button_dm').click(); // click to add a channel
|
||||
assert.strictEqual(discuss.$('.o_mail_add_channel input:visible').length, 1,
|
||||
"should display the input to add a channel");
|
||||
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
});
|
||||
@@ -30,9 +30,9 @@
|
||||
}
|
||||
|
||||
.btn.o_enable_searchview {
|
||||
width: 10%;
|
||||
margin-left: 2%;
|
||||
padding: 0px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
> .o_cp_left {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@include o-flex(0, 0, auto);
|
||||
max-width: 100%;
|
||||
@include o-flex-display;
|
||||
position: relative;
|
||||
margin: 1px 3px 0 0;
|
||||
|
||||
.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_searchview_input {
|
||||
width: 100px;
|
||||
@include o-flex(1, 0, auto);
|
||||
}
|
||||
|
||||
.o_searchview_more {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_searchview_autocomplete {
|
||||
@include o-position-absolute(100%, $left: auto);
|
||||
width: 100%;
|
||||
.o_searchview_input_container {
|
||||
@include o-flex-display;
|
||||
@include o-flex-flow(row, wrap);
|
||||
|
||||
li {
|
||||
padding-left: 25px;
|
||||
.o_searchview_facet {
|
||||
$o-searchview-facet-remove-width: 18px;
|
||||
@include o-flex(0, 0, auto);
|
||||
max-width: 100%;
|
||||
@include o-flex-display;
|
||||
position: relative;
|
||||
&.o-indent {
|
||||
padding-left: 50px;
|
||||
margin: 1px 3px 0 0;
|
||||
|
||||
.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);
|
||||
}
|
||||
a {
|
||||
display: inline-block;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
&:hover {
|
||||
background-color: inherit;
|
||||
|
||||
.o_facet_values {
|
||||
padding: 0 $o-searchview-facet-remove-width 0 5px;
|
||||
.o_facet_values_sep {
|
||||
font-style: italic;
|
||||
}
|
||||
&.o-expand, &.o-expanded { // caret
|
||||
@include o-position-absolute($left: 6px);
|
||||
padding: 3px;
|
||||
}
|
||||
.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_more {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_searchview_autocomplete {
|
||||
@include o-position-absolute(100%, $left: auto);
|
||||
width: 100%;
|
||||
|
||||
li {
|
||||
padding-left: 25px;
|
||||
position: relative;
|
||||
&.o-indent {
|
||||
padding-left: 50px;
|
||||
}
|
||||
&.o-expand:before {
|
||||
@include o-caret-right;
|
||||
}
|
||||
&.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"/>
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
odoo.define('web.search_tests', function (require) {
|
||||
"use strict";
|
||||
|
||||
var testUtils = require('web.test_utils');
|
||||
|
||||
var createActionManager = testUtils.createActionManager;
|
||||
|
||||
QUnit.module('Mobile Search view Screen', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
partner: {
|
||||
fields: {
|
||||
foo: {string: "Foo", type: "char"},
|
||||
boolean_field: {string: "I am a boolean", type: "boolean"},
|
||||
},
|
||||
records: [
|
||||
{id: 1, display_name: "First record", foo: "yop"},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
this.actions = [{
|
||||
id: 1,
|
||||
name: 'Partners Action 1',
|
||||
res_model: 'partner',
|
||||
type: 'ir.actions.act_window',
|
||||
views: [[false, 'list']],
|
||||
}];
|
||||
|
||||
this.archs = {
|
||||
// list views
|
||||
'partner,false,list': '<tree><field name="foo"/></tree>',
|
||||
|
||||
// search views
|
||||
'partner,false,search': '<search>' +
|
||||
'<filter string="Active" name="my_projects" domain="[(\'boolean_field\', \'=\', True)]"/>' +
|
||||
'<field name="foo" string="Foo"/>' +
|
||||
'</search>',
|
||||
};
|
||||
},
|
||||
}, function () {
|
||||
QUnit.test('can activate a filter with mobile search view', function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
var filterActiveFlag = false;
|
||||
|
||||
var actionManager = createActionManager({
|
||||
actions: this.actions,
|
||||
archs: this.archs,
|
||||
data: this.data,
|
||||
mockRPC: function (route, args) {
|
||||
if (filterActiveFlag) {
|
||||
assert.deepEqual(args.domain, [['boolean_field', '=', true]],
|
||||
"domain should have been properly transferred to list view");
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
actionManager.doAction(1);
|
||||
|
||||
assert.ok(!$('.o_mobile_search').is(':visible'),
|
||||
'mobile search view is not visible');
|
||||
// open the search view
|
||||
$('button.o_enable_searchview').click();
|
||||
|
||||
assert.ok($('.o_mobile_search').is(':visible'),
|
||||
'mobile search view is visible');
|
||||
|
||||
// open filter sub menu
|
||||
$('button.o_dropdown_toggler_btn').first().click();
|
||||
|
||||
filterActiveFlag = true;
|
||||
|
||||
// click on Active filter
|
||||
$('.o_filters_menu a:contains(Active)').click();
|
||||
|
||||
actionManager.destroy();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -100,6 +100,9 @@ var createActionManager = function (params) {
|
||||
addMockEnvironment(widget, _.defaults(params, {debounce: false}));
|
||||
widget.appendTo($target);
|
||||
widget.$el.addClass('o_web_client');
|
||||
if (config.device.isMobile) {
|
||||
widget.$el.addClass('o_touch_device');
|
||||
}
|
||||
|
||||
var userContext = params.context && params.context.user_context || {};
|
||||
var actionManager = new ActionManager(widget, userContext);
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/kanban_view_mobile.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/web_calendar.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/search_view.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/search_view_mobile.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/search_view_extra.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/data_export.scss"/>
|
||||
|
||||
@@ -211,6 +212,7 @@
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/user_menu.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/menu.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/search_view.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/search_view_mobile.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/search_filters.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/search_inputs.js"></script>
|
||||
<script type="text/javascript" src="/web/static/src/js/chrome/search_menus.js"></script>
|
||||
@@ -579,6 +581,7 @@
|
||||
<script type="text/javascript" src="/base/static/tests/base_settings_mobile_tests.js"></script>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/chrome/action_manager_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/chrome/search_view_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/calendar_mobile_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/kanban_mobile_tests.js"></script>
|
||||
</t>
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
</div>
|
||||
|
||||
<t t-name="website.DateRangeButtons">
|
||||
<div class="btn-group btn-group-sm o_date_range_buttons pull-right">
|
||||
<!-- TODO: Applied hidden-xs class as it is going to push in control panel and it breaks UI, maybe we will improve it in future -->
|
||||
<div class="btn-group btn-group-sm o_date_range_buttons hidden-xs pull-right">
|
||||
<button class="btn btn-sm btn-default js_date_range active" data-date="week">Last Week</button>
|
||||
<button class="btn btn-sm btn-default js_date_range" data-date="month">Last Month</button>
|
||||
<button class="btn btn-sm btn-default js_date_range" data-date="year">Last Year</button>
|
||||
|
||||
Reference in New Issue
Block a user