diff --git a/cypress/elements/catalog/products/product-details.js b/cypress/elements/catalog/products/product-details.js index 830fb4850..e1bd9bb98 100644 --- a/cypress/elements/catalog/products/product-details.js +++ b/cypress/elements/catalog/products/product-details.js @@ -25,7 +25,7 @@ export const PRODUCT_DETAILS = { uploadSavedImagesButton: '[data-test-id="upload-images"]', uploadMediaUrlButton: '[data-test-id="upload-media-url"]', saveUploadUrlButton: '[data-test-id="upload-url-button"]', - editVariant: '[id="menu-list-grow"]', + editVariant: '[data-test-id="row-action-button"]', firstRowDataGrid: "[data-testid='glide-cell-1-0']", dataGridTable: "[data-testid='data-grid-canvas']", }; diff --git a/cypress/support/pages/catalog/products/productDetailsPage.js b/cypress/support/pages/catalog/products/productDetailsPage.js index 51f728aa1..ca1cfef4b 100644 --- a/cypress/support/pages/catalog/products/productDetailsPage.js +++ b/cypress/support/pages/catalog/products/productDetailsPage.js @@ -154,8 +154,6 @@ export function enterVariantEditPage() { cy.get(PRODUCT_DETAILS.dataGridTable) .should("be.visible") .wait(1000) - .get(BUTTON_SELECTORS.showMoreButton) - .click() .get(PRODUCT_DETAILS.editVariant) .click(); } diff --git a/src/components/CardMenu/CardMenu.tsx b/src/components/CardMenu/CardMenu.tsx index 12c50a606..90aaf8d86 100644 --- a/src/components/CardMenu/CardMenu.tsx +++ b/src/components/CardMenu/CardMenu.tsx @@ -25,6 +25,7 @@ export interface CardMenuItem { loading?: boolean; withLoading?: boolean; hasError?: boolean; + Icon?: React.ReactElement; } export interface CardMenuProps { diff --git a/src/components/Datagrid/Datagrid.tsx b/src/components/Datagrid/Datagrid.tsx index e90674472..0dd2ce4d7 100644 --- a/src/components/Datagrid/Datagrid.tsx +++ b/src/components/Datagrid/Datagrid.tsx @@ -9,17 +9,18 @@ import DataEditor, { } from "@glideapps/glide-data-grid"; import { Card, CardContent, Typography } from "@material-ui/core"; import { usePreventHistoryBack } from "@saleor/hooks/usePreventHistoryBack"; -import { MoreHorizontalIcon, useTheme } from "@saleor/macaw-ui"; +import { useTheme } from "@saleor/macaw-ui"; import clsx from "clsx"; import range from "lodash/range"; import throttle from "lodash/throttle"; import React from "react"; import { FormattedMessage } from "react-intl"; -import CardMenu, { CardMenuItem } from "../CardMenu"; +import { CardMenuItem } from "../CardMenu"; import ColumnPicker from "../ColumnPicker"; import { FullScreenContainer } from "./FullScreenContainer"; import { Header } from "./Header"; +import { RowActions } from "./RowActions"; import useStyles, { useDatagridTheme, useFullScreenStyles } from "./styles"; import { AvailableColumn } from "./types"; import useCells from "./useCells"; @@ -280,8 +281,8 @@ export const Datagrid: React.FC = ({
= ({ {Array(rowsTotal) .fill(0) .map((_, index) => ( -
- = rowsTotal - added.length} - Icon={MoreHorizontalIcon} - IconButtonProps={{ - className: classes.columnPickerBtn, - hoverOutline: false, - state: "default", - }} - menuItems={menuItems(index)} - /> -
+ = rowsTotal - added.length} + /> ))}
} diff --git a/src/components/Datagrid/RowActions.test.tsx b/src/components/Datagrid/RowActions.test.tsx new file mode 100644 index 000000000..8a78bab4f --- /dev/null +++ b/src/components/Datagrid/RowActions.test.tsx @@ -0,0 +1,206 @@ +import { EditIcon, ThemeProvider } from "@saleor/macaw-ui"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import React from "react"; + +import { RowActions } from "./RowActions"; + +describe("RowActions", () => { + it("should render empty when menu items count equal to 0", () => { + // Arrange & Act + const { container } = render( + + + , + ); + + // Assert + expect(container.firstChild).toBeNull(); + }); + + it("should render icon button when only one menu item and has icon props", () => { + // Arrange & Act + render( + + , + }, + ]} + disabled={false} + /> + , + ); + + // Assert + expect(screen.getByTestId("row-action-button")).toBeInTheDocument(); + expect(screen.getByTestId("edit-icon")).toBeInTheDocument(); + }); + + it("should render card meu when only one menu item and has no icon props", () => { + // Arrange & Act + render( + + + , + ); + + // Assert + expect(screen.getByTestId("show-more-button")).toBeInTheDocument(); + }); + + it("should render card meu with multiple items", async () => { + // Arrange + render( + + + , + ); + + // Act + + await userEvent.click(screen.getByTestId("show-more-button")); + + // Assert + expect(screen.getByTestId("show-more-button")).toBeInTheDocument(); + expect(screen.getByTestId("edit-button")).toBeInTheDocument(); + expect(screen.getByTestId("delete-button")).toBeInTheDocument(); + expect(screen.getByTestId("upgrade-button")).toBeInTheDocument(); + }); + + it("should fire callback when click on icon button when single menu item with icon props", async () => { + // Arrange + const onSelectCallback = jest.fn(); + + render( + + , + }, + ]} + disabled={false} + /> + , + ); + + // Act + await userEvent.click(screen.getByTestId("row-action-button")); + + // Assert + expect(onSelectCallback).toHaveBeenCalled(); + }); + + it("should fire callback when click on icon button when multiple menu item", async () => { + // Arrange + const onIconClickCallback = jest.fn(); + + render( + + + , + ); + + // Act + await userEvent.click(screen.getByTestId("show-more-button")); + await userEvent.click(screen.getByTestId("edit-button")); + + // Assert + expect(onIconClickCallback).toHaveBeenCalled(); + }); + + it("should disabled show more button when RowAction disabled", async () => { + // Arrange & Act + render( + + + , + ); + + // Assert + expect(screen.getByTestId("show-more-button")).toBeDisabled(); + }); + + it("should disabled row action button when RowAction disabled", async () => { + // Arrange & Act + render( + + , + }, + ]} + disabled={true} + /> + , + ); + + // Assert + expect(screen.getByTestId("row-action-button")).toBeDisabled(); + }); +}); diff --git a/src/components/Datagrid/RowActions.tsx b/src/components/Datagrid/RowActions.tsx new file mode 100644 index 000000000..a206ecf55 --- /dev/null +++ b/src/components/Datagrid/RowActions.tsx @@ -0,0 +1,51 @@ +import { IconButton, MoreHorizontalIcon } from "@saleor/macaw-ui"; +import React from "react"; + +import CardMenu, { CardMenuItem } from "../CardMenu"; +import useStyles from "./styles"; + +interface RowActionsProps { + menuItems: CardMenuItem[]; + disabled?: boolean; +} + +export const RowActions = ({ menuItems, disabled }: RowActionsProps) => { + const classes = useStyles(); + const hasSingleMenuItem = menuItems.length === 1; + const firstMenuItem = menuItems[0]; + + const handleIconClick = () => { + firstMenuItem.onSelect(); + }; + + if (!menuItems.length) { + return null; + } + + return ( +
+ {hasSingleMenuItem && firstMenuItem.Icon ? ( + + {firstMenuItem.Icon} + + ) : ( + + )} +
+ ); +}; diff --git a/src/components/Datagrid/styles.ts b/src/components/Datagrid/styles.ts index 86f06a953..d79bf7932 100644 --- a/src/components/Datagrid/styles.ts +++ b/src/components/Datagrid/styles.ts @@ -34,10 +34,8 @@ const useStyles = makeStyles( justifyContent: "center", height: 48, }, - columnPickerBtn: { - "&:hover": { - color: theme.palette.saleor.main[1], - }, + ghostIcon: { + color: theme.palette.saleor.main[3], }, portal: { "& input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": { diff --git a/src/icons/Edit.tsx b/src/icons/Edit.tsx new file mode 100644 index 000000000..914e36fa8 --- /dev/null +++ b/src/icons/Edit.tsx @@ -0,0 +1,22 @@ +import React from "react"; + +const EditIcon = () => ( + + + + +); + +export default EditIcon; diff --git a/src/products/components/ProductVariants/ProductVariants.tsx b/src/products/components/ProductVariants/ProductVariants.tsx index 1ff606444..3b286f8a4 100644 --- a/src/products/components/ProductVariants/ProductVariants.tsx +++ b/src/products/components/ProductVariants/ProductVariants.tsx @@ -12,6 +12,7 @@ import { RefreshLimitsQuery, WarehouseFragment, } from "@saleor/graphql"; +import EditIcon from "@saleor/icons/Edit"; import { buttonMessages } from "@saleor/intl"; import { Button } from "@saleor/macaw-ui"; import { ProductVariantListError } from "@saleor/products/views/ProductUpdate/handlers/errors"; @@ -121,6 +122,7 @@ export const ProductVariants: React.FC = ({ { label: "Edit Variant", onSelect: () => onRowClick(variants[index].id), + Icon: , }, ]} rows={variants?.length ?? 0}