[FIX] web: useViewButtons: add beforeExecute param

This rev allows the function built by the useViewButtons hook to take
a beforeExecute callback at call time, in addition to the existing
beforeExecuteAction callback that we can pass to the hook, at the
function's build time.

The rationale for this is to allow any caller to prevent the execution
of the action represented by the clickParams at the call level. It is
useful to check if a user is allowed business-wise to execute an action.

Part-of: odoo/odoo#78221
This commit is contained in:
Lucas Perais
2022-07-22 16:21:43 +02:00
committed by Géry Debongnie
parent 6ebf19b189
commit e3a54289ac
2 changed files with 91 additions and 3 deletions
@@ -22,6 +22,10 @@ function enableButtons(el, manuallyDisabledButtons) {
}
}
}
function undefinedAsTrue(val) {
return typeof val === "undefined" || val;
}
export function useViewButtons(model, ref, options = {}) {
const action = useService("action");
const dialog = useService("dialog");
@@ -33,12 +37,17 @@ export function useViewButtons(model, ref, options = {}) {
return true;
});
useSubEnv({
async onClickViewButton({ clickParams, record }) {
async onClickViewButton({ clickParams, record, beforeExecute }) {
const manuallyDisabledButtons = disableButtons(getEl());
async function execute() {
const _continue = await beforeExecuteAction(clickParams);
if (typeof _continue !== "undefined" && !_continue) {
let _continue = true;
if (beforeExecute) {
_continue = undefinedAsTrue(await beforeExecute());
}
_continue = _continue && undefinedAsTrue(await beforeExecuteAction(clickParams));
if (!_continue) {
enableButtons(getEl(), manuallyDisabledButtons);
return;
}
@@ -0,0 +1,79 @@
/** @odoo-module */
import { useViewButtons } from "@web/views/view_button/view_button_hook";
import { setupViewRegistries } from "./helpers";
import { click, getFixture } from "../helpers/utils";
import { makeTestEnv } from "../helpers/mock_env";
import { registry } from "@web/core/registry";
const { useRef, mount, Component, xml } = owl;
QUnit.module("UseViewButton tests", (hooks) => {
let target;
hooks.beforeEach(() => {
target = getFixture();
setupViewRegistries();
});
QUnit.test("action can be prevented", async (assert) => {
registry.category("services").add(
"action",
{
start() {
return {
doActionButton() {
assert.step("doActionButton");
},
};
},
},
{ force: true }
);
let executeInHook;
let executeInHandler;
class MyComponent extends Component {
setup() {
const rootRef = useRef("root");
useViewButtons({}, rootRef, {
beforeExecuteAction: () => {
assert.step("beforeExecuteAction in hook");
return executeInHook;
},
});
}
onClick() {
const record = {
resIds: [3],
resId: 3,
load: () => {},
};
const clickParams = {};
const beforeExecute = () => {
assert.step("beforeExecuteAction on handler");
return executeInHandler;
};
this.env.onClickViewButton({ beforeExecute, record, clickParams });
}
}
MyComponent.template = xml`<div t-ref="root" t-on-click="onClick" class="myComponent">Some text</div>`;
const env = await makeTestEnv();
await mount(MyComponent, target, { env, props: {} });
await click(target, ".myComponent");
assert.verifySteps([
"beforeExecuteAction on handler",
"beforeExecuteAction in hook",
"doActionButton",
]);
executeInHook = false;
await click(target, ".myComponent");
assert.verifySteps(["beforeExecuteAction on handler", "beforeExecuteAction in hook"]);
executeInHandler = false;
await click(target, ".myComponent");
assert.verifySteps(["beforeExecuteAction on handler"]);
});
});