[FIX] web: ListViewHeaderButton use the correct context

Before this commit, when a ListViewHeaderButton was clicked, the view
context wasn't sent to the server.

As ListViewHeaderButton shows, the onClickViewButton API is not correct.
It expects a record in params but this is not correct in the case of
ListViewHeaderButton. So we decided not to pass a record but a getParams
callback that allows us to calculate the params when we need them.

Part-of: odoo/odoo#97558
This commit is contained in:
FrancoisGe
2022-08-23 16:28:57 +02:00
parent 221ee0cdc3
commit b2a0a1c7d3
9 changed files with 65 additions and 50 deletions
@@ -17,28 +17,24 @@ export class ExpenseFormController extends FormController {
const t = this.env._t;
const previousOnClickViewButton = this.env.onClickViewButton;
useSubEnv({
async onClickViewButton({ clickParams, record}) {
if (clickParams.name === "action_submit_expenses") {
if (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.data.id],
);
previousOnClickViewButton({ clickParams, record});
},
cancel: () => {},
});
} else {
previousOnClickViewButton({ clickParams, record});
}
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({ clickParams, record});
previousOnClickViewButton(params);
}
}
},
});
}
}
@@ -48,4 +44,4 @@ export const ExpenseFormView = {
Controller: ExpenseFormController,
};
registry.category("views").add('hr_expense_form_view', ExpenseFormView);
registry.category("views").add("hr_expense_form_view", ExpenseFormView);
@@ -20,23 +20,27 @@ const { Component, onWillStart, useSubEnv, useEffect, useRef } = owl;
export class ListViewHeaderButton extends ViewButton {
async onClick() {
const clickParams = this.props.clickParams;
const resIds = await this.props.getSelectedResIds();
const resModel = this.props.resModel;
const { clickParams, list } = this.props;
const resIds = await list.getResIds(true);
clickParams.buttonContext = {
active_domain: this.props.domain,
// active_id: resIds[0], // FGE TODO
active_ids: resIds,
active_model: resModel,
active_model: list.resModel,
};
this.env.onClickViewButton({
clickParams,
record: { resModel, resIds },
getResParams: () => ({
context: list.context,
evalContext: list.evalContext,
resModel: list.resModel,
resIds,
}),
});
}
}
ListViewHeaderButton.props = [...ViewButton.props, "resModel", "domain", "getSelectedResIds"];
ListViewHeaderButton.props = [...ViewButton.props, "list", "domain"];
// -----------------------------------------------------------------------------
@@ -53,12 +53,11 @@
<t t-if="nbSelected">
<t t-foreach="archInfo.headerButtons" t-as="button" t-key="button.id">
<ListViewHeaderButton
list="model.root"
clickParams="button.clickParams"
defaultRank="button.defaultRank"
domain="props.domain"
icon="button.icon"
getSelectedResIds.bind="getSelectedResIds"
resModel="model.root.resModel"
string="button.string"
title="button.title"
/>
@@ -1,6 +1,7 @@
/** @odoo-module */
import { DROPDOWN } from "@web/core/dropdown/dropdown";
import { pick } from "@web/core/utils/objects";
import { debounce as debounceFn } from "@web/core/utils/timing";
const { Component } = owl;
@@ -84,7 +85,8 @@ export class ViewButton extends Component {
}
this.env.onClickViewButton({
clickParams: this.clickParams,
record: this.props.record,
getResParams: () =>
pick(this.props.record, "context", "evalContext", "resModel", "resId", "resIds"),
beforeExecute: () => {
if (this.env[DROPDOWN]) {
this.env[DROPDOWN].close();
@@ -37,7 +37,7 @@ export function useViewButtons(model, ref, options = {}) {
return true;
});
useSubEnv({
async onClickViewButton({ clickParams, record, beforeExecute }) {
async onClickViewButton({ clickParams, getResParams, beforeExecute }) {
const manuallyDisabledButtons = disableButtons(getEl());
async function execute() {
@@ -51,15 +51,13 @@ export function useViewButtons(model, ref, options = {}) {
enableButtons(getEl(), manuallyDisabledButtons);
return;
}
const resId = record.resId;
const resIds = record.resIds || model.resIds;
const params = getResParams();
const resId = params.resId;
const resIds = params.resIds || model.resIds;
let buttonContext = {};
if (clickParams.context) {
if (typeof clickParams.context === "string") {
const valuesForEval = Object.assign({}, record.evalContext, {
active_id: resId,
active_ids: resIds,
});
const valuesForEval = Object.assign({}, params.evalContext);
buttonContext = evaluateExpr(clickParams.context, valuesForEval);
} else {
buttonContext = clickParams.context;
@@ -69,13 +67,13 @@ export function useViewButtons(model, ref, options = {}) {
Object.assign(buttonContext, clickParams.buttonContext);
}
const doActionParams = Object.assign({}, clickParams, {
resModel: record.resModel || model.resModel,
resModel: params.resModel || model.resModel,
resId,
resIds,
context: record.context || {}, //LPE FIXME new Context(payload.env.context).eval();
context: params.context || {}, //LPE FIXME new Context(payload.env.context).eval();
buttonContext,
onClose: async () => {
const reload = options.reload || (() => record.model.root.load());
const reload = options.reload || (() => model.root.load());
await reload();
comp.render(true); // FIXME WOWL reactivity
},
@@ -1,6 +1,7 @@
/** @odoo-module **/
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";
@@ -91,7 +92,8 @@ export class SettingsFormController extends formView.Controller {
name: "execute",
type: "object",
},
record: this.model.root,
getResParams: () =>
pick(this.model.root, "context", "evalContext", "resModel", "resId", "resIds"),
});
}
@@ -101,7 +103,8 @@ export class SettingsFormController extends formView.Controller {
name: "cancel",
type: "object",
},
record: this.model.root,
getResParams: () =>
pick(this.model.root, "context", "evalContext", "resModel", "resId", "resIds"),
});
}
}
@@ -765,6 +765,9 @@ QUnit.module("Views", (hooks) => {
</header>
<field name="foo" />
</tree>`,
context: {
paf: "pif",
},
});
patchWithCleanup(list.env.services.action, {
doActionButton: async (params) => {
@@ -784,7 +787,12 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(resModel, "foo");
assert.deepEqual([...resIds], [1]);
assert.strictEqual(JSON.stringify(context), "{}");
assert.deepEqual(context, {
lang: "en",
paf: "pif",
tz: "taht",
uid: 7,
});
},
});
await click(
@@ -835,7 +843,11 @@ QUnit.module("Views", (hooks) => {
active_model: "foo",
});
assert.strictEqual(JSON.stringify(context), "{}");
assert.deepEqual(context, {
lang: "en",
tz: "taht",
uid: 7,
});
assert.strictEqual(resModel, "foo");
assert.deepEqual([...resIds], [1, 2, 3, 4]);
},
@@ -46,17 +46,16 @@ QUnit.module("UseViewButton tests", (hooks) => {
}
onClick() {
const record = {
const getResParams = () => ({
resIds: [3],
resId: 3,
load: () => {},
};
});
const clickParams = {};
const beforeExecute = () => {
assert.step("beforeExecuteAction on handler");
return executeInHandler;
};
this.env.onClickViewButton({ beforeExecute, record, clickParams });
this.env.onClickViewButton({ beforeExecute, getResParams, clickParams });
}
}
MyComponent.template = xml`<div t-ref="root" t-on-click="onClick" class="myComponent">Some text</div>`;
@@ -1,6 +1,7 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { pick } from "@web/core/utils/objects";
const { Component } = owl;
@@ -13,9 +14,10 @@ class RedirectField extends Component {
this.env.onClickViewButton({
clickParams: {
type: "object",
name: "open_website_url"
name: "open_website_url",
},
record: this.props.record,
getResParams: () =>
pick(this.props.record, "context", "evalContext", "resModel", "resId", "resIds"),
});
}
}