From 46992fa90f27337baaeef8801b2edb27342d38b1 Mon Sep 17 00:00:00 2001 From: Romain Estievenart Date: Tue, 6 Jun 2023 09:02:50 +0000 Subject: [PATCH] [FIX] board: display all data when force 1 column layout on small screen Before this commit, on a dashboard having a multi-column layout, the user couldn't see all those columns' actions when the layout fallback to the "1 column" on a small screen. This commit fixes it by, not only keeping the fallback to "1 column" to optimize the screen's real-estate, but also properly bringing the hidden columns' actions in the single column, so they become accessible by the user. Steps to reproduce: - Create My dashboard on PC with two views set one next to the other - Open My dashboard on mobile devices, and you see only the action inside the column on the left and not the action inside the columns on the right => bug opw-3145706 closes odoo/odoo#124360 X-original-commit: fa1da53af1d327c4fafd944547dbf3c7312a93b4 Signed-off-by: Pierre Paridans (app) Signed-off-by: Romain Estievenart (res) --- addons/board/static/src/board_controller.js | 56 ++++++++++--------- addons/board/static/src/board_controller.xml | 6 +- .../mobile/{board_test.js => board_tests.js} | 51 +++++++++++++++-- 3 files changed, 80 insertions(+), 33 deletions(-) rename addons/board/static/tests/mobile/{board_test.js => board_tests.js} (56%) diff --git a/addons/board/static/src/board_controller.js b/addons/board/static/src/board_controller.js index 0081898c70e..1fd4b9d2c9b 100644 --- a/addons/board/static/src/board_controller.js +++ b/addons/board/static/src/board_controller.js @@ -18,29 +18,29 @@ export class BoardController extends Component { this.rpc = useService("rpc"); this.dialogService = useService("dialog"); if (this.env.isSmall) { - this.board.layout = "1"; - this.board.colNumber = 1; + this.selectLayout("1", false); + } else { + const mainRef = useRef("main"); + useSortable({ + ref: mainRef, + elements: ".o-dashboard-action", + handle: ".o-dashboard-action-header", + cursor: "move", + groups: ".o-dashboard-column", + connectGroups: true, + onDrop: ({ element, previous, parent }) => { + const fromColIdx = parseInt(element.parentElement.dataset.idx, 10); + const fromActionIdx = parseInt(element.dataset.idx, 10); + const toColIdx = parseInt(parent.dataset.idx, 10); + const toActionIdx = previous ? parseInt(previous.dataset.idx, 10) + 1 : 0; + if (fromColIdx !== toColIdx) { + // to reduce visual flickering + element.classList.add("d-none"); + } + this.moveAction(fromColIdx, fromActionIdx, toColIdx, toActionIdx); + }, + }); } - const mainRef = useRef("main"); - useSortable({ - ref: mainRef, - elements: ".o-dashboard-action", - handle: ".o-dashboard-action-header", - cursor: "move", - groups: ".o-dashboard-column", - connectGroups: true, - onDrop: ({ element, previous, parent }) => { - const fromColIdx = parseInt(element.parentElement.dataset.idx, 10); - const fromActionIdx = parseInt(element.dataset.idx, 10); - const toColIdx = parseInt(parent.dataset.idx, 10); - const toActionIdx = previous ? parseInt(previous.dataset.idx, 10) + 1 : 0; - if (fromColIdx !== toColIdx) { - // to reduce visual flickering - element.classList.add("d-none"); - } - this.moveAction(fromColIdx, fromActionIdx, toColIdx, toActionIdx); - }, - }); } moveAction(fromColIdx, fromActionIdx, toColIdx, toActionIdx) { @@ -66,7 +66,7 @@ export class BoardController extends Component { this.saveBoard(); } - selectLayout(layout) { + selectLayout(layout, save = true) { const currentColNbr = this.board.colNumber; const nextColNbr = layout.split("-").length; if (nextColNbr < currentColNbr) { @@ -80,7 +80,9 @@ export class BoardController extends Component { } this.board.layout = layout; this.board.colNumber = nextColNbr; - this.saveBoard(); + if (save) { + this.saveBoard(); + } if (document.querySelector("canvas")) { // horrible hack to force charts to be recreated so they pick up the // proper size. also, no idea why raf is needed :( @@ -100,9 +102,11 @@ export class BoardController extends Component { }); } - toggleAction(action) { + toggleAction(action, save = true) { action.isFolded = !action.isFolded; - this.saveBoard(); + if (save) { + this.saveBoard(); + } } saveBoard() { diff --git a/addons/board/static/src/board_controller.xml b/addons/board/static/src/board_controller.xml index b03249d33a8..0c19acb34ac 100644 --- a/addons/board/static/src/board_controller.xml +++ b/addons/board/static/src/board_controller.xml @@ -34,9 +34,9 @@

- - - + + +

diff --git a/addons/board/static/tests/mobile/board_test.js b/addons/board/static/tests/mobile/board_tests.js similarity index 56% rename from addons/board/static/tests/mobile/board_test.js rename to addons/board/static/tests/mobile/board_tests.js index 8675fe88bf1..43578303044 100644 --- a/addons/board/static/tests/mobile/board_test.js +++ b/addons/board/static/tests/mobile/board_tests.js @@ -62,10 +62,7 @@ QUnit.module("Board", (hooks) => { if (route === "/web/action/load") { return Promise.resolve({ res_model: "partner", - views: [ - [4, "list"], - [5, "form"], - ], + views: [[4, "list"]], }); } }, @@ -77,5 +74,51 @@ QUnit.module("Board", (hooks) => { target.querySelector(".o-dashboard-action .o_control_panel"), "views in the dashboard do not have a control panel" ); + assert.containsNone( + target, + ".o-dashboard-action-header .fa-close", + "Should not have a close action button" + ); + }); + + QUnit.test("Correctly soft switch to '1' layout on small screen", async function (assert) { + serverData.views["partner,4,list"] = ''; + + await makeView({ + serverData, + type: "form", + resModel: "board", + arch: ` +
+ + + + + + + + +
`, + mockRPC(route, args) { + if (route === "/web/action/load") { + return Promise.resolve({ + res_model: "partner", + views: [[4, "list"]], + }); + } + }, + }); + assert.containsOnce(target, ".o-dashboard-layout-1", "The display layout is force to 1"); + assert.containsOnce( + target, + ".o-dashboard-column", + "The display layout is force to 1 column" + ); + assert.containsN( + target, + ".o-dashboard-action", + 2, + "The display should contains the 2 actions" + ); }); });