diff --git a/addons/hr_expense/static/src/views/expense_form_view.js b/addons/hr_expense/static/src/views/expense_form_view.js index 2caac995f0b..ab20202353a 100644 --- a/addons/hr_expense/static/src/views/expense_form_view.js +++ b/addons/hr_expense/static/src/views/expense_form_view.js @@ -7,35 +7,35 @@ import { formView } from "@web/views/form/form_view"; import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_dialog"; -const { useSubEnv } = owl; - export class ExpenseFormController extends FormController { setup() { super.setup(); - const dialogService = useService("dialog"); - const orm = useService("orm"); - const t = this.env._t; - const previousOnClickViewButton = this.env.onClickViewButton; - useSubEnv({ - async onClickViewButton(params) { - const record = this.model.root; - if ( - params.clickParams.name === "action_submit_expenses" && - record.data.duplicate_expense_ids.count - ) { - dialogService.add(ConfirmationDialog, { - body: t("An expense of same category, amount and date already exists."), - confirm: async () => { - orm.call("hr.expense", "action_approve_duplicates", [record.resId]); - previousOnClickViewButton(params); - }, - cancel: () => {}, - }); - } else { - previousOnClickViewButton(params); - } - }, - }); + this.dialogService = useService("dialog"); + this.orm = useService("orm"); + } + + /** + * @override + */ + async beforeExecuteActionButton(clickParams) { + const record = this.model.root; + if ( + clickParams.name === "action_submit_expenses" && + record.data.duplicate_expense_ids.count + ) { + return new Promise((resolve) => { + this.dialogService.add(ConfirmationDialog, { + body: this.env._t("An expense of same category, amount and date already exists."), + confirm: async () => { + await this.orm.call("hr.expense", "action_approve_duplicates", [record.resId]); + resolve(true); + }, + }, { + onClose: resolve.bind(null, false), + }); + }); + } + return super.beforeExecuteActionButton(...arguments); } } diff --git a/addons/portal/static/src/views/fields/portal_wizard_user_one2many.js b/addons/portal/static/src/views/fields/portal_wizard_user_one2many.js index 4a96a4d0662..5b8773234d3 100644 --- a/addons/portal/static/src/views/fields/portal_wizard_user_one2many.js +++ b/addons/portal/static/src/views/fields/portal_wizard_user_one2many.js @@ -1,13 +1,13 @@ /** @odoo-module **/ -import { PortalWizardUserListRenderer } from "../list/portal_wizard_user_list_renderer"; +import { PortalWizardUserListController } from "../list/portal_wizard_user_list_controller"; import { X2ManyField } from "@web/views/fields/x2many/x2many_field"; import { registry } from "@web/core/registry"; export class PortalUserX2ManyField extends X2ManyField {} PortalUserX2ManyField.components = { ...X2ManyField.components, - ListRenderer: PortalWizardUserListRenderer, + Controller: PortalWizardUserListController, }; registry.category("fields").add("portal_wizard_user_one2many", PortalUserX2ManyField); diff --git a/addons/portal/static/src/views/list/portal_wizard_user_list_controller.js b/addons/portal/static/src/views/list/portal_wizard_user_list_controller.js new file mode 100644 index 00000000000..d54e0d85846 --- /dev/null +++ b/addons/portal/static/src/views/list/portal_wizard_user_list_controller.js @@ -0,0 +1,28 @@ +/** @odoo-module **/ + +import { ListController } from "@web/views/list/list_controller"; + +export class PortalWizardUserListController extends ListController { + setup() { + super.setup(); + this.isPortalActionOngoing = false; + } + + /** + * @override + */ + async beforeExecuteActionButton(clickParams) { + if (clickParams.name === 'action_refresh_modal' || this.isPortalActionOngoing) { + return false; + } + this.isPortalActionOngoing = true; + return super.beforeExecuteActionButton(clickParams); + } + + /** + * @override + */ + async afterExecuteActionButton(clickParams) { + this.isPortalActionOngoing = false; + } +} diff --git a/addons/portal/static/src/views/list/portal_wizard_user_list_renderer.js b/addons/portal/static/src/views/list/portal_wizard_user_list_renderer.js deleted file mode 100644 index 4d21b441b1b..00000000000 --- a/addons/portal/static/src/views/list/portal_wizard_user_list_renderer.js +++ /dev/null @@ -1,23 +0,0 @@ -/** @odoo-module **/ - -import { ListRenderer } from "@web/views/list/list_renderer"; - -const { useSubEnv } = owl; - -export class PortalWizardUserListRenderer extends ListRenderer { - setup() { - super.setup(); - this.isPortalActionOngoing = false; - const defaultOnClickViewButton = this.env.onClickViewButton; - useSubEnv({ - onClickViewButton: async (params) => { - if (params.clickParams.name === 'action_refresh_modal' || this.isPortalActionOngoing) { - return false; - } - this.isPortalActionOngoing = true; - await defaultOnClickViewButton(params); - this.isPortalActionOngoing = false; - }, - }); - } -} diff --git a/addons/web/static/src/views/form/form_controller.js b/addons/web/static/src/views/form/form_controller.js index c2e69a98dad..398bdaccc31 100644 --- a/addons/web/static/src/views/form/form_controller.js +++ b/addons/web/static/src/views/form/form_controller.js @@ -172,20 +172,11 @@ export class FormController extends Component { this.archInfo.arch = this.archInfo.xmlDoc.outerHTML; } - const beforeExecuteAction = (clickParams) => { - if (clickParams.special !== "cancel") { - return this.model.root.save({ stayInEdition: true }).then((saved) => { - if (saved && this.props.onSave) { - this.props.onSave(this.model.root); - } - return saved; - }); - } else if (this.props.onDiscard) { - this.props.onDiscard(this.model.root); - } - }; const rootRef = useRef("root"); - useViewButtons(this.model, rootRef, { beforeExecuteAction }); + useViewButtons(this.model, rootRef, { + beforeExecuteAction: this.beforeExecuteActionButton.bind(this), + afterExecuteAction: this.afterExecuteActionButton.bind(this), + }); useSetupView({ rootRef, beforeLeave: () => { @@ -354,6 +345,21 @@ export class FormController extends Component { this.state.isDisabled = false; } + async beforeExecuteActionButton(clickParams) { + if (clickParams.special !== "cancel") { + return this.model.root.save({ stayInEdition: true }).then((saved) => { + if (saved && this.props.onSave) { + this.props.onSave(this.model.root); + } + return saved; + }); + } else if (this.props.onDiscard) { + this.props.onDiscard(this.model.root); + } + } + + async afterExecuteActionButton(clickParams) {} + async edit() { await this.model.root.switchMode("edit"); } diff --git a/addons/web/static/src/views/kanban/kanban_controller.js b/addons/web/static/src/views/kanban/kanban_controller.js index 6cda6c9f1bd..d3c03dba775 100644 --- a/addons/web/static/src/views/kanban/kanban_controller.js +++ b/addons/web/static/src/views/kanban/kanban_controller.js @@ -35,7 +35,10 @@ export class KanbanController extends Component { }); const rootRef = useRef("root"); - useViewButtons(this.model, rootRef); + useViewButtons(this.model, rootRef, { + beforeExecuteAction: this.beforeExecuteActionButton.bind(this), + afterExecuteAction: this.afterExecuteActionButton.bind(this), + }); useSetupView({ rootRef, getGlobalState: () => { @@ -110,6 +113,10 @@ export class KanbanController extends Component { } return list.isGrouped ? list.groups.length > 0 || !groupCreate : true; } + + async beforeExecuteActionButton(clickParams) {} + + async afterExecuteActionButton(clickParams) {} } KanbanController.template = `web.KanbanView`; diff --git a/addons/web/static/src/views/list/list_controller.js b/addons/web/static/src/views/list/list_controller.js index eedc5d68859..86eba4f6146 100644 --- a/addons/web/static/src/views/list/list_controller.js +++ b/addons/web/static/src/views/list/list_controller.js @@ -86,7 +86,10 @@ export class ListController extends Component { ? !fields.x_active.readonly : false; useSubEnv({ model: this.model }); // do this in useModel? - useViewButtons(this.model, this.rootRef); + useViewButtons(this.model, this.rootRef, { + beforeExecuteAction: this.beforeExecuteActionButton.bind(this), + afterExecuteAction: this.afterExecuteActionButton.bind(this), + }); useSetupView({ rootRef: this.rootRef, beforeLeave: async () => { @@ -451,6 +454,10 @@ export class ListController extends Component { record.toggleSelection(false); }); } + + async beforeExecuteActionButton(clickParams) {} + + async afterExecuteActionButton(clickParams) {} } ListController.template = `web.ListView`; diff --git a/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js b/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js index 75262fd17ae..b2ef535225a 100644 --- a/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js +++ b/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js @@ -3,7 +3,6 @@ import { useAutofocus } from "@web/core/utils/hooks"; import { pick } from "@web/core/utils/objects"; import { formView } from "@web/views/form/form_view"; -import { useViewButtons } from "@web/views/view_button/view_button_hook"; import { SettingsConfirmationDialog } from "./settings_confirmation_dialog"; import { SettingsFormRenderer } from "./settings_form_renderer"; @@ -12,46 +11,6 @@ const { useSubEnv, useState, useRef, useEffect } = owl; export class SettingsFormController extends formView.Controller { setup() { super.setup(); - const beforeExecuteAction = async (clickParams) => { - if (clickParams.name === "cancel") { - return true; - } - let _continue = true; - if ( - this.model.root.isDirty && - !["execute"].includes(clickParams.name) && - !clickParams.noSaveDialog - ) { - const message = this.env._t("Would you like to save your changes?"); - await new Promise((resolve) => { - this.dialogService.add(SettingsConfirmationDialog, { - body: message, - confirm: async () => { - await this.model.root.save({ stayInEdition: true }); - await this.save(); - // It doesn't make sense to do the action of the button - // as the res.config.settings `execute` method will trigger a reload. - _continue = false; - resolve(); - }, - cancel: async () => { - await this.model.root.discard(); - await this.model.root.save({ stayInEdition: true }); - _continue = true; - resolve(); - }, - stayHere: () => { - _continue = false; - resolve(); - }, - }); - }); - } else { - _continue = await this.model.root.save({ stayInEdition: true }); - } - return _continue; - }; - useViewButtons(this.model, useRef("root"), { beforeExecuteAction }); useAutofocus(); this.state = useState({ displayNoContent: false }); this.searchState = useState({ value: "" }); @@ -84,6 +43,49 @@ export class SettingsFormController extends formView.Controller { this.initialApp = "module" in this.props.context && this.props.context.module; } + /** + * @override + */ + async beforeExecuteActionButton(clickParams) { + if (clickParams.name === "cancel") { + return true; + } + let _continue = true; + if ( + this.model.root.isDirty && + !["execute"].includes(clickParams.name) && + !clickParams.noSaveDialog + ) { + const message = this.env._t("Would you like to save your changes?"); + await new Promise((resolve) => { + this.dialogService.add(SettingsConfirmationDialog, { + body: message, + confirm: async () => { + await this.model.root.save({ stayInEdition: true }); + await this.save(); + // It doesn't make sense to do the action of the button + // as the res.config.settings `execute` method will trigger a reload. + _continue = false; + resolve(); + }, + cancel: async () => { + await this.model.root.discard(); + await this.model.root.save({ stayInEdition: true }); + _continue = true; + resolve(); + }, + stayHere: () => { + _continue = false; + resolve(); + }, + }); + }); + } else { + _continue = await this.model.root.save({ stayInEdition: true }); + } + return _continue; + } + displayName() { return this.env._t("Settings"); } diff --git a/addons/web/static/tests/views/form/form_view_tests.js b/addons/web/static/tests/views/form/form_view_tests.js index b04f35f398e..8b89220edb5 100644 --- a/addons/web/static/tests/views/form/form_view_tests.js +++ b/addons/web/static/tests/views/form/form_view_tests.js @@ -2807,10 +2807,10 @@ QUnit.module("Views", (hooks) => { assert.verifySteps(["read1", "willStart"]); await click(target.querySelector(".o_form_statusbar button.p")); - assert.verifySteps(["read2", "willUpdateProps", "willUpdateProps"]); + assert.verifySteps(["willUpdateProps", "read2", "willUpdateProps", "willUpdateProps"]); await click(target.querySelector(".o_form_statusbar button.p")); - assert.verifySteps(["willUpdateProps", "read3", "willUpdateProps", "willUpdateProps"]); + assert.verifySteps(["willUpdateProps", "willUpdateProps", "read3", "willUpdateProps", "willUpdateProps"]); }); QUnit.test("buttons in form view, new record", async function (assert) {