[FIX] web: ButtonBox: do not display More for one button
Before this commit, it could happen that the More dropdown was displayed, but it only contained a single stat button. This isn't what we want, as that single button could simply be displayed instead of the More dropdown toggler. Task 3778382 closes odoo/odoo#156241 Related: odoo/enterprise#58565 Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
@@ -4,27 +4,30 @@ import { useService } from "@web/core/utils/hooks";
|
||||
import { Dropdown } from "@web/core/dropdown/dropdown";
|
||||
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Component, onWillRender } from "@odoo/owl";
|
||||
export class ButtonBox extends Component {
|
||||
setup() {
|
||||
const ui = useService("ui");
|
||||
this.getMaxButtons = () => [2, 3, 4, 6, 3, 4, 7][ui.size] || 7;
|
||||
onWillRender(() => {
|
||||
const maxVisibleButtons = [3, 4, 5, 7, 4, 5, 8][ui.size] || 8;
|
||||
const allVisibleButtons = Object.entries(this.props.slots)
|
||||
.filter(([_, slot]) => this.isSlotVisible(slot))
|
||||
.map(([slotName]) => slotName);
|
||||
if (allVisibleButtons.length <= maxVisibleButtons) {
|
||||
this.visibleButtons = allVisibleButtons;
|
||||
this.additionalButtons = [];
|
||||
this.isFull = allVisibleButtons.length === maxVisibleButtons;
|
||||
} else {
|
||||
// -1 for "More" dropdown
|
||||
this.visibleButtons = allVisibleButtons.slice(0, maxVisibleButtons - 1);
|
||||
this.additionalButtons = allVisibleButtons.slice(maxVisibleButtons - 1);
|
||||
this.isFull = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getButtons() {
|
||||
const maxVisibleButtons = this.getMaxButtons();
|
||||
const visible = [];
|
||||
const additional = [];
|
||||
for (const [slotName, slot] of Object.entries(this.props.slots)) {
|
||||
if (!("isVisible" in slot) || slot.isVisible) {
|
||||
if (visible.length >= maxVisibleButtons) {
|
||||
additional.push(slotName);
|
||||
} else {
|
||||
visible.push(slotName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { visible, additional };
|
||||
isSlotVisible(slot) {
|
||||
return !("isVisible" in slot) || slot.isVisible;
|
||||
}
|
||||
}
|
||||
ButtonBox.template = "web.Form.ButtonBox";
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="web.Form.ButtonBox" >
|
||||
<t t-set="allButtons" t-value="getButtons()" />
|
||||
<t t-set="visibleButtons" t-value="allButtons['visible']" />
|
||||
<t t-set="additionalButtons" t-value="allButtons['additional']" />
|
||||
<div class="o-form-buttonbox position-relative d-flex w-md-auto" t-attf-class="{{ visibleButtons.length >= getMaxButtons() ? 'o_full w-100' : 'o_not_full'}} {{this.props.class}}">
|
||||
<div class="o-form-buttonbox position-relative d-flex w-md-auto" t-attf-class="{{ isFull ? 'o_full w-100' : 'o_not_full'}} {{this.props.class}}">
|
||||
<t t-slot="{{ button_value }}" t-foreach="visibleButtons" t-as="button" t-key="button_value"/>
|
||||
<t t-if="additionalButtons.length" >
|
||||
<Dropdown position="'bottom-end'" togglerClass="'o_button_more btn btn-outline-secondary d-flex justify-content-center align-items-center'" menuClass="'o_dropdown_more position-absolute top-100 p-0 border-0'" class="'oe_stat_button btn position-relative p-0 border-0'">
|
||||
|
||||
@@ -28,6 +28,7 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
|
||||
fields: {
|
||||
display_name: { type: "char", string: "Display Name" },
|
||||
trululu: { type: "many2one", string: "Trululu", relation: "partner" },
|
||||
boolean: { type: "boolean", string: "Bool" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, display_name: "first record", trululu: 4 },
|
||||
@@ -479,4 +480,38 @@ QUnit.module("Mobile Views", ({ beforeEach }) => {
|
||||
await nextTick();
|
||||
assert.verifySteps(["post"]);
|
||||
});
|
||||
|
||||
QUnit.test("button box with 3/4 buttons (close to threshold)", async (assert) => {
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<sheet>
|
||||
<div name="button_box">
|
||||
<button>MyButton</button>
|
||||
<button>MyButton2</button>
|
||||
<button>MyButton3</button>
|
||||
<button invisible="not boolean">MyButton4</button>
|
||||
</div>
|
||||
<field name="boolean"/>
|
||||
</sheet>
|
||||
</form>`,
|
||||
resId: 2,
|
||||
});
|
||||
|
||||
// 3 buttons to display -> no "More" dropdown
|
||||
assert.containsNone(fixture, ".o_field_widget[name=boolean] input:checked");
|
||||
assert.containsN(fixture, ".o-form-buttonbox > .oe_stat_button", 3);
|
||||
assert.containsNone(fixture, ".o-form-buttonbox .o_button_more");
|
||||
|
||||
// 4 buttons to display -> 2 buttons visible + 2 inside the "More" dropdown
|
||||
await click(fixture.querySelector(".o_field_widget[name=boolean] input"));
|
||||
assert.containsN(fixture, ".o-form-buttonbox > .oe_stat_button", 3);
|
||||
assert.containsOnce(fixture, ".o-form-buttonbox .oe_stat_button .o_button_more");
|
||||
|
||||
await click(fixture.querySelector(".o_button_more"));
|
||||
assert.containsN(fixture, ".o_dropdown_more .oe_stat_button", 2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -430,7 +430,7 @@ QUnit.module("Views", (hooks) => {
|
||||
});
|
||||
return {
|
||||
bus: new EventBus(),
|
||||
size: 9,
|
||||
size: 6,
|
||||
isSmall: false,
|
||||
};
|
||||
},
|
||||
@@ -8391,7 +8391,7 @@ QUnit.module("Views", (hooks) => {
|
||||
});
|
||||
|
||||
QUnit.test("correct amount of buttons", async function (assert) {
|
||||
let screenSize = 7;
|
||||
let screenSize = 6;
|
||||
const uiService = {
|
||||
start(env) {
|
||||
Object.defineProperty(env, "isSmall", {
|
||||
@@ -8445,7 +8445,7 @@ QUnit.module("Views", (hooks) => {
|
||||
await assertFormContainsNButtonsWithSizeClass(0, 2);
|
||||
await assertFormContainsNButtonsWithSizeClass(1, 3);
|
||||
await assertFormContainsNButtonsWithSizeClass(2, 4);
|
||||
await assertFormContainsNButtonsWithSizeClass(3, 6);
|
||||
await assertFormContainsNButtonsWithSizeClass(3, 7);
|
||||
await assertFormContainsNButtonsWithSizeClass(4, 3);
|
||||
await assertFormContainsNButtonsWithSizeClass(5, 4);
|
||||
await assertFormContainsNButtonsWithSizeClass(6, 7);
|
||||
|
||||
Reference in New Issue
Block a user