From 8665bf83dd6b024c313437f534a72b0a8867400b Mon Sep 17 00:00:00 2001 From: FrancoisGe Date: Thu, 4 Jan 2024 13:48:24 +0100 Subject: [PATCH] [FIX] web: close dialogs when executing action Have a form view in a dialog with an action button (e.g. a stat button). Click on it. Before this commit, the action was executed in the background, but the dialog remained open, which could confuse the user and was definitely weird UX-wise. With this commit, we automatically close all dialogs when we execute an action which will update the main action container. Note that this was working in previous versions thanks to legacy compatibility code [1], but this code has no impact on the new (wowl) dialogs, so as of 16.0, it has very limited impact. Here's a specific scenario to reproduce the issue: - go to the project task gantt view - click on a pill - in the task for view (in dialog), click on the external button of the project many2one - in the project form view (in dialog), click on a stat button (e.g. "At risk") -> before this commit, the 2 dialogs remained open. opw 3644904 [1] https://github.com/odoo/odoo/blob/15.0/addons/web/static/src/legacy/action_adapters.js#L42 X-original-commit: 03fa39738c4f81ae30caaaa032c099797ecba9e7 Part-of: odoo/odoo#149543 Co-authored-by: Aaron Bohy (aab) --- .../src/webclient/actions/action_service.js | 2 ++ .../src/webclient/menus/menu_providers.js | 3 --- .../web/static/tests/helpers/mock_services.js | 3 ++- .../webclient/actions/window_action_tests.js | 17 +++++++++++++++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/webclient/actions/action_service.js b/addons/web/static/src/webclient/actions/action_service.js index 1417e31d078..5c9ed50c1a0 100644 --- a/addons/web/static/src/webclient/actions/action_service.js +++ b/addons/web/static/src/webclient/actions/action_service.js @@ -849,6 +849,7 @@ function makeActionManager(env) { Component: ControllerComponent, componentProps: controller.props, }; + env.services.dialog.closeAll(); env.bus.trigger("ACTION_MANAGER:UPDATE", controller.__info__); return Promise.all([currentActionProm, closingProm]).then((r) => r[0]); } @@ -1451,6 +1452,7 @@ export const actionService = { "title", "ui", "user", + "dialog", ], start(env) { return makeActionManager(env); diff --git a/addons/web/static/src/webclient/menus/menu_providers.js b/addons/web/static/src/webclient/menus/menu_providers.js index 60c5bcb78c3..e7bfc3bbffa 100644 --- a/addons/web/static/src/webclient/menus/menu_providers.js +++ b/addons/web/static/src/webclient/menus/menu_providers.js @@ -33,7 +33,6 @@ commandProviderRegistry.add("menu", { async provide(env, options) { const result = []; const menuService = env.services.menu; - const dialogService = env.services.dialog; let { apps, menuItems } = computeAppsAndMenuItems(menuService.getMenuAsTree("root")); if (options.searchValue !== "") { apps = fuzzyLookup(options.searchValue, apps, (menu) => menu.label); @@ -43,7 +42,6 @@ commandProviderRegistry.add("menu", { ).forEach((menu) => { result.push({ action() { - dialogService.closeAll(); menuService.selectMenu(menu); }, category: "menu_items", @@ -68,7 +66,6 @@ commandProviderRegistry.add("menu", { result.push({ Component: AppIconCommand, action() { - dialogService.closeAll(); menuService.selectMenu(menu); }, category: "apps", diff --git a/addons/web/static/tests/helpers/mock_services.js b/addons/web/static/tests/helpers/mock_services.js index 599cb960ec5..9ea4d1492b1 100644 --- a/addons/web/static/tests/helpers/mock_services.js +++ b/addons/web/static/tests/helpers/mock_services.js @@ -251,11 +251,12 @@ export function makeFakeNotificationService(mock) { }; } -export function makeFakeDialogService(addDialog) { +export function makeFakeDialogService(addDialog, closeAllDialog) { return { start() { return { add: addDialog || (() => () => {}), + closeAll: closeAllDialog || (() => () => {}), }; }, }; diff --git a/addons/web/static/tests/webclient/actions/window_action_tests.js b/addons/web/static/tests/webclient/actions/window_action_tests.js index ce39db16878..1f318440d24 100644 --- a/addons/web/static/tests/webclient/actions/window_action_tests.js +++ b/addons/web/static/tests/webclient/actions/window_action_tests.js @@ -9,6 +9,7 @@ import { registry } from "@web/core/registry"; import { session } from "@web/session"; import { editView } from "@web/views/debug_items"; import { listView } from "@web/views/list/list_view"; +import { FormViewDialog } from "@web/views/view_dialogs/form_view_dialog"; import { useSetupAction } from "@web/webclient/actions/action_hook"; import { clearUncommittedChanges } from "@web/webclient/actions/action_service"; import testUtils from "@web/../tests/legacy/helpers/test_utils"; @@ -2410,4 +2411,20 @@ QUnit.module("ActionManager", (hooks) => { "Validation Error" ); }); + + QUnit.test("executing an action closes dialogs", async function (assert) { + const webClient = await createWebClient({ serverData }); + await doAction(webClient, 3); + assert.containsOnce(target, ".o_list_view"); + + webClient.env.services.dialog.add(FormViewDialog, { resModel: "partner", resId: 1 }); + await nextTick(); + assert.containsOnce(target, ".o_dialog .o_form_view"); + + await click( + target.querySelector(".o_dialog .o_form_view .o_statusbar_buttons button[name='4']") + ); + assert.containsOnce(target, ".o_kanban_view"); + assert.containsNone(target, ".o_dialog"); + }); });