Permalink
Browse files

[IMP] web: Made Kanban Mobile Tabs more closer to Material Design spec

 With this change, it's apply a kanban tabs more closer to something
 like material design tabs
 See: https://material.io/design/components/tabs.html

Task: 1893168
  • Loading branch information...
res-odoo committed Nov 26, 2018
1 parent bdb26a6 commit a4fc773de62683b7964eb9ea14eb65de2c07241f
@@ -45,6 +45,8 @@ KanbanRenderer.include({
$column.scrollLeft(this._scrollPosition.left);
$column.scrollTop(this._scrollPosition.top);
}
this._computeTabHeaderJustifyContent();
this._computeTabScrollPosition();
this._super.apply(this, arguments);
},
/**
@@ -121,6 +123,104 @@ KanbanRenderer.include({
}
});
},
/**
* Compute the justify content of the kanban tab headers
* @private
*/
_computeTabHeaderJustifyContent: function () {
if (this.widgets && this.widgets.length) {
var self = this;
// Use to compute the sum of the outerWidth of all tab
var widthChilds = this.widgets.map(function (column) {
return self.$('.o_kanban_mobile_tab[data-id="' + (column.id || column.db_id) + '"]').outerWidth();
}).reduce(function (a, b) {
return a + b;
});
// Apply a space around between child if the parent length is higher then the sum of the child width
var $oKanbanMobileTabs = this.$('.o_kanban_mobile_tabs');
if ($oKanbanMobileTabs.outerWidth() >= widthChilds) {
$oKanbanMobileTabs.addClass('justify-content-around');
} else {
$oKanbanMobileTabs.removeClass('justify-content-around');
}
}
},
/**
* Compute the scroll x value for the tabs
* @private
*/
_computeTabScrollPosition: function () {
if (this.widgets && this.widgets.length) {
var lastItemIndex = this.widgets.length - 1;
var moveToIndex = this.activeColumnIndex;
var scrollToLeft = 0;
for (var i = 0; i < moveToIndex; i++) {
var $tab = this.$('.o_kanban_mobile_tab[data-id="' + (this.widgets[i].id || this.widgets[i].db_id) + '"]');
if (moveToIndex !== lastItemIndex && i === moveToIndex - 1) {
scrollToLeft += $tab.outerWidth() * 0.75;
} else {
scrollToLeft += $tab.outerWidth();
}
}
// Apply the scroll x on the tabs
this.$('.o_kanban_mobile_tabs').scrollLeft(scrollToLeft);
}
},
/**
* Define the o_current class to the current selected kanban (column & tab)
* @private
*/
_computeOCurrentClass: function () {
if (this.widgets && this.widgets.length) {
var column = this.widgets[this.activeColumnIndex];
if (!column) {
return;
}
var columnID = column.id || column.db_id;
this.$('.o_kanban_mobile_tab.o_current, ' +
'.o_kanban_group.o_current')
.removeClass('o_current');
this.$('.o_kanban_group[data-id="' + columnID + '"], ' +
'.o_kanban_mobile_tab[data-id="' + columnID + '"]')
.addClass('o_current');
}
},
/**
* Update the columns positions
* @private
* @param {boolean} [animate=false] set to true to animate
*/
_computeColumnPosition: function (animate) {
if (this.widgets && this.widgets.length) {
var moveToIndex = this.activeColumnIndex;
var updateFunc = animate ? 'animate' : 'css';
for (var i = 0; i < this.widgets.length; i++) {
var $column = this.$('.o_kanban_group[data-id="' + (this.widgets[i].id || this.widgets[i].db_id) + '"]');
if (i === moveToIndex - 1) {
$column[updateFunc]({left: '-100%'});
} else if (i === moveToIndex + 1) {
$column[updateFunc]({left: '100%'});
} else if (i === moveToIndex) {
$column[updateFunc]({left: '0%'});
} else if (i < moveToIndex) {
$column.css({left: '-100%'});
} else if (i > moveToIndex) {
$column.css({left: '100%'});
}
}
}
},
/**
* Update the kanban layout
* @private
* @param {boolean} [animate=false] set to true to animate
*/
_computeMoveToGroupUpdateKanban : function (animate) {
this._computeOCurrentClass();
this._computeColumnPosition(animate);
this._computeTabHeaderJustifyContent();
this._computeTabScrollPosition();
},
/**
* Moves to the given kanban column
*
@@ -133,6 +233,7 @@ KanbanRenderer.include({
_moveToGroup: function (moveToIndex, animate) {
var self = this;
if (moveToIndex < 0 || moveToIndex >= this.widgets.length) {
this._computeMoveToGroupUpdateKanban(animate);
return $.when();
}
var def = $.Deferred();
@@ -141,31 +242,7 @@ KanbanRenderer.include({
this.trigger_up('kanban_load_records', {
columnID: column.db_id,
onSuccess: function () {
// update the columns and tabs positions (optionally with an animation)
var updateFunc = animate ? 'animate' : 'css';
self.$('.o_kanban_mobile_tab, .o_kanban_group').removeClass('o_current');
_.each(self.widgets, function (column, index) {
var columnID = column.id || column.db_id;
var $column = self.$('.o_kanban_group[data-id="' + columnID + '"]');
var $tab = self.$('.o_kanban_mobile_tab[data-id="' + columnID + '"]');
if (index === moveToIndex - 1) {
$column[updateFunc]({left: '-100%'});
$tab[updateFunc]({left: '0%'});
} else if (index === moveToIndex + 1) {
$column[updateFunc]({left: '100%'});
$tab[updateFunc]({left: '100%'});
} else if (index === moveToIndex) {
$column[updateFunc]({left: '0%'});
$tab[updateFunc]({left: '50%'});
$tab.add($column).addClass('o_current');
} else if (index < moveToIndex) {
$column.css({left: '-100%'});
$tab[updateFunc]({left: '-100%'});
} else if (index > moveToIndex) {
$column.css({left: '100%'});
$tab[updateFunc]({left: '200%'});
}
});
self._computeMoveToGroupUpdateKanban(animate);
def.resolve();
},
});
@@ -5,15 +5,16 @@
overflow: hidden;

.o_kanban_mobile_tabs {
display:flex;
width: 100%;
height: $o-kanban-mobile-tabs-height;
position: relative;
overflow-x: auto;
background-color: #5E5E5E;

.o_kanban_mobile_tab {
@include o-position-absolute($left: 100%);
transform: translateX(-50%);
height: $o-kanban-mobile-tabs-height;
padding: 10px;
padding: 10px 20px;
font-size: 14px;
color: white;

@@ -23,6 +24,7 @@
}
.o_column_title {
white-space: nowrap;
text-transform: uppercase;
}
}
}
@@ -56,7 +56,7 @@ QUnit.module('Views', {
QUnit.module('KanbanView Mobile');

QUnit.test('mobile grouped rendering', function (assert) {
assert.expect(11);
assert.expect(12);

var kanban = createView({
View: KanbanView,
@@ -73,6 +73,8 @@ QUnit.module('Views', {

// basic rendering tests
assert.containsN(kanban, '.o_kanban_group', 2, "should have 2 columns" );
assert.hasClass(kanban.$('.o_kanban_mobile_tabs'),'justify-content-around',
"tabs should have class 'justify-content-around'");
assert.hasClass(kanban.$('.o_kanban_mobile_tab:first'),'o_current',
"first tab is the active tab with class 'o_current'");
assert.hasClass(kanban.$('.o_kanban_group:first'),'o_current',

0 comments on commit a4fc773

Please sign in to comment.