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:
parent
ad7e6458b5
commit
9c2ed377cc
30 changed files with 840 additions and 722 deletions
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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>
|
||||
) : (
|
||||
|
|
|
@ -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>
|
||||
) : (
|
||||
|
|
|
@ -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 =>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
44
src/components/TableButtonWrapper/TableButtonWrapper.tsx
Normal file
44
src/components/TableButtonWrapper/TableButtonWrapper.tsx
Normal 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;
|
||||
};
|
0
src/components/TableButtonWrapper/index.tsx
Normal file
0
src/components/TableButtonWrapper/index.tsx
Normal 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>
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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}
|
||||
|
|
20
src/misc.ts
20
src/misc.ts
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
})}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -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
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue