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 ID: 1893168
  • Loading branch information...
res-odoo committed Nov 26, 2018
1 parent b9902d9 commit cde807fe0c4682053d653503671768e739950b1b
@@ -45,6 +45,8 @@ KanbanRenderer.include({
$column.scrollLeft(this._scrollPosition.left);
$column.scrollTop(this._scrollPosition.top);
}
this._computeKanbanTabHeaderJustifyContent();
this._computeKanbanTabScrollPosition();
this._super.apply(this, arguments);
},
/**
@@ -121,6 +123,87 @@ KanbanRenderer.include({
}
});
},
/**
* Compute the justify content of the kanban tab headers
* @private
*/
_computeKanbanTabHeaderJustifyContent: 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
*/
_computeKanbanTabScrollPosition: function () {
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);
},
_computeKanbanOCurrentClass: function () {
var column = this.widgets[this.activeColumnIndex];
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
* @param {boolean} [animate=false] set to true to animate
* @private
*/
_computeKanbanColumnPosition: function (animate) {
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%'});
}
}
},
_computeMoveToGroupUpdateKanban : function (animate) {
this._computeKanbanOCurrentClass();
this._computeKanbanColumnPosition(animate);
this._computeKanbanTabHeaderJustifyContent();
this._computeKanbanTabScrollPosition();
},
/**
* Moves to the given kanban column
*
@@ -133,6 +216,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 +225,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;
}
}
}
@@ -162,5 +162,33 @@ QUnit.module('Views', {

kanban.destroy();
});

QUnit.test('mobile grouped with undefined column c', function (assert) {
assert.expect(3);

var kanban = createView({
View: KanbanView,
model: 'partner',
data: this.data,
arch: '<kanban class="o_kanban_test o_kanban_small_column">' +
'<templates><t t-name="kanban-box">' +
'<div><field name="foo"/></div>' +
'</t></templates>' +
'</kanban>',
groupBy: ['product_id'],
});

// first column should be undefined with framework unique identifier
assert.containsN(kanban, '.o_kanban_group', 3, "should have 3 columns" );
assert.containsOnce(kanban, '.o_kanban_mobile_tabs + .o_kanban_group[data-id^="partner_"]',
"Undefined column should be first and have unique framework identifier as data-id")

// kanban column should match kanban mobile tabs
var column_ids = kanban.$('.o_kanban_group').map(function(){ return $(this).data('id') }).get();
var tab_ids = kanban.$('.o_kanban_mobile_tab').map(function(){ return $(this).data('id') }).get();
assert.deepEqual(column_ids, tab_ids, "all columns data-id should match mobile tabs data-id");

kanban.destroy();
});
});
});

0 comments on commit cde807f

Please sign in to comment.