diff --git a/addons/board/static/src/board_controller.js b/addons/board/static/src/board_controller.js index 751876257b0..4095d8128e7 100644 --- a/addons/board/static/src/board_controller.js +++ b/addons/board/static/src/board_controller.js @@ -7,7 +7,7 @@ import { Dropdown } from "@web/core/dropdown/dropdown"; import { DropdownItem } from "@web/core/dropdown/dropdown_item"; import { useService } from "@web/core/utils/hooks"; import { renderToString } from "@web/core/utils/render"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; import { standardViewProps } from "@web/views/standard_view_props"; import { BoardAction } from "./board_action"; import { blockDom, Component, useState, useRef } from "@odoo/owl"; diff --git a/addons/web/static/src/core/utils/sortable.js b/addons/web/static/src/core/utils/sortable.js index f3e63efdcb4..e536aef644c 100644 --- a/addons/web/static/src/core/utils/sortable.js +++ b/addons/web/static/src/core/utils/sortable.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { makeDraggableHook } from "@web/core/utils/draggable_hook_builder_owl"; +import { makeDraggableHook as nativeMakeDraggableHook } from "@web/core/utils/draggable_hook_builder"; import { pick } from "@web/core/utils/objects"; /** @typedef {import("@web/core/utils/draggable_hook_builder").DraggableHandlerParams} DraggableHandlerParams */ @@ -63,8 +63,8 @@ import { pick } from "@web/core/utils/objects"; * @property {boolean} dragging */ -/** @type {(params: SortableParams) => SortableState} */ -export const useSortable = makeDraggableHook({ +/** @type SortableParams */ +const hookParams = { name: "useSortable", acceptedParams: { groups: [String, Function], @@ -205,4 +205,11 @@ export const useSortable = makeDraggableHook({ return pick(current, "element", "group"); }, -}); +}; + +/** @type {(params: SortableParams) => SortableState} */ +export const useSortable = (sortableParams) => { + const { setupHooks } = sortableParams; + delete sortableParams.setupHooks; + return nativeMakeDraggableHook({ ...hookParams, setupHooks })(sortableParams); +}; diff --git a/addons/web/static/src/core/utils/sortable_owl.js b/addons/web/static/src/core/utils/sortable_owl.js new file mode 100644 index 00000000000..0ace0819736 --- /dev/null +++ b/addons/web/static/src/core/utils/sortable_owl.js @@ -0,0 +1,26 @@ +/** @odoo-module */ + +import { onWillUnmount, reactive, useEffect, useExternalListener } from "@odoo/owl"; +import { useThrottleForAnimation } from "./timing"; +import { useSortable as nativeUseSortable } from "@web/core/utils/sortable"; + +/** + * Set of default `useSortable` setup hooks that makes use of Owl lifecycle + * and reactivity hooks to properly set up, update and tear down the elements and + * listeners added by the draggable hook builder. + * + * @see {nativeUseSortable} + * @type {typeof nativeUseSortable} + */ +export function useSortable(params) { + return nativeUseSortable({ + ...params, + setupHooks: { + addListener: useExternalListener, + setup: useEffect, + teardown: onWillUnmount, + throttle: useThrottleForAnimation, + wrapState: reactive, + }, + }); +} diff --git a/addons/web/static/src/views/fields/properties/properties_field.js b/addons/web/static/src/views/fields/properties/properties_field.js index 1ca35885adb..7c6c910c8c5 100644 --- a/addons/web/static/src/views/fields/properties/properties_field.js +++ b/addons/web/static/src/views/fields/properties/properties_field.js @@ -14,7 +14,7 @@ import { ConfirmationDialog } from "@web/core/confirmation_dialog/confirmation_d import { reposition } from "@web/core/position_hook"; import { archParseBoolean } from "@web/views/utils"; import { pick } from "@web/core/utils/objects"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; import { Component, useRef, useState, useEffect, onWillStart } from "@odoo/owl"; diff --git a/addons/web/static/src/views/fields/properties/property_definition_selection.js b/addons/web/static/src/views/fields/properties/property_definition_selection.js index 39eba4136aa..4c3a67bb8cc 100644 --- a/addons/web/static/src/views/fields/properties/property_definition_selection.js +++ b/addons/web/static/src/views/fields/properties/property_definition_selection.js @@ -4,7 +4,7 @@ import { useService } from "@web/core/utils/hooks"; import { uuid } from "../../utils"; import { Component, useState, useRef, useEffect } from "@odoo/owl"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; export class PropertyDefinitionSelection extends Component { setup() { diff --git a/addons/web/static/src/views/kanban/kanban_renderer.js b/addons/web/static/src/views/kanban/kanban_renderer.js index 81eb886f83f..ff19f95830e 100644 --- a/addons/web/static/src/views/kanban/kanban_renderer.js +++ b/addons/web/static/src/views/kanban/kanban_renderer.js @@ -6,7 +6,7 @@ import { DropdownItem } from "@web/core/dropdown/dropdown_item"; import { useHotkey } from "@web/core/hotkeys/hotkey_hook"; import { registry } from "@web/core/registry"; import { useBus, useService } from "@web/core/utils/hooks"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; import { isNull } from "@web/views/utils"; import { ColumnProgress } from "@web/views/view_components/column_progress"; import { useBounceButton } from "@web/views/view_hook"; @@ -229,7 +229,7 @@ export class KanbanRenderer extends Component { fieldNodes.length && fieldNodes.some((fieldNode) => "readonly" in fieldNode) ) { - isReadonly = fieldNodes.every((fieldNode) => fieldNode.readonly === 'True'); + isReadonly = fieldNodes.every((fieldNode) => fieldNode.readonly === "True"); } return !isReadonly && this.isMovableField(groupByField); } diff --git a/addons/web/static/src/views/list/list_renderer.js b/addons/web/static/src/views/list/list_renderer.js index 5f40df65d41..2daaf276709 100644 --- a/addons/web/static/src/views/list/list_renderer.js +++ b/addons/web/static/src/views/list/list_renderer.js @@ -9,7 +9,7 @@ import { Pager } from "@web/core/pager/pager"; import { evaluateBooleanExpr } from "@web/core/py_js/py"; import { registry } from "@web/core/registry"; import { useBus, useService } from "@web/core/utils/hooks"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; import { getTabableElements } from "@web/core/utils/ui"; import { Field, getPropertyFieldInfo } from "@web/views/fields/field"; import { getTooltipInfo } from "@web/views/fields/field_tooltip"; diff --git a/addons/web/static/src/views/view_dialogs/export_data_dialog.js b/addons/web/static/src/views/view_dialogs/export_data_dialog.js index c1fc60063e9..b6a02d39334 100644 --- a/addons/web/static/src/views/view_dialogs/export_data_dialog.js +++ b/addons/web/static/src/views/view_dialogs/export_data_dialog.js @@ -7,7 +7,7 @@ import { Dialog } from "@web/core/dialog/dialog"; import { unique } from "@web/core/utils/arrays"; import { useService } from "@web/core/utils/hooks"; import { fuzzyLookup } from "@web/core/utils/search"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; import { useDebounced } from "@web/core/utils/timing"; import { Component, useRef, useState, onMounted, onWillStart, onWillUnmount } from "@odoo/owl"; diff --git a/addons/web/static/tests/core/utils/sortable_tests.js b/addons/web/static/tests/core/utils/sortable_tests.js index a1acc6fa7e6..e563fd2f232 100644 --- a/addons/web/static/tests/core/utils/sortable_tests.js +++ b/addons/web/static/tests/core/utils/sortable_tests.js @@ -8,7 +8,7 @@ import { mount, nextTick, } from "@web/../tests/helpers/utils"; -import { useSortable } from "@web/core/utils/sortable"; +import { useSortable } from "@web/core/utils/sortable_owl"; import { Component, reactive, useRef, useState, xml } from "@odoo/owl"; @@ -330,7 +330,7 @@ QUnit.module("Draggable", ({ beforeEach }) => { assert.strictEqual(renderer.scrollWidth, 900); assert.containsNone(target, ".item.o_dragged"); - let dragHelpers = await drag(".item11"); + const dragHelpers = await drag(".item11"); // Drag first record of first group to the right await dragHelpers.moveTo(".list3 .item");