Fix redirect when modal is opened from table (#2034)

* Fix redirect when modal is opened on apps list

* Update snapshots

* Fix failing Cypress test

* Fix issues with TableRowLink and buttons that have onClick

* Fix CustomAppDetailsPage using wrong Backlink compponent

* Remove custom click event handler from TableRowLink

* Add TableButtonWrapper component

* Refactor Buttons and Links in TableRowLink to use TableButtonWrapper

* Refactor Buttons in SortableTableRowLink to use TableButtonWrapper

* Add comments about reasoning behind TableButtonWrapper
This commit is contained in:
Jonatan Witoszek 2022-05-13 13:04:16 +02:00 committed by GitHub
parent ad7e6458b5
commit 9c2ed377cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 840 additions and 722 deletions

View file

@ -8,15 +8,13 @@ import {
Typography
} from "@material-ui/core";
import ErrorIcon from "@material-ui/icons/Error";
import { Button } from "@saleor/components/Button";
import CardTitle from "@saleor/components/CardTitle";
import { IconButton } from "@saleor/components/IconButton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import { AppsInstallationsQuery, JobStatusEnum } from "@saleor/graphql";
import {
Button,
DeleteIcon,
IconButton,
ResponsiveTable
} from "@saleor/macaw-ui";
import { renderCollection, stopPropagation } from "@saleor/misc";
import { DeleteIcon, ResponsiveTable } from "@saleor/macaw-ui";
import { renderCollection } from "@saleor/misc";
import classNames from "classnames";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
@ -97,20 +95,24 @@ const AppsInProgress: React.FC<AppsInProgressProps> = ({
<ErrorIcon />
</Tooltip>
</Typography>
<Button onClick={() => onAppInstallRetry(id)}>
<FormattedMessage
id="+c/f61"
defaultMessage="Retry"
description="retry installation"
/>
</Button>
<IconButton
variant="secondary"
color="primary"
onClick={stopPropagation(() => onRemove(id))}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<Button onClick={() => onAppInstallRetry(id)}>
<FormattedMessage
id="+c/f61"
defaultMessage="Retry"
description="retry installation"
/>
</Button>
</TableButtonWrapper>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
onClick={() => onRemove(id)}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
)}
</TableRow>

View file

@ -32,8 +32,7 @@ const props: AppsListPageProps = {
onCustomAppRemove: () => undefined,
onInstalledAppRemove: () => undefined,
onNextPage: () => undefined,
onPreviousPage: () => undefined,
onRowAboutClick: () => undefined
onPreviousPage: () => undefined
};
storiesOf("Views / Apps / Apps list", module)

View file

@ -22,7 +22,6 @@ export interface AppsListPageProps extends ListProps {
onCustomAppRemove: (id: string) => void;
onAppInProgressRemove: (id: string) => void;
onAppInstallRetry: (id: string) => void;
onRowAboutClick: (id: string) => () => void;
}
const AppsListPage: React.FC<AppsListPageProps> = ({
@ -35,7 +34,6 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
onCustomAppRemove,
onAppInProgressRemove,
onAppInstallRetry,
onRowAboutClick,
...listProps
}) => {
const intl = useIntl();
@ -59,7 +57,6 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
<InstalledApps
appsList={installedAppsList}
onRemove={onInstalledAppRemove}
onRowAboutClick={onRowAboutClick}
{...listProps}
/>
<CardSpacer />

View file

@ -1,5 +1,6 @@
import { appsListUrl } from "@saleor/apps/urls";
import AccountPermissions from "@saleor/components/AccountPermissions";
import { Backlink } from "@saleor/components/Backlink";
import CardSpacer from "@saleor/components/CardSpacer";
import Container from "@saleor/components/Container";
import Form from "@saleor/components/Form";
@ -15,11 +16,7 @@ import {
import { SubmitPromise } from "@saleor/hooks/useForm";
import useNavigator from "@saleor/hooks/useNavigator";
import { sectionNames } from "@saleor/intl";
import {
Backlink,
Button,
ConfirmButtonTransitionState
} from "@saleor/macaw-ui";
import { Button, ConfirmButtonTransitionState } from "@saleor/macaw-ui";
import { getFormErrors } from "@saleor/utils/errors";
import getAppErrorMessage from "@saleor/utils/errors/app";
import WebhooksList from "@saleor/webhooks/components/WebhooksList";

View file

@ -8,11 +8,12 @@ import {
import { customAppAddUrl } from "@saleor/apps/urls";
import { Button } from "@saleor/components/Button";
import CardTitle from "@saleor/components/CardTitle";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableRowLink from "@saleor/components/TableRowLink";
import { AppsListQuery } from "@saleor/graphql";
import { commonMessages } from "@saleor/intl";
import { DeleteIcon, IconButton, ResponsiveTable } from "@saleor/macaw-ui";
import { renderCollection, stopPropagation } from "@saleor/misc";
import { renderCollection } from "@saleor/misc";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
@ -74,13 +75,15 @@ const CustomApps: React.FC<CustomAppsProps> = ({
)}
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
variant="secondary"
color="primary"
onClick={stopPropagation(() => onRemove(app.node.id))}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
onClick={() => onRemove(app.node.id)}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
) : (

View file

@ -6,18 +6,16 @@ import {
TableRow,
Typography
} from "@material-ui/core";
import { appUrl } from "@saleor/apps/urls";
import { appDetailsUrl, appUrl } from "@saleor/apps/urls";
import { Button } from "@saleor/components/Button";
import CardTitle from "@saleor/components/CardTitle";
import { IconButton } from "@saleor/components/IconButton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TablePagination from "@saleor/components/TablePagination";
import TableRowLink from "@saleor/components/TableRowLink";
import { AppsListQuery } from "@saleor/graphql";
import {
Button,
DeleteIcon,
IconButton,
ResponsiveTable
} from "@saleor/macaw-ui";
import { renderCollection, stopPropagation } from "@saleor/misc";
import { DeleteIcon, ResponsiveTable } from "@saleor/macaw-ui";
import { renderCollection } from "@saleor/misc";
import { ListProps } from "@saleor/types";
import clsx from "clsx";
import React from "react";
@ -30,7 +28,6 @@ import DeactivatedText from "../DeactivatedText";
export interface InstalledAppsProps extends ListProps {
appsList: AppsListQuery["apps"]["edges"];
onRemove: (id: string) => void;
onRowAboutClick: (id: string) => () => void;
}
const numberOfColumns = 2;
@ -41,7 +38,6 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
disabled,
onNextPage,
onPreviousPage,
onRowAboutClick,
onUpdateListSettings,
pageInfo,
...props
@ -103,22 +99,24 @@ const InstalledApps: React.FC<InstalledAppsProps> = ({
{app.node.appUrl}
</Typography>
)}
<Button
onClick={stopPropagation(onRowAboutClick(app.node.id))}
>
<FormattedMessage
id="TBaMo2"
defaultMessage="About"
description="about app"
/>
</Button>
<IconButton
variant="secondary"
color="primary"
onClick={stopPropagation(() => onRemove(app.node.id))}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<Button href={appDetailsUrl(app.node.id)}>
<FormattedMessage
id="TBaMo2"
defaultMessage="About"
description="about app"
/>
</Button>
</TableButtonWrapper>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
onClick={() => onRemove(app.node.id)}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
) : (

View file

@ -32,7 +32,6 @@ import AppInProgressDeleteDialog from "../../components/AppInProgressDeleteDialo
import AppsListPage from "../../components/AppsListPage";
import { EXTENSION_LIST_QUERY } from "../../queries";
import {
appDetailsUrl,
AppListUrlDialog,
AppListUrlQueryParams,
appsListUrl,
@ -312,7 +311,6 @@ export const AppsList: React.FC<AppsListProps> = ({ params }) => {
onNextPage={loadNextPage}
onPreviousPage={loadPreviousPage}
onUpdateListSettings={updateListSettings}
onRowAboutClick={id => () => navigate(appDetailsUrl(id))}
onAppInstallRetry={onAppInstallRetry}
getCustomAppHref={id => customAppUrl(id)}
onInstalledAppRemove={id =>

View file

@ -13,6 +13,7 @@ import LimitReachedAlert from "@saleor/components/LimitReachedAlert";
import PageHeader from "@saleor/components/PageHeader";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellHeader from "@saleor/components/TableCellHeader";
import TableRowLink from "@saleor/components/TableRowLink";
import { configurationMenuUrl } from "@saleor/configuration";
@ -130,17 +131,19 @@ export const ChannelsListPage: React.FC<ChannelsListPageProps> = ({
</TableCell>
<TableCell className={classes.colAction}>
{channelsList?.length > 1 && (
<IconButton
variant="secondary"
color="primary"
onClick={
channel
? stopPropagation(() => onRemove(channel.id))
: undefined
}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
onClick={
channel
? stopPropagation(() => onRemove(channel.id))
: undefined
}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
)}
</TableCell>
</TableRowLink>

View file

@ -11,6 +11,7 @@ import { ChannelsAvailabilityDropdown } from "@saleor/components/ChannelsAvailab
import Checkbox from "@saleor/components/Checkbox";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellAvatar from "@saleor/components/TableCellAvatar";
import { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar/Avatar";
import TableHead from "@saleor/components/TableHead";
@ -208,14 +209,16 @@ const CollectionProducts: React.FC<CollectionProductsProps> = props => {
)}
</TableCell>
<TableCell className={classes.colActions}>
<IconButton
data-test-id="delete-icon"
variant="secondary"
disabled={!product}
onClick={event => onProductUnassign(product.id, event)}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
data-test-id="delete-icon"
variant="secondary"
disabled={!product}
onClick={event => onProductUnassign(product.id, event)}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
);

View file

@ -0,0 +1,44 @@
import React from "react";
interface TableButtonWrapper {
children: React.ReactElement<{
onClick?: (e: React.MouseEvent<any>) => void;
href?: string;
}>;
}
/**
* Wraps any `Button` or `Link` used inside `TableRowLink` to handle events properly
*
* @example
* ```jsx
* <TableButtonWrapper>
* <Button href="/some-page" />
* </TableButtonWrapper>
* ```
*/
export const TableButtonWrapper = <T extends HTMLElement>({
children
}: TableButtonWrapper) => {
const onClick = (e: React.MouseEvent<T>) => {
if (!children.props.href) {
// <TableRowLink> is a <a> that wraps each <tr>
// This causes buttons to act like links rather than buttons
// The events isn't boubled up to react-router's link, rather
// browser makes full page navigation directly, so we need to stop that
e.preventDefault();
}
// Stop propagation of clicks to the <Link> component, to prevent navigation
e.stopPropagation();
if (children.props.onClick) {
children.props.onClick(e);
}
};
if (React.isValidElement(children)) {
return React.cloneElement(children, { ...children.props, onClick });
}
return children;
};

View file

@ -1,9 +1,9 @@
import { TableRow, TableRowTypeMap } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import { isExternalURL } from "@saleor/utils/urls";
import clsx from "classnames";
import React from "react";
import Link from "../Link";
import { Link } from "react-router-dom";
type MaterialTableRowPropsType = TableRowTypeMap["props"];
@ -33,13 +33,13 @@ const TableRowLink = ({
}: TableRowLinkProps) => {
const classes = useStyles();
if (!href) {
if (!href || isExternalURL(href)) {
return <TableRow {...props}>{children}</TableRow>;
}
return (
<TableRow {...props}>
<Link className={clsx(classes.link, linkClassName)} href={href}>
<Link className={clsx(classes.link, linkClassName)} to={href}>
{children}
</Link>
</TableRow>

View file

@ -11,6 +11,7 @@ import CardTitle from "@saleor/components/CardTitle";
import Checkbox from "@saleor/components/Checkbox";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination";
import TableRowLink from "@saleor/components/TableRowLink";
@ -136,16 +137,18 @@ const DiscountCategories: React.FC<DiscountCategoriesProps> = props => {
)}
</TableCell>
<TableCell className={classes.colActions}>
<IconButton
variant="secondary"
disabled={!category || disabled}
onClick={event => {
event.stopPropagation();
onCategoryUnassign(category.id);
}}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
disabled={!category || disabled}
onClick={event => {
event.stopPropagation();
onCategoryUnassign(category.id);
}}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
);

View file

@ -11,6 +11,7 @@ import CardTitle from "@saleor/components/CardTitle";
import Checkbox from "@saleor/components/Checkbox";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination";
import TableRowLink from "@saleor/components/TableRowLink";
@ -136,16 +137,18 @@ const DiscountCollections: React.FC<DiscountCollectionsProps> = props => {
)}
</TableCell>
<TableCell className={classes.colActions}>
<IconButton
variant="secondary"
disabled={!collection || disabled}
onClick={event => {
event.stopPropagation();
onCollectionUnassign(collection.id);
}}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
disabled={!collection || disabled}
onClick={event => {
event.stopPropagation();
onCollectionUnassign(collection.id);
}}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
);

View file

@ -11,6 +11,7 @@ import { ChannelsAvailabilityDropdown } from "@saleor/components/ChannelsAvailab
import Checkbox from "@saleor/components/Checkbox";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellAvatar from "@saleor/components/TableCellAvatar";
import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination";
@ -157,16 +158,18 @@ const DiscountProducts: React.FC<SaleProductsProps> = props => {
)}
</TableCell>
<TableCell className={classes.colActions}>
<IconButton
variant="secondary"
disabled={!product || disabled}
onClick={event => {
event.stopPropagation();
onProductUnassign(product.id);
}}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
disabled={!product || disabled}
onClick={event => {
event.stopPropagation();
onProductUnassign(product.id);
}}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
);

View file

@ -10,6 +10,7 @@ import CardTitle from "@saleor/components/CardTitle";
import Checkbox from "@saleor/components/Checkbox";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellAvatar from "@saleor/components/TableCellAvatar";
import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination";
@ -154,16 +155,18 @@ const DiscountVariants: React.FC<SaleVariantsProps> = props => {
)}
</TableCell>
<TableCell className={classes.colActions}>
<IconButton
variant="secondary"
disabled={!variant || disabled}
onClick={event => {
event.stopPropagation();
onVariantUnassign(variant.id);
}}
>
<DeleteIcon color="primary" />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
disabled={!variant || disabled}
onClick={event => {
event.stopPropagation();
onVariantUnassign(variant.id);
}}
>
<DeleteIcon color="primary" />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
);

View file

@ -12,6 +12,7 @@ import Link from "@saleor/components/Link";
import Money from "@saleor/components/Money";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableRowLink from "@saleor/components/TableRowLink";
import { customerUrl } from "@saleor/customers/urls";
import GiftCardStatusChip from "@saleor/giftCards/components/GiftCardStatusChip/GiftCardStatusChip";
@ -138,22 +139,26 @@ const GiftCardsListTable: React.FC = () => {
</TableCell>
<TableCell>
{product ? (
<PillLink
component={RouterLink}
to={productUrl(product?.id)}
onClick={onLinkClick}
>
{product?.name}
</PillLink>
<TableButtonWrapper>
<PillLink
component={RouterLink}
to={productUrl(product?.id)}
onClick={onLinkClick}
>
{product?.name}
</PillLink>
</TableButtonWrapper>
) : (
PLACEHOLDER
)}
</TableCell>
<TableCell>
{usedBy ? (
<Link href={customerUrl(usedBy?.id)}>
{`${usedBy?.firstName} ${usedBy?.lastName}`}
</Link>
<TableButtonWrapper>
<Link href={customerUrl(usedBy?.id)}>
{`${usedBy?.firstName} ${usedBy?.lastName}`}
</Link>
</TableButtonWrapper>
) : (
<Typography noWrap>
{usedByEmail || PLACEHOLDER}

View file

@ -333,16 +333,30 @@ export function getUserInitials(user?: User) {
: undefined;
}
interface AnyEvent {
interface AnyEventWithPropagation {
stopPropagation: () => void;
}
export function stopPropagation(cb: (event?: AnyEvent) => void) {
return (event: AnyEvent) => {
export function stopPropagation<T extends AnyEventWithPropagation>(
cb: (event?: T) => void
) {
return (event: T) => {
event.stopPropagation();
cb(event);
};
}
interface AnyEventWithPreventDefault {
preventDefault: () => void;
}
export function preventDefault<T extends AnyEventWithPreventDefault>(
cb: (event?: T) => void
) {
return (event: T) => {
event.preventDefault();
cb(event);
};
}
export interface DateTime {
date: string;
time: string;

View file

@ -9,6 +9,7 @@ import Checkbox from "@saleor/components/Checkbox";
import IconButtonTableCell from "@saleor/components/IconButtonTableCell";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellHeader from "@saleor/components/TableCellHeader";
import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination";
@ -164,13 +165,15 @@ const MenuList: React.FC<MenuListProps> = props => {
<Skeleton />
)}
</TableCell>
<IconButtonTableCell
className={classes.colAction}
disabled={disabled}
onClick={() => onDelete(menu.id)}
>
<DeleteIcon />
</IconButtonTableCell>
<TableButtonWrapper>
<IconButtonTableCell
className={classes.colAction}
disabled={disabled}
onClick={() => onDelete(menu.id)}
>
<DeleteIcon />
</IconButtonTableCell>
</TableButtonWrapper>
</TableRowLink>
);
},

View file

@ -9,10 +9,11 @@ import {
SortableTableBody,
SortableTableRow
} from "@saleor/components/SortableTable";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import { AttributeFragment, AttributeTypeEnum } from "@saleor/graphql";
import { DeleteIcon, IconButton, makeStyles } from "@saleor/macaw-ui";
import { renderCollection, stopPropagation } from "@saleor/misc";
import { renderCollection } from "@saleor/misc";
import { ListActions, ReorderAction } from "@saleor/types";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
@ -155,14 +156,14 @@ const PageTypeAttributes: React.FC<PageTypeAttributesProps> = props => {
{attribute?.slug || <Skeleton />}
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
variant="secondary"
onClick={stopPropagation(() =>
onAttributeUnassign(attribute.id)
)}
>
<DeleteIcon color="primary" />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
onClick={() => onAttributeUnassign(attribute.id)}
>
<DeleteIcon color="primary" />
</IconButton>
</TableButtonWrapper>
</TableCell>
</SortableTableRow>
);

View file

@ -7,6 +7,7 @@ import {
} from "@material-ui/core";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellHeader from "@saleor/components/TableCellHeader";
import TablePagination from "@saleor/components/TablePagination";
import TableRowLink from "@saleor/components/TableRowLink";
@ -150,16 +151,18 @@ const PermissionGroupList: React.FC<PermissionGroupListProps> = props => {
{permissionGroup ? (
<>
{permissionGroup.userCanManage && (
<IconButton
variant="secondary"
data-test-id="delete-icon"
color="primary"
onClick={stopPropagation(() =>
onDelete(permissionGroup.id)
)}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
data-test-id="delete-icon"
color="primary"
onClick={stopPropagation(() =>
onDelete(permissionGroup.id)
)}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
)}
</>
) : (

View file

@ -9,10 +9,11 @@ import {
SortableTableBody,
SortableTableRow
} from "@saleor/components/SortableTable";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import { AttributeFragment, ProductAttributeType } from "@saleor/graphql";
import { DeleteIcon, IconButton, makeStyles } from "@saleor/macaw-ui";
import { maybe, renderCollection, stopPropagation } from "@saleor/misc";
import { maybe, renderCollection } from "@saleor/misc";
import { ListActions, ReorderAction } from "@saleor/types";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
@ -167,16 +168,16 @@ const ProductTypeAttributes: React.FC<ProductTypeAttributesProps> = props => {
)}
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
data-test-id="delete-icon"
disabled={disabled}
variant="secondary"
onClick={stopPropagation(() =>
onAttributeUnassign(attribute.id)
)}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
data-test-id="delete-icon"
disabled={disabled}
variant="secondary"
onClick={() => onAttributeUnassign(attribute.id)}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</SortableTableRow>
);

View file

@ -10,10 +10,11 @@ import {
SortableTableBody,
SortableTableRow
} from "@saleor/components/SortableTable";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import { ProductAttributeType, ProductTypeDetailsQuery } from "@saleor/graphql";
import { DeleteIcon, IconButton, makeStyles } from "@saleor/macaw-ui";
import { maybe, renderCollection, stopPropagation } from "@saleor/misc";
import { maybe, renderCollection } from "@saleor/misc";
import { ListActions, ReorderAction } from "@saleor/types";
import capitalize from "lodash/capitalize";
import React, { useEffect } from "react";
@ -268,14 +269,14 @@ const ProductTypeVariantAttributes: React.FC<ProductTypeVariantAttributesProps>
</div>
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
data-test-id="delete-icon"
onClick={stopPropagation(() =>
onAttributeUnassign(attribute.id)
)}
>
<DeleteIcon color="primary" />
</IconButton>
<TableButtonWrapper>
<IconButton
data-test-id="delete-icon"
onClick={() => onAttributeUnassign(attribute.id)}
>
<DeleteIcon color="primary" />
</IconButton>
</TableButtonWrapper>
</TableCell>
</SortableTableRow>
);

View file

@ -147,7 +147,10 @@ const ProductVariantNavigation: React.FC<ProductVariantNavigationProps> = props
{!isCreate ? (
<TableRow>
<TableCell colSpan={3}>
<Button href={productVariantAddUrl(productId)}>
<Button
href={productVariantAddUrl(productId)}
data-test-id="button-add-variant"
>
<FormattedMessage
id="3C3Nj5"
defaultMessage="Add variant"

View file

@ -19,6 +19,7 @@ import {
SortableTableBody,
SortableTableRow
} from "@saleor/components/SortableTable";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import {
ProductDetailsVariantFragment,
@ -459,17 +460,20 @@ export const ProductVariants: React.FC<ProductVariantsProps> = props => {
)
)}
</TableCell>
<TableCell
className={classes.colActions}
data-test-id="actions"
onClick={e => e.stopPropagation()}
>
{variant?.id !== product?.defaultVariant?.id && (
<ProductVariantSetDefault
onSetDefaultVariant={() => onSetDefaultVariant(variant)}
/>
)}
</TableCell>
<TableButtonWrapper>
<TableCell
className={classes.colActions}
data-test-id="actions"
>
{variant?.id !== product?.defaultVariant?.id && (
<ProductVariantSetDefault
onSetDefaultVariant={() =>
onSetDefaultVariant(variant)
}
/>
)}
</TableCell>
</TableButtonWrapper>
</SortableTableRow>
);
})}

View file

@ -12,6 +12,7 @@ import Money from "@saleor/components/Money";
import MoneyRange from "@saleor/components/MoneyRange";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableRowLink from "@saleor/components/TableRowLink";
import WeightRange from "@saleor/components/WeightRange";
import { ShippingZoneDetailsFragment } from "@saleor/graphql";
@ -180,20 +181,24 @@ const ShippingZoneRates: React.FC<ShippingZoneRatesProps> = props => {
<Skeleton />
)}
</TableCell>
<IconButtonTableCell
disabled={disabled}
onClick={() => navigate(getRateEditHref(rate.id))}
className={classes.buttonColumn}
>
<EditIcon />
</IconButtonTableCell>
<IconButtonTableCell
disabled={disabled}
onClick={() => onRateRemove(rate.id)}
className={classes.buttonColumn}
>
<DeleteIcon />
</IconButtonTableCell>
<TableButtonWrapper>
<IconButtonTableCell
disabled={disabled}
onClick={() => navigate(getRateEditHref(rate.id))}
className={classes.buttonColumn}
>
<EditIcon />
</IconButtonTableCell>
</TableButtonWrapper>
<TableButtonWrapper>
<IconButtonTableCell
disabled={disabled}
onClick={() => onRateRemove(rate.id)}
className={classes.buttonColumn}
>
<DeleteIcon />
</IconButtonTableCell>
</TableButtonWrapper>
</TableRowLink>
);
},

View file

@ -10,6 +10,7 @@ import CardTitle from "@saleor/components/CardTitle";
import Checkbox from "@saleor/components/Checkbox";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableHead from "@saleor/components/TableHead";
import TablePagination from "@saleor/components/TablePagination";
import TableRowLink from "@saleor/components/TableRowLink";
@ -171,17 +172,19 @@ const ShippingZonesList: React.FC<ShippingZonesListProps> = props => {
)}
</TableCell>
<TableCell className={classes.colAction}>
<IconButton
variant="secondary"
color="primary"
disabled={disabled}
onClick={event => {
event.stopPropagation();
onRemove(shippingZone.id);
}}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
disabled={disabled}
onClick={event => {
event.stopPropagation();
onRemove(shippingZone.id);
}}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
);

File diff suppressed because it is too large Load diff

View file

@ -8,6 +8,7 @@ import {
import EditIcon from "@material-ui/icons/Edit";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellHeader from "@saleor/components/TableCellHeader";
import TablePagination from "@saleor/components/TablePagination";
import TableRowLink from "@saleor/components/TableRowLink";
@ -163,13 +164,15 @@ const WarehouseList: React.FC<WarehouseListProps> = props => {
>
<EditIcon />
</IconButton>
<IconButton
variant="secondary"
color="primary"
onClick={stopPropagation(() => onRemove(warehouse.id))}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
onClick={stopPropagation(() => onRemove(warehouse.id))}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</div>
</TableCell>
</TableRowLink>

View file

@ -9,6 +9,7 @@ import { Button } from "@saleor/components/Button";
import CardTitle from "@saleor/components/CardTitle";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import { TableButtonWrapper } from "@saleor/components/TableButtonWrapper/TableButtonWrapper";
import TableCellHeader from "@saleor/components/TableCellHeader";
import TableRowLink from "@saleor/components/TableRowLink";
import { AppQuery } from "@saleor/graphql";
@ -109,17 +110,19 @@ const WebhooksList: React.FC<WebhooksListProps> = ({
<TableCell
className={classNames(classes.colAction, classes.colRight)}
>
<IconButton
variant="secondary"
color="primary"
onClick={
webhook
? stopPropagation(() => onRemove(webhook.id))
: undefined
}
>
<DeleteIcon />
</IconButton>
<TableButtonWrapper>
<IconButton
variant="secondary"
color="primary"
onClick={
webhook
? stopPropagation(() => onRemove(webhook.id))
: undefined
}
>
<DeleteIcon />
</IconButton>
</TableButtonWrapper>
</TableCell>
</TableRowLink>
),