[FIX] web: settings form view: save on click on an action button

On the res.config.settings form view, click on button that will do an action
e.g. defined as some flavor of `<button type="object" name="myMethod" />`

Before this commit, this did not work as we never fully created the res.config.settings record in python
hence, when executing myMethod on the model res.config.settings, the ID was unset, pointing to no record.

After this commit, we "create" in python the transient res.config.settings record before doing anything.

closes odoo/odoo#97428

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Lucas Perais
2022-08-04 20:11:03 +02:00
parent 1ac43fab05
commit 9b81ddb993
2 changed files with 104 additions and 19 deletions
@@ -20,26 +20,30 @@ export class SettingsFormController extends formView.Controller {
) {
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();
},
cancel: () => {},
stayHere: () => {
_continue = false;
},
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();
},
{ onClose: resolve }
);
cancel: async () => {
await this.model.root.discard();
await this.model.root.save({ stayInEdition: true });
_continue = true;
resolve();
},
stayHere: () => {
_continue = false;
resolve();
},
});
});
} else {
if (clickParams.name === "execute") {
_continue = await this.model.root.save({ stayInEdition: true });
}
_continue = await this.model.root.save({ stayInEdition: true });
}
return _continue;
};
@@ -11,6 +11,7 @@ import {
import { editSearch } from "@web/../tests/search/helpers";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { createWebClient, doAction } from "@web/../tests/webclient/helpers";
import { registry } from "@web/core/registry";
let target;
let serverData;
@@ -307,7 +308,7 @@ QUnit.module("SettingsFormView", (hooks) => {
QUnit.test(
"settings views does not read existing id when coming back in breadcrumbs",
async function (assert) {
assert.expect(9);
assert.expect(11);
serverData.actions = {
1: {
@@ -373,7 +374,9 @@ QUnit.module("SettingsFormView", (hooks) => {
assert.notOk(target.querySelector(".o_field_boolean input").disabled);
assert.verifySteps([
"get_views", // initial setting action
"onchange", // this is a setting view => create new record
"onchange", // this is a setting view => new record transient record
"create", // create the record before doing the action
"read", // read the created record
"get_views", // for other action in breadcrumb,
"web_search_read", // with a searchread
"onchange", // when we come back, we want to restart from scratch
@@ -647,6 +650,84 @@ QUnit.module("SettingsFormView", (hooks) => {
}
);
QUnit.test("clicking a button with dirty settings -- save", async (assert) => {
registry.category("services").add(
"action",
{
start() {
return {
doActionButton(params) {
assert.step(`action executed ${JSON.stringify(params)}`);
},
};
},
},
{ force: true }
);
await makeView({
type: "form",
arch: `
<form js_class="base_settings">
<field name="foo" />
<button type="object" name="mymethod" class="myBtn"/>
</form>`,
serverData,
resModel: "res.config.settings",
mockRPC(route, args) {
assert.step(args.method);
},
});
assert.verifySteps(["get_views", "onchange"]);
await click(target, ".o_field_boolean input[type='checkbox']");
await click(target, ".myBtn");
await click(target, ".modal .btn-primary");
assert.verifySteps([
"create",
"read",
'action executed {"name":"execute","type":"object","resModel":"res.config.settings","resId":1,"resIds":[1],"context":{"lang":"en","uid":7,"tz":"taht"},"buttonContext":{}}',
]);
});
QUnit.test("clicking a button with dirty settings -- discard", async (assert) => {
registry.category("services").add(
"action",
{
start() {
return {
doActionButton(params) {
assert.step(`action executed ${JSON.stringify(params)}`);
},
};
},
},
{ force: true }
);
await makeView({
type: "form",
arch: `
<form js_class="base_settings">
<field name="foo" />
<button type="object" name="mymethod" class="myBtn"/>
</form>`,
serverData,
resModel: "res.config.settings",
mockRPC(route, args) {
assert.step(args.method);
},
});
assert.verifySteps(["get_views", "onchange"]);
await click(target, ".o_field_boolean input[type='checkbox']");
await click(target, ".myBtn");
await click(target.querySelectorAll(".modal .btn-secondary")[1]);
assert.verifySteps([
"create",
"read",
'action executed {"context":{"lang":"en","uid":7,"tz":"taht"},"type":"object","name":"mymethod","resModel":"res.config.settings","resId":1,"resIds":[1],"buttonContext":{}}',
]);
});
QUnit.test(
"clicking on a button with noSaveDialog will not show discard warning",
async function (assert) {