From 0dfee1606b3de0815989d1e1d9a037f66b47daff Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Thu, 29 Feb 2024 08:29:15 +0100 Subject: [PATCH] [FIX] web: can edit SelectionField in draggable kanban Before this commit, if a SelectionField was used in a kanban view alongside the HandleField (enabling re-sequencing, i.e. drag&drop), the "select" element couldn't be edited. This is because the d&d feature calls preventDefault on almost all "pointerdown" events occuring in the card, and the "pointerdown" event is the one that opens the select. There's no usecase in 17.0, but there's one in master, in the product document kanban view. We fix this in 17.0 which is the version that introduced the kanban version of the SelectionField. closes odoo/odoo#155827 Signed-off-by: Julien Mougenot (jum) --- .../views/fields/selection/selection_field.js | 21 +++++-- .../src/views/kanban/kanban_renderer.js | 2 +- .../views/fields/selection_field_tests.js | 60 ++++++++++++++----- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/addons/web/static/src/views/fields/selection/selection_field.js b/addons/web/static/src/views/fields/selection/selection_field.js index 8c8f269990c..c69a56e79ca 100644 --- a/addons/web/static/src/views/fields/selection/selection_field.js +++ b/addons/web/static/src/views/fields/selection/selection_field.js @@ -72,15 +72,24 @@ export class SelectionField extends Component { switch (this.type) { case "many2one": if (value === false) { - this.props.record.update({ [this.props.name]: false }, { save: this.props.autosave }); + this.props.record.update( + { [this.props.name]: false }, + { save: this.props.autosave } + ); } else { - this.props.record.update({ - [this.props.name]: this.options.find((option) => option[0] === value), - }, { save: this.props.autosave }); + this.props.record.update( + { + [this.props.name]: this.options.find((option) => option[0] === value), + }, + { save: this.props.autosave } + ); } break; case "selection": - this.props.record.update({ [this.props.name]: value }, { save: this.props.autosave }); + this.props.record.update( + { [this.props.name]: value }, + { save: this.props.autosave } + ); break; } } @@ -100,7 +109,7 @@ export const selectionField = { }; if (viewType === "kanban") { props.readonly = dynamicInfo.readonly; - }; + } return props; }, }; diff --git a/addons/web/static/src/views/kanban/kanban_renderer.js b/addons/web/static/src/views/kanban/kanban_renderer.js index 67dc8ccf344..e06683557cc 100644 --- a/addons/web/static/src/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/views/kanban/kanban_renderer.js @@ -97,7 +97,7 @@ export class KanbanRenderer extends Component { // Params ref: this.rootRef, elements: ".o_draggable", - ignore: ".dropdown", + ignore: ".dropdown,select", groups: () => this.props.list.isGrouped && ".o_kanban_group", connectGroups: () => this.canMoveRecords, cursor: "move", diff --git a/addons/web/static/tests/views/fields/selection_field_tests.js b/addons/web/static/tests/views/fields/selection_field_tests.js index e71b381234c..dddc9743c23 100644 --- a/addons/web/static/tests/views/fields/selection_field_tests.js +++ b/addons/web/static/tests/views/fields/selection_field_tests.js @@ -405,7 +405,7 @@ QUnit.module("Fields", (hooks) => { [...target.querySelectorAll(".o_field_widget[name='color'] option")].map( (option) => option.value ), - ["false", "\"red\"", "\"black\""] + ["false", '"red"', '"black"'] ); }); @@ -440,13 +440,13 @@ QUnit.module("Fields", (hooks) => { QUnit.test( "SelectionField don't open form view on click in kanban view", async function (assert) { - assert.expect(1); + assert.expect(1); - await makeView({ - type: "kanban", - resModel: "partner", - serverData, - arch: ` + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` @@ -456,15 +456,16 @@ QUnit.module("Fields", (hooks) => { `, - domain: [["id", "=", 1]], - selectRecord: () => { - assert.step("selectRecord"); - }, - }); + domain: [["id", "=", 1]], + selectRecord: () => { + assert.step("selectRecord"); + }, + }); - await click(target, ".o_field_widget[name='color'] select"); - assert.verifySteps([]); - }); + await click(target, ".o_field_widget[name='color'] select"); + assert.verifySteps([]); + } + ); QUnit.test("SelectionField is disabled if field readonly", async function (assert) { assert.expect(1); @@ -523,4 +524,33 @@ QUnit.module("Fields", (hooks) => { "field should be readonly" ); }); + + QUnit.test("SelectionField in kanban view with handle widget", async function (assert) { + // When records are draggable, most pointerdown events are default prevented. This test + // comes with a fix that blacklists "select" elements, i.e. pointerdown events on such + // elements aren't default prevented, because if they were, the select element can't be + // opened. The test is a bit artificial but there's no other way to test the scenario, as + // using editSelect simply triggers a "change" event, which obviously always works. + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + + +
+ +
+
+
+
`, + }); + + const ev = new PointerEvent("pointerdown", { bubbles: true, cancelable: true }); + const select = target.querySelector(".o_kanban_record .o_field_widget[name=color] select"); + select.dispatchEvent(ev); + assert.notOk(ev.defaultPrevented); + }); });