[FIX] web,project: Restore kanban drag&drop in Firefox

Before this commit, the drag & drop feature for the Project "Tasks"
kanban view did not work if the drag sequence was initiated from the
title of the card.

This was due to the "o_kanban_record_headings" class having the CSS rule
`overflow: hidden`, because of a well known 6 year-long-and-counting
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1352061

Namely: mouse enter|leave events won't fire on anything underneath
elements having `overflow: hidden`.

This commit solves this issue by introducing a dedicated class name
'o_dragged' to all elements dragged using the `draggable_hook_builder`,
and defining on it the CSS attributes that were assigned in JS before,
as well as `pointer-events: none` on itself and all its children to
avoid the issue mentioned above.

Also in this commit: fixed a syntax error in a CSS rule in project's
"task_name_with_subtask_count_char_field" widget.

closes odoo/odoo#105353

Related: odoo/enterprise#33774
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Julien Mougenot
2022-11-10 12:21:57 +01:00
parent f0eb6f3906
commit cda3396546
7 changed files with 34 additions and 17 deletions
@@ -6,7 +6,7 @@
<span
class="text-muted ms-2"
t-out="formattedSubtaskCount"
style="{ font-weight: normal; }"
style="font-weight: normal;"
/>
</xpath>
</t>
@@ -81,6 +81,7 @@ const DEFAULT_DEFAULT_PARAMS = {
threshold: 30,
},
};
const DRAGGED_CLASS = "o_dragged";
const LEFT_CLICK = 0;
const MANDATORY_PARAMS = ["ref", "elements"];
@@ -247,9 +248,6 @@ export function makeDraggableHook(hookParams = {}) {
ctx.offset.y -= eRect.y;
addStyle(ctx.currentElement, {
position: "fixed",
"pointer-events": "none",
"z-index": 1000,
width: `${eRect.width}px`,
height: `${eRect.height}px`,
left: `${eRect.x}px`,
@@ -271,6 +269,9 @@ export function makeDraggableHook(hookParams = {}) {
cleanups.push(cleanupFn);
}
ctx.currentElement.classList.add(DRAGGED_CLASS);
cleanups.push(() => ctx.currentElement.classList.remove(DRAGGED_CLASS));
execBuildHandler("onDragStart");
};
@@ -0,0 +1,14 @@
.o_dragged {
position: fixed !important;
z-index: 1000 !important;
// In FireFox: elements with `overflow: hidden` will prevent mouseenter and mouseleave
// events from firing on elements underneath them. This is the case when dragging a card
// by the `.o_kanban_record_headings` element. In such cases, the pointer events are
// disabled to allow mouse events to fire properly.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1352061
&,
* {
pointer-events: none;
}
}
+2 -2
View File
@@ -139,8 +139,7 @@ export const useSortable = makeDraggableHook({
const { width, height } = ctx.currentElementRect;
// Prepares the ghost element
ctx.ghostElement = ctx.currentElement.cloneNode(false);
// Ghost element is hidden and its size is frozen
ctx.ghostElement.style = `visibility: hidden; display: block; width: ${width}px; height:${height}px;`;
// Binds handlers on eligible groups, if the elements are not confined to
@@ -193,6 +192,7 @@ export const useSortable = makeDraggableHook({
ctx.currentContainer = ctx.currentGroup;
}
}
ctx.ghostElement = ctx.currentElement.cloneNode(false);
},
onCleanup({ ctx }) {
if (ctx.ghostElement) {
@@ -530,7 +530,7 @@ export class KanbanRenderer extends Component {
* @param {HTMLElement} [params.group]
*/
sortStart({ element }) {
element.classList.add("o_dragged", "shadow");
element.classList.add("shadow");
}
/**
@@ -539,7 +539,7 @@ export class KanbanRenderer extends Component {
* @param {HTMLElement} [params.group]
*/
sortStop({ element, group }) {
element.classList.remove("o_dragged", "shadow");
element.classList.remove("shadow");
if (group) {
group.classList.remove("o_kanban_hover");
}
@@ -1745,18 +1745,14 @@ export class ListRenderer extends Component {
* @param {HTMLElement} params.element
* @param {HTMLElement} [params.group]
*/
sortStart({ element }) {
element.classList.add("o_dragged");
}
sortStart() {}
/**
* @param {Object} params
* @param {HTMLElement} params.element
* @param {HTMLElement} [params.group]
*/
sortStop({ element }) {
element.classList.remove("o_dragged");
}
sortStop() {}
}
ListRenderer.template = "web.ListRenderer";
@@ -1,6 +1,6 @@
/** @odoo-module **/
import { dragAndDrop, getFixture, mount, nextTick } from "@web/../tests/helpers/utils";
import { drag, dragAndDrop, getFixture, mount, nextTick } from "@web/../tests/helpers/utils";
import { useSortable } from "@web/core/utils/sortable";
import { Component, reactive, useRef, useState, xml } from "@odoo/owl";
@@ -88,7 +88,7 @@ QUnit.module("UI", ({ beforeEach }) => {
});
QUnit.test("Simple sorting in single group", async (assert) => {
assert.expect(19);
assert.expect(22);
class List extends Component {
setup() {
@@ -132,12 +132,18 @@ QUnit.module("UI", ({ beforeEach }) => {
await mount(List, target);
assert.containsN(target, ".item", 3);
assert.containsNone(target, ".o_dragged");
assert.verifySteps([]);
// First item after 2nd item
await dragAndDrop(".item:first-child", ".item:nth-child(2)");
const drop = await drag(".item:first-child", ".item:nth-child(2)");
assert.hasClass(target.querySelector(".item"), "o_dragged");
await drop();
assert.containsN(target, ".item", 3);
assert.containsNone(target, ".o_dragged");
assert.verifySteps(["start", "elemententer", "stop", "drop"]);
});