[IMP] web: add control action button in x2many
This commit adds the possibility to define control action buttons in the
arch of a list view for a x2many. These buttons are action buttons that
will be placed in the same place as the control create ("Add a line").
The goal of this new feature is to offer the possibility to define
buttons that execute actions linked to an x2many.
Here is an example where we define a control create and a control action
button:
<tree>
<control>
<create string="Create" context="{}" />
<button string="Action Button" name="do_something"
class="btn-link" type="object" context="{'parent_id': parent.id}"/>
</control>
<field name="display_name"/>
</tree>
Part-of: odoo/odoo#97558
This commit is contained in:
@@ -125,11 +125,21 @@ export class ListArchParser extends XMLParser {
|
||||
}))
|
||||
.filter((button) => button.modifiers.invisible !== true);
|
||||
return false;
|
||||
} else if (node.tagName === "create") {
|
||||
creates.push({
|
||||
context: node.getAttribute("context"),
|
||||
description: node.getAttribute("string"),
|
||||
});
|
||||
} else if (node.tagName === "control") {
|
||||
for (const childNode of node.children) {
|
||||
if (childNode.tagName === "button") {
|
||||
creates.push({
|
||||
type: "button",
|
||||
...processButton(childNode),
|
||||
});
|
||||
} else if (childNode.tagName === "create") {
|
||||
creates.push({
|
||||
type: "create",
|
||||
context: childNode.getAttribute("context"),
|
||||
string: childNode.getAttribute("string"),
|
||||
});
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (["tree", "list"].includes(node.tagName)) {
|
||||
const activeActions = {
|
||||
|
||||
@@ -330,10 +330,16 @@
|
||||
}
|
||||
|
||||
.o_field_x2many_list_row_add, .o_group_field_row_add {
|
||||
a:focus, a:active {
|
||||
a:focus, a:active, button:focus, button:active {
|
||||
color: $link-hover-color;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
font-weight: 400;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ export class ListRenderer extends Component {
|
||||
|
||||
this.creates = this.props.archInfo.creates.length
|
||||
? this.props.archInfo.creates
|
||||
: [{ description: this.env._t("Add a line") }];
|
||||
: [{ type: "create", string: this.env._t("Add a line") }];
|
||||
|
||||
this.cellToFocus = null;
|
||||
this.activeRowId = null;
|
||||
|
||||
@@ -81,14 +81,25 @@
|
||||
>
|
||||
<t t-foreach="creates" t-as="create" t-key="create_index">
|
||||
<a
|
||||
t-if="create.type === 'create'"
|
||||
href="#"
|
||||
role="button"
|
||||
t-att-class="create_index !== 0 ? 'ml16' : ''"
|
||||
t-att-tabindex="props.list.editedRecord ? '-1' : '0'"
|
||||
t-on-click.stop.prevent="() => this.props.onAdd({context: create.context})"
|
||||
>
|
||||
<t t-esc="create.description"/>
|
||||
<t t-esc="create.string"/>
|
||||
</a>
|
||||
<ViewButton
|
||||
t-if="create.type === 'button'"
|
||||
className="`${create.className} ${create_index !== 0 ? 'ml16' : ''}`"
|
||||
clickParams="create.clickParams"
|
||||
icon="create.icon"
|
||||
record="props.list"
|
||||
string="create.string"
|
||||
title="create.title"
|
||||
tabindex="props.list.editedRecord ? '-1' : '0'"
|
||||
/>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -9099,6 +9099,45 @@ QUnit.module("Fields", (hooks) => {
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("o2m add an action button control", async function (assert) {
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
resId: 2,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="p">
|
||||
<tree>
|
||||
<control>
|
||||
<create string="Create" context="{}" />
|
||||
<button string="Action Button" name="do_something" class="btn-link" type="object" context="{'parent_id': parent.id}"/>
|
||||
</control>
|
||||
<field name="display_name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</form>`,
|
||||
mockRPC(route, args) {
|
||||
if (args.method === "do_something") {
|
||||
assert.step("do_something");
|
||||
assert.strictEqual(args.kwargs.context.parent_id, 2);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
await clickEdit(target);
|
||||
assert.deepEqual(
|
||||
[...target.querySelector(".o_field_x2many_list_row_add").children].map(
|
||||
(el) => el.textContent
|
||||
),
|
||||
["Create", "Action Button"]
|
||||
);
|
||||
|
||||
await click(target, ".o_field_x2many_list_row_add button");
|
||||
assert.verifySteps(["do_something"]);
|
||||
});
|
||||
|
||||
QUnit.test("o2m add a line custom control create align with handle", async function (assert) {
|
||||
await makeView({
|
||||
type: "form",
|
||||
|
||||
@@ -415,7 +415,8 @@
|
||||
<rng:element name="create">
|
||||
<rng:ref name="overload"/>
|
||||
<rng:attribute name="string"/>
|
||||
<rng:attribute name="context"/>
|
||||
<rng:optional><rng:attribute name="context"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="name"/></rng:optional>
|
||||
</rng:element>
|
||||
</rng:define>
|
||||
|
||||
@@ -425,6 +426,7 @@
|
||||
<rng:oneOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="create"/>
|
||||
<rng:ref name="button"/>
|
||||
</rng:choice>
|
||||
</rng:oneOrMore>
|
||||
</rng:element>
|
||||
|
||||
Reference in New Issue
Block a user