From be8472c8510e3584b09628287e7d2830505bbfb4 Mon Sep 17 00:00:00 2001 From: Mathieu Duckerts-Antoine Date: Fri, 24 Jun 2022 15:58:16 +0000 Subject: [PATCH] [FIX] kanban: click outside of a quick create record When on click outside of a quick create record, one wants - to remove the quick create record if it is not dirty - not to remove it if it is dirty with some exceptions: if the click is on a "Create", "Load more" or "+" (quick add) button This fix makes the external listener of KanbanRecordQuickCreate work as expected. Part-of: odoo/odoo#92475 --- .../kanban/kanban_record_quick_create.js | 20 +- .../static/tests/views/kanban_view_tests.js | 178 ++++++++++++++++++ 2 files changed, 195 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/views/kanban/kanban_record_quick_create.js b/addons/web/static/src/views/kanban/kanban_record_quick_create.js index fcb85a69d0d..2bf2d1912b4 100644 --- a/addons/web/static/src/views/kanban/kanban_record_quick_create.js +++ b/addons/web/static/src/views/kanban/kanban_record_quick_create.js @@ -5,6 +5,12 @@ import { FormRenderer } from "@web/views/form/form_renderer"; const { Component, onMounted, useExternalListener, useState, useRef } = owl; +const ACTION_SELECTORS = [ + ".o_kanban_quick_add", + ".o_kanban_load_more button", + ".o-kanban-button-new", +]; + export class KanbanRecordQuickCreate extends Component { setup() { this.uiService = useService("ui"); @@ -28,9 +34,17 @@ export class KanbanRecordQuickCreate extends Component { return; } const target = this.mousedownTarget || ev.target; - const gotClickedInside = this.rootRef.el.contains(target); - if (!gotClickedInside) { - this.cancel(false); + const gotClickedOutside = !this.rootRef.el.contains(target); + if (gotClickedOutside) { + let force = false; + for (const selector of ACTION_SELECTORS) { + const closestEl = target.closest(selector); + if (closestEl) { + force = true; + break; + } + } + this.cancel(force); } this.mousedownTarget = null; }, diff --git a/addons/web/static/tests/views/kanban_view_tests.js b/addons/web/static/tests/views/kanban_view_tests.js index cf97e4a68e2..e2532a37b86 100644 --- a/addons/web/static/tests/views/kanban_view_tests.js +++ b/addons/web/static/tests/views/kanban_view_tests.js @@ -9619,4 +9619,182 @@ QUnit.module("Views", (hooks) => { assert.containsOnce(target, ".o_kanban_group:nth-child(2) .o_kanban_record"); assert.verifySteps(["get_views", "web_read_group", "web_search_read", "web_search_read"]); }); + + QUnit.test("quick create record and click outside (no dirty input)", async (assert) => { + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + + +
+ +
+
+
+
`, + groupBy: ["bar"], + createRecord: () => { + assert.step("create record"); + }, + }); + + assert.containsNone(target, ".o_kanban_quick_create"); + + await quickCreateRecord(); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(1) .o_kanban_quick_create"); + + await click(target, ".o_control_panel"); + + assert.containsNone(target, ".o_kanban_quick_create"); + + await quickCreateRecord(); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(1) .o_kanban_quick_create"); + + await quickCreateRecord(1); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(2) .o_kanban_quick_create"); + + await click(target, ".o_kanban_load_more button"); + + assert.containsNone(target, ".o_kanban_quick_create"); + + await quickCreateRecord(); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(1) .o_kanban_quick_create"); + + assert.verifySteps([]); + + await click(target, ".o-kanban-button-new"); + + assert.verifySteps(["create record"]); + assert.containsNone(target, ".o_kanban_quick_create"); + }); + + QUnit.test("quick create record and click outside (with dirty input)", async (assert) => { + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + + +
+ +
+
+
+
`, + groupBy: ["bar"], + createRecord: () => { + assert.step("create record"); + }, + }); + + assert.containsNone(target, ".o_kanban_quick_create"); + + await quickCreateRecord(); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(1) .o_kanban_quick_create"); + + await editInput(target, ".o_kanban_quick_create [name=display_name] input", "ABC"); + + assert.strictEqual( + target.querySelector(".o_kanban_quick_create [name=display_name] input").value, + "ABC" + ); + + await click(target, ".o_control_panel"); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(1) .o_kanban_quick_create"); + assert.strictEqual( + target.querySelector(".o_kanban_quick_create [name=display_name] input").value, + "ABC" + ); + + await quickCreateRecord(1); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(2) .o_kanban_quick_create"); + assert.strictEqual( + target.querySelector(".o_kanban_quick_create [name=display_name] input").value, + "" + ); + + await editInput(target, ".o_kanban_quick_create [name=display_name] input", "ABC"); + + assert.strictEqual( + target.querySelector(".o_kanban_quick_create [name=display_name] input").value, + "ABC" + ); + + await click(target, ".o_kanban_load_more button"); + + assert.containsNone(target, ".o_kanban_quick_create"); + + await quickCreateRecord(); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(1) .o_kanban_quick_create"); + + await editInput(target, ".o_kanban_quick_create [name=display_name] input", "ABC"); + + assert.strictEqual( + target.querySelector(".o_kanban_quick_create [name=display_name] input").value, + "ABC" + ); + assert.verifySteps([]); + + await click(target, ".o-kanban-button-new"); + + assert.verifySteps(["create record"]); + assert.containsNone(target, ".o_kanban_quick_create"); + }); + + QUnit.test("quick create record and click on 'Load more'", async (assert) => { + await makeView({ + type: "kanban", + resModel: "partner", + serverData, + arch: ` + + + + +
+ +
+
+
+
`, + groupBy: ["bar"], + }); + + assert.containsNone(target, ".o_kanban_quick_create"); + + await quickCreateRecord(1); + + assert.containsOnce(target, ".o_kanban_quick_create"); + assert.containsOnce(target, ".o_kanban_group:nth-child(2) .o_kanban_quick_create"); + assert.containsN(target, ".o_kanban_group:nth-child(2) .o_kanban_record", 2); + + await click(target, ".o_kanban_load_more button"); + await nextTick(); + + assert.containsNone(target, ".o_kanban_quick_create"); + assert.containsN(target, ".o_kanban_group:nth-child(2) .o_kanban_record", 3); + }); });