From f0870c53fc4ca04106db485225f026642d53082e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chy=C5=82a?= Date: Fri, 31 Jan 2025 13:26:51 +0100 Subject: [PATCH] Fix open with cmd key (#5381) * Fix open with cmd key * Add changeset * Log href * Remove console.log and use default action * Add tests * Change mocking --- .changeset/five-bears-doubt.md | 5 ++ src/components/Datagrid/Datagrid.tsx | 19 +---- .../hooks/useRowAnchorHandler.test.ts | 80 +++++++++++++++++++ .../Datagrid/hooks/useRowAnchorHandler.ts | 22 +++++ 4 files changed, 111 insertions(+), 15 deletions(-) create mode 100644 .changeset/five-bears-doubt.md create mode 100644 src/components/Datagrid/hooks/useRowAnchorHandler.test.ts create mode 100644 src/components/Datagrid/hooks/useRowAnchorHandler.ts diff --git a/.changeset/five-bears-doubt.md b/.changeset/five-bears-doubt.md new file mode 100644 index 00000000000..12c431600bb --- /dev/null +++ b/.changeset/five-bears-doubt.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +Opening item in new tab using cmd key on datagrid now takes into account mounting point diff --git a/src/components/Datagrid/Datagrid.tsx b/src/components/Datagrid/Datagrid.tsx index d4f4659b25a..c628b7d5b3e 100644 --- a/src/components/Datagrid/Datagrid.tsx +++ b/src/components/Datagrid/Datagrid.tsx @@ -1,6 +1,7 @@ import "@glideapps/glide-data-grid/dist/index.css"; -import useNavigator, { NavigatorOpts } from "@dashboard/hooks/useNavigator"; +import { useRowAnchorHandler } from "@dashboard/components/Datagrid/hooks/useRowAnchorHandler"; +import { NavigatorOpts } from "@dashboard/hooks/useNavigator"; import { usePreventHistoryBack } from "@dashboard/hooks/usePreventHistoryBack"; import { getCellAction } from "@dashboard/products/components/ProductListDatagrid/datagrid"; import DataEditor, { @@ -139,7 +140,6 @@ export const Datagrid: React.FC = ({ const datagridTheme = useDatagridTheme(readonly, readonly); const editor = useRef(null); const customRenderers = useCustomCellRenderers(); - const navigate = useNavigator(); const { scrolledToRight, scroller } = useScrollRight(); const fullScreenClasses = useFullScreenStyles(classes); const { isOpen, isAnimationOpenFinished, toggle } = useFullScreenMode(); @@ -152,6 +152,7 @@ export const Datagrid: React.FC = ({ rowMarkers, availableColumns, }); + const rowAnchorHandler = useRowAnchorHandler(navigatorOpts); const { handleRowHover, hoverRow } = useRowHover({ hasRowHover, @@ -529,19 +530,7 @@ export const Datagrid: React.FC = ({ tabIndex={-1} aria-hidden={true} onWheelCapture={hideLinkAndShowAfterDelay} - onClick={e => { - e.preventDefault(); - - if (e.currentTarget.dataset.reactRouterPath) { - const url = e.currentTarget.dataset.reactRouterPath; - - if (e.metaKey || e.ctrlKey) { - window.open(url, "_blank"); - } else { - navigate(url, navigatorOpts); - } - } - }} + onClick={rowAnchorHandler} /> )} diff --git a/src/components/Datagrid/hooks/useRowAnchorHandler.test.ts b/src/components/Datagrid/hooks/useRowAnchorHandler.test.ts new file mode 100644 index 00000000000..0fa8a6c99ab --- /dev/null +++ b/src/components/Datagrid/hooks/useRowAnchorHandler.test.ts @@ -0,0 +1,80 @@ +import useNavigator from "@dashboard/hooks/useNavigator"; +import { renderHook } from "@testing-library/react-hooks"; + +import { useRowAnchorHandler } from "./useRowAnchorHandler"; + +jest.mock("@dashboard/hooks/useNavigator", () => jest.fn()); + +jest.mock("@dashboard/hooks/useNavigator", () => ({ + __esModule: true, + default: jest.fn(() => jest.fn()), +})); + +describe("useRowAnchorHandler", () => { + it("should navigate to the given path", () => { + // Arrange + const navigate = jest.fn(); + + (useNavigator as jest.Mock).mockReturnValue(navigate); + + const navigatorOpts = { replace: true }; + const handler = renderHook(() => useRowAnchorHandler(navigatorOpts)).result.current; + const event = { + preventDefault: jest.fn(), + currentTarget: { + dataset: { + reactRouterPath: "/some-path", + }, + }, + }; + + // Act + handler(event as any); + + // Assert + expect(event.preventDefault).toHaveBeenCalled(); + expect(navigate).toHaveBeenCalledWith("/some-path", navigatorOpts); + }); + + it("should not prevent default when CMD key is pressed", () => { + // Arrange + const navigate = jest.fn(); + + (useNavigator as jest.Mock).mockReturnValue(navigate); + + const handler = renderHook(() => useRowAnchorHandler()).result.current; + const event = { + preventDefault: jest.fn(), + metaKey: true, + ctrlKey: false, + }; + + // Act + handler(event as any); + + // Assert + expect(event.preventDefault).not.toHaveBeenCalled(); + expect(navigate).not.toHaveBeenCalled(); + }); + + it("should not prevent default when CTRL key is pressed", () => { + // Arrange + const navigate = jest.fn(); + + (useNavigator as jest.Mock).mockReturnValue(navigate); + + const handler = renderHook(() => useRowAnchorHandler()).result.current; + const event = { + preventDefault: jest.fn(), + metaKey: false, + ctrlKey: true, + }; + + // Act + handler(event as any); + + // Assert + expect(event.preventDefault).not.toHaveBeenCalled(); + expect(navigate).not.toHaveBeenCalled(); + }); +}); diff --git a/src/components/Datagrid/hooks/useRowAnchorHandler.ts b/src/components/Datagrid/hooks/useRowAnchorHandler.ts new file mode 100644 index 00000000000..a85acf35a04 --- /dev/null +++ b/src/components/Datagrid/hooks/useRowAnchorHandler.ts @@ -0,0 +1,22 @@ +import useNavigator, { NavigatorOpts } from "@dashboard/hooks/useNavigator"; +import { MouseEvent } from "react"; + +export const useRowAnchorHandler = (navigatorOpts?: NavigatorOpts) => { + const navigate = useNavigator(); + + return (e: MouseEvent) => { + // When someone clicks with CMD key to open in new tab, we should not prevent default + if (e.metaKey || e.ctrlKey) { + return; + } + + // Prevent default when navigate with browser router + e.preventDefault(); + + if (e.currentTarget.dataset.reactRouterPath) { + // Navigate gets only a path to navigate, for example, /products/1 + // Navigate use browser router and cover case when url is with /dashboard or not + navigate(e.currentTarget.dataset.reactRouterPath, navigatorOpts); + } + }; +};