Odoo18-Base/addons/web_hierarchy/static/src/hierarchy_node_draggable.js
2025-01-06 10:57:38 +07:00

104 lines
3.3 KiB
JavaScript

/** @odoo-module */
import { onWillUnmount, reactive, useEffect, useExternalListener } from "@odoo/owl";
import { useThrottleForAnimation } from "@web/core/utils/timing";
import { pick } from "@web/core/utils/objects";
import { makeDraggableHook } from "@web/core/utils/draggable_hook_builder";
const hookParams = {
name: "useHierarchyNodeDraggable",
acceptedParams: {
rows: [String],
},
defaultParams: {
edgeScrolling: { speed: 20, threshold: 60 },
rows: null,
},
onComputeParams({ ctx, params }) {
// Row selector
ctx.rowSelector = params.rows || null;
if (ctx.rowSelector) {
ctx.fullSelector = `${ctx.rowSelector} ${ctx.fullSelector}`;
}
},
onDragStart(params) {
const { ctx, addListener, callHandler } = params;
const onElementPointerEnter = (ev) => {
const element = ev.currentTarget;
current.hierarchyElement = element;
callHandler("onElementEnter", { element });
};
const onElementPointerLeave = (ev) => {
const element = ev.currentTarget;
current.hierarchyElement = null;
callHandler("onElementLeave", { element });
};
const onRowPointerEnter = (ev) => {
const row = ev.currentTarget;
current.hierarchyRow = row;
callHandler("onRowEnter", { row });
};
const onRowPointerLeave = (ev) => {
const row = ev.currentTarget;
current.hierarchyRow = null;
callHandler("onRowLeave", { row });
};
const { ref, current, elementSelector, rowSelector } = ctx;
for (const rowEl of ref.el.querySelectorAll(rowSelector)) {
addListener(rowEl, "pointerenter", onRowPointerEnter);
addListener(rowEl, "pointerleave", onRowPointerLeave);
}
for (const siblingEl of ref.el.querySelectorAll(elementSelector)) {
if (siblingEl !== current.element) {
addListener(siblingEl, "pointerenter", onElementPointerEnter);
addListener(siblingEl, "pointerleave", onElementPointerLeave);
}
}
return pick(current, "element", "row");
},
onDragEnd({ ctx }) {
return pick(ctx.current, "element", "row", "hierarchyRow");
},
onDrop({ ctx }) {
const { current } = ctx;
const rowElement = current.hierarchyRow;
const element = current.hierarchyElement;
if ((rowElement && rowElement !== current.row) || element) {
return {
element: current.element,
row: current.row,
nextRow: rowElement && current.row !== rowElement ? rowElement : null,
newParentNode: element,
};
}
},
onWillStartDrag({ ctx }) {
const { current, rowSelector } = ctx;
if (rowSelector) {
current.row = current.element.closest(rowSelector);
}
return pick(current, "element", "row");
},
};
export function useHierarchyNodeDraggable(params) {
const setupHooks = {
addListener: useExternalListener,
setup: useEffect,
teardown: onWillUnmount,
throttle: useThrottleForAnimation,
wrapState: reactive,
}
return makeDraggableHook({ ...hookParams, setupHooks })(params);
}