[IMP] web: StateSelectionField: add current value in the dropdown

This commit revamps the UX of the StateSelection field widget. Now, instead
of filtering the options by removing the current selected value, the field
displays the entire list in the dropdown, and the selected item has a
checkmark to indicate its status.

This allows us to remove the tooltip, since its presence was not useful
anymore, and was unintuitive to use. This changes required to adapt some
tests asserting its presence, as well as the number of items shown in the
dropdown menu.

task #3177182

closes odoo/odoo#113203

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
luvi
2023-02-24 09:10:46 +01:00
parent 93af90cc1d
commit 0ef798a3db
4 changed files with 33 additions and 36 deletions
@@ -51,9 +51,6 @@ export class StateSelectionField extends Component {
return [state, this.props.record.data[`legend_${state}`] || label];
});
}
get availableOptions() {
return this.options.filter((o) => o[0] !== this.currentValue);
}
get currentValue() {
return this.props.value || this.options[0][0];
}
@@ -9,19 +9,19 @@
</button>
</t>
<t t-else="">
<Dropdown tooltip="label" togglerClass="'btn btn-link d-flex p-0'">
<Dropdown togglerClass="'btn btn-link d-flex p-0'">
<t t-set-slot="toggler">
<div class="d-flex align-items-center">
<span t-attf-class="o_status {{ statusColor(currentValue) }} "/>
<span t-if="showLabel" class="o_status_label ms-1" t-esc="label"/>
</div>
</t>
<t t-foreach="availableOptions" t-as="option" t-key="option[0]">
<DropdownItem onSelected="() => this.updateRecord(option[0])">
<div class="d-flex align-items-center">
<span t-attf-class="o_status {{ statusColor(option[0]) }} "/>
<span class="ms-2" t-esc="option[1]"/>
</div>
<t t-foreach="options" t-as="option" t-key="option[0]">
<DropdownItem
class="`d-flex align-items-center ${option[0] === currentValue ? 'active' : ''}`"
onSelected="() => this.updateRecord(option[0])">
<span t-attf-class="o_status ms-3 {{ statusColor(option[0]) }} "/>
<span t-esc="option[1]"/>
</DropdownItem>
</t>
</Dropdown>
@@ -83,11 +83,6 @@ QUnit.module("Fields", (hooks) => {
"should not have one green status since selection is the second, blocked state"
);
assert.containsNone(target, ".dropdown-menu", "there should not be a dropdown");
assert.strictEqual(
target.querySelector(".o_field_state_selection .dropdown-toggle").dataset.tooltip,
"Blocked",
"tooltip attribute has the right text"
);
// Click on the status button to make the dropdown appear
await click(target, ".o_field_widget.o_field_state_selection .o_status");
@@ -95,8 +90,13 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
target,
".dropdown-menu .dropdown-item",
2,
"there should be two options in the dropdown"
3,
"there should be three options in the dropdown"
);
assert.hasClass(
target.querySelector(".dropdown-menu .dropdown-item:nth-child(2)"),
"active",
"current value has a checkmark"
);
// Click on the first option, "Normal"
@@ -141,8 +141,8 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
target,
".dropdown-menu .dropdown-item",
2,
"there should be two options in the dropdown"
3,
"there should be three options in the dropdown"
);
// Click on the last option, "Done"
@@ -297,8 +297,8 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
target,
".dropdown-menu .dropdown-item",
2,
"there should be two options in the dropdown"
3,
"there should be three options in the dropdown"
);
// Click on the first option, "Normal"
@@ -352,8 +352,8 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
target,
".dropdown-menu .dropdown-item",
2,
"there should be two options in the dropdown"
3,
"there should be three options in the dropdown"
);
// Click on another row
@@ -382,8 +382,8 @@ QUnit.module("Fields", (hooks) => {
assert.containsN(
target,
".dropdown-menu .dropdown-item",
2,
"there should be two options in the dropdown"
3,
"there should be three options in the dropdown"
);
// Click on the last option, "Done"
@@ -495,17 +495,17 @@ QUnit.module("Fields", (hooks) => {
});
await click(target, ".o_status");
let dropdownItemTexts = [...target.querySelectorAll(".dropdown-item")].map(
(el) => el.textContent
);
assert.deepEqual(dropdownItemTexts, ["Custom normal", "Custom done"]);
let dropdownItemTexts = [
...target.querySelectorAll(".o_field_state_selection .dropdown-item"),
].map((el) => el.textContent);
assert.deepEqual(dropdownItemTexts, ["Custom normal", "Custom blocked", "Custom done"]);
await click(target.querySelector(".dropdown-item .o_status"));
await click(target, ".o_status");
dropdownItemTexts = [...target.querySelectorAll(".dropdown-item")].map(
(el) => el.textContent
);
assert.deepEqual(dropdownItemTexts, ["Custom blocked", "Custom done"]);
dropdownItemTexts = [
...target.querySelectorAll(".o_field_state_selection .dropdown-item"),
].map((el) => el.textContent);
assert.deepEqual(dropdownItemTexts, ["Custom normal", "Custom blocked", "Custom done"]);
});
QUnit.test("works when required in a readonly view ", async function (assert) {
@@ -534,7 +534,7 @@ QUnit.module("Fields", (hooks) => {
});
await click(target, ".o_field_state_selection button");
const doneItem = target.querySelectorAll(".dropdown-item")[1]; // item "done";
const doneItem = target.querySelectorAll(".dropdown-item")[2]; // item "done";
await click(doneItem);
assert.verifySteps(["write"]);
@@ -2561,7 +2561,7 @@ QUnit.module("Views", (hooks) => {
// Select state in kanban
await click(getCard(0), ".o_status");
await click(getCard(0), ".o_field_state_selection .dropdown-item:first-child");
await click(getCard(0), ".o_field_state_selection .dropdown-item:nth-child(2)");
assert.hasClass(
target.querySelector(".o_status"),
@@ -11651,7 +11651,7 @@ QUnit.module("Views", (hooks) => {
// Changes the state of the first record of the "Yes" column to "def"
// The updated record should remain visible
await click(getCard(2), ".o_status");
await click(getCard(2), ".o_field_state_selection .dropdown-item:first-child");
await click(getCard(2), ".o_field_state_selection .dropdown-item:nth-child(2)");
assert.deepEqual(getCounters(), ["1", "1"]);
assert.containsN(getColumn(1), ".o_kanban_record", 2);