diff --git a/addons/crm/static/src/xml/forecast_kanban.xml b/addons/crm/static/src/xml/forecast_kanban.xml
index 7cbbee8f0f9..eb223af3360 100644
--- a/addons/crm/static/src/xml/forecast_kanban.xml
+++ b/addons/crm/static/src/xml/forecast_kanban.xml
@@ -4,8 +4,10 @@
diff --git a/addons/web/static/src/legacy/js/views/kanban/kanban_column.js b/addons/web/static/src/legacy/js/views/kanban/kanban_column.js
index 261e0da8dc6..140aa2d02e9 100644
--- a/addons/web/static/src/legacy/js/views/kanban/kanban_column.js
+++ b/addons/web/static/src/legacy/js/views/kanban/kanban_column.js
@@ -2,6 +2,7 @@ odoo.define('web.KanbanColumn', function (require) {
"use strict";
var core = require('web.core');
+var config = require('web.config');
var session = require('web.session');
var Dialog = require('web.Dialog');
var KanbanRecord = require('web.KanbanRecord');
@@ -66,7 +67,7 @@ var KanbanColumn = Widget.extend({
this.offset = 0;
this.loadMoreCount = data.loadMoreCount;
this.loadMoreOffset = data.loadMoreOffset;
- this.canBeFolded = this.folded;
+ this.isMobile = config.device.isMobile;
if (options.hasProgressBar) {
this.barOptions = {
@@ -107,7 +108,7 @@ var KanbanColumn = Widget.extend({
defs.push(this._addRecord(this.data_records[i]));
}
- if (this.recordsDraggable) {
+ if (this.recordsDraggable && !config.device.isMobile) {
this.$el.sortable({
connectWith: '.o_kanban_group',
containment: this.draggable ? false : 'parent',
@@ -147,21 +148,23 @@ var KanbanColumn = Widget.extend({
}
});
}
- this.$el.click(function (event) {
- if (self.folded) {
- self._onToggleFold(event);
- }
- });
+ if (!config.device.isMobile) {
+ this.$el.click(function (event) {
+ if (self.folded) {
+ self._onToggleFold(event);
+ }
+ });
+ }
if (this.barOptions) {
this.$el.addClass('o_kanban_has_progressbar');
this.progressBar = this._getKanbanColumnProgressBar();
defs.push(this.progressBar.appendTo(this.$header));
}
- var title = this.folded ? this.title + ' (' + this.data.count + ')' : this.title;
+ var title = !config.device.isMobile && this.folded ? this.title + ' (' + this.data.count + ')' : this.title;
this.$header.find('.o_column_title').text(title);
- this.$el.toggleClass('o_column_folded', this.canBeFolded);
+ this.$el.toggleClass('o_column_folded', !config.device.isMobile && this.folded);
if (this.tooltipInfo) {
this.$header.find('.o_kanban_header_title').tooltip({}).attr('data-original-title', this.tooltipInfo);
}
@@ -365,7 +368,11 @@ var KanbanColumn = Widget.extend({
*/
_onLoadMore: function (event) {
event.preventDefault();
- this.trigger_up('kanban_load_column_records', { loadMoreOffset: this.loadMoreOffset });
+ if (this.folded) {
+ this.trigger_up('column_toggle_fold');
+ } else {
+ this.trigger_up('kanban_load_column_records', { loadMoreOffset: this.loadMoreOffset });
+ }
},
/**
* @private
diff --git a/addons/web/static/src/legacy/js/views/kanban/kanban_column_quick_create.js b/addons/web/static/src/legacy/js/views/kanban/kanban_column_quick_create.js
index dc5489bf200..c4795f8fa44 100644
--- a/addons/web/static/src/legacy/js/views/kanban/kanban_column_quick_create.js
+++ b/addons/web/static/src/legacy/js/views/kanban/kanban_column_quick_create.js
@@ -7,6 +7,7 @@ odoo.define('web.kanban_column_quick_create', function (require) {
*/
var core = require('web.core');
+var config = require('web.config');
var Dialog = require('web.Dialog');
var Widget = require('web.Widget');
@@ -35,7 +36,7 @@ var ColumnQuickCreate = Widget.extend({
this.applyExamplesText = options.applyExamplesText || _t("Use This For My Kanban");
this.examples = options.examples;
this.folded = true;
- this.isMobile = false;
+ this.isMobile = config.device.isMobile;
this.isFirstColumn = options.isFirstColumn;
},
/**
@@ -204,6 +205,7 @@ var ColumnQuickCreate = Widget.extend({
text: _t('Close'),
}],
size: "large",
+ fullscreen: config.device.isMobile,
title: _t("Kanban Examples"),
}).open();
dialog.on('closed', this, function () {
diff --git a/addons/web/static/src/legacy/js/views/kanban/kanban_controller.js b/addons/web/static/src/legacy/js/views/kanban/kanban_controller.js
index 7f807eb0465..223705f4b38 100644
--- a/addons/web/static/src/legacy/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/legacy/js/views/kanban/kanban_controller.js
@@ -9,6 +9,7 @@ odoo.define('web.KanbanController', function (require) {
var BasicController = require('web.BasicController');
var Context = require('web.Context');
+var config = require('web.config');
var core = require('web.core');
var Dialog = require('web.Dialog');
var Domain = require('web.Domain');
@@ -50,6 +51,14 @@ var KanbanController = BasicController.extend({
this.hasButtons = params.hasButtons;
this.quickCreateEnabled = params.quickCreateEnabled;
},
+ /**
+ * @override
+ */
+ async start() {
+ await this._super(...arguments);
+ const { groupedBy } = this.model.get(this.handle);
+ this.el.classList.toggle("o_action_delegate_scroll", config.device.isMobile && groupedBy.length);
+ },
//--------------------------------------------------------------------------
// Public
@@ -72,6 +81,14 @@ var KanbanController = BasicController.extend({
this.$buttons.appendTo($node);
}
},
+ /**
+ * @override
+ */
+ async update() {
+ await this._super(...arguments);
+ const { groupedBy } = this.model.get(this.handle);
+ this.el.classList.toggle("o_action_delegate_scroll", config.device.isMobile && groupedBy.length);
+ },
/**
* In grouped mode, set 'Create' button as btn-secondary if there is no column
* (except if we can't create new columns)
diff --git a/addons/web/static/src/legacy/scss/kanban_view.scss b/addons/web/static/src/legacy/scss/kanban_view.scss
index 5843af7e65f..399bcde90fe 100644
--- a/addons/web/static/src/legacy/scss/kanban_view.scss
+++ b/addons/web/static/src/legacy/scss/kanban_view.scss
@@ -428,6 +428,13 @@
padding: 0;
background-color: $gray-100;
+ @include media-breakpoint-down(sm) {
+ min-height: initial;
+ height: 100%;
+ overflow: scroll hidden !important;
+ scroll-snap-type: x mandatory;
+ }
+
.o_kanban_record, .o_kanban_quick_create {
width: 100%;
margin-left: 0;
@@ -441,7 +448,7 @@
// Kanban Grouped Layout - Column default
.o_kanban_group {
- flex: 0 0 auto;
+ flex: 0 0 $o-kanban-default-record-width + 2*$o-kanban-group-padding;
padding: 0 $o-kanban-group-padding $o-kanban-group-padding $o-kanban-group-padding;
background-color: inherit;
@@ -471,22 +478,16 @@
.o_kanban_config {
visibility: hidden;
+ @include media-breakpoint-down(sm) {
+ visibility: visible;
+ }
+
i {
@include o-kanban-icon;
}
}
}
- .o_kanban_load_more {
- padding: $o-kanban-record-margin 0;
- box-shadow: inset 0 10px 13px -13px black;
- text-align: center;
- }
-
- &:not(.o_column_folded) {
- width: $o-kanban-default-record-width + 2*$o-kanban-group-padding;
- }
-
&.o_kanban_dragged {
background-color: $o-main-text-color;
@@ -495,45 +496,50 @@
}
}
}
-
&.ui-sortable .o_kanban_header_title .o_column_title {
cursor: move;
}
// Kanban Grouped Layout - Column Folded
.o_kanban_group.o_column_folded {
- @include o-kanban-slim-col;
- background-color: $gray-200;
+ // don't visually fold on smaller screens (aka. mobile)
+ @include media-breakpoint-up(md) {
+ @include o-kanban-slim-col;
+ background-color: $gray-200;
- & + .o_kanban_group.o_column_folded {
- margin-left: 1px;
- }
- .o_kanban_header_title {
- position: relative;
- opacity: 0.5;
-
- .o_column_title {
- @include o-kanban-v-title;
+ & + .o_kanban_group.o_column_folded {
+ margin-left: 1px;
}
- .o_column_unfold {
- @include o-kanban-icon(1);
- }
- }
- > .o_kanban_record, .o_kanban_quick_add, .o_kanban_config, .o_kanban_load_more {
- display: none!important;
- }
-
- &:hover, &.o_kanban_hover {
.o_kanban_header_title {
- opacity: 1;
+ position: relative;
+ opacity: 0.5;
+
+ .o_column_title {
+ @include o-kanban-v-title;
+ }
+
+ .o_column_unfold {
+ @include o-kanban-icon(1);
+ }
+ }
+
+ > .o_kanban_record, .o_kanban_quick_add, .o_kanban_config, .o_kanban_load_more {
+ display: none !important;
+ }
+ &:hover, &.o_kanban_hover {
+ .o_kanban_header_title {
+ opacity: 1;
+ }
}
}
}
// Kanban Grouped Layout - "Create new column" column
.o_column_quick_create {
+ flex-basis: $o-kanban-small-record-width + 2*$o-kanban-group-padding;
+
.o_quick_create_folded {
cursor: pointer;
padding: 12px 16px;
@@ -541,21 +547,15 @@
font-weight: $font-weight-bold;
@include o-hover-opacity(.7);
@include o-hover-text-color($text-muted, $body-color);
-
- .o_kanban_add_column {
- margin-right: $o-kanban-inside-hgutter;
- display: inline-block;
- padding: 10px 14px;
- background-color: rgba($text-muted, .1);
- }
}
.o_quick_create_unfolded {
margin: $border-width ($o-kanban-inside-hgutter * .5) 0;
padding: $o-kanban-inside-vgutter $o-kanban-inside-hgutter;
- width: $o-kanban-small-record-width;
- height: 100%;
- background-color: $o-view-background-color;
+
+ @include media-breakpoint-down(sm) {
+ margin: 0;
+ }
.o_kanban_header {
height: 50px;
@@ -579,6 +579,25 @@
}
}
+ @include media-breakpoint-down(sm) {
+ .o_kanban_group, .o_column_quick_create {
+ flex: 1 0 90%; // don't take full width to give a hint of next/previous column
+ scroll-snap-align: center;
+ overflow-y: scroll;
+
+ .o_kanban_header {
+ position: sticky; // keep it visible
+ top: 0;
+ z-index: 10; // same as the sticky ControlPanel
+ background-color: inherit;
+ }
+
+ .o_kanban_header_title {
+ margin-top: 0 !important; // avoid sticky glitch when scrolling
+ }
+ }
+ }
+
// Kanban UN-grouped Layout
&.o_kanban_ungrouped {
min-height: 100%;
diff --git a/addons/web/static/src/legacy/scss/modal.scss b/addons/web/static/src/legacy/scss/modal.scss
index 601c99c09dc..f1075065083 100644
--- a/addons/web/static/src/legacy/scss/modal.scss
+++ b/addons/web/static/src/legacy/scss/modal.scss
@@ -14,6 +14,14 @@
.modal-body {
&.o_act_window {
padding: 0;
+
+ @include media-breakpoint-down(sm) {
+ .o_action {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ }
+ }
}
.o_modal_header {
diff --git a/addons/web/static/src/legacy/xml/kanban.xml b/addons/web/static/src/legacy/xml/kanban.xml
index 741fc0e67c7..b7577961844 100644
--- a/addons/web/static/src/legacy/xml/kanban.xml
+++ b/addons/web/static/src/legacy/xml/kanban.xml
@@ -18,7 +18,7 @@