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 @@