From 9c970b13b7b20cd17dad02cdc38cbc36a458d87f Mon Sep 17 00:00:00 2001 From: Romeo Fragomeli Date: Fri, 29 Sep 2023 10:29:41 +0200 Subject: [PATCH] [REF] board,web: adapt useSortable to be used natively This commit removes Owl hooks from the sortable hook builder file and introduces a new parameter attribute (`setupHooks`) to specify which functions must be used to set up, update and tear down the draggable hook. This has been done to allow using the hook function in environments where Owl is not available. Part-of: odoo/odoo#137527 --- addons/board/static/src/board_controller.js | 2 +- addons/web/static/src/core/utils/sortable.js | 15 ++++++++--- .../web/static/src/core/utils/sortable_owl.js | 26 +++++++++++++++++++ .../fields/properties/properties_field.js | 2 +- .../property_definition_selection.js | 2 +- .../src/views/kanban/kanban_renderer.js | 4 +-- .../static/src/views/list/list_renderer.js | 2 +- .../views/view_dialogs/export_data_dialog.js | 2 +- .../static/tests/core/utils/sortable_tests.js | 4 +-- 9 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 addons/web/static/src/core/utils/sortable_owl.js 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");