Add hover tooltip on sorting disabled columns (#1811)
* Add hover tooltip on sorting disabled columns in lists (#1784) * Update macaw * Add TooltipTableCellHeader component * Add filterDependency type to lists * Add tooltip to conditional columns in Voucher List * Add tooltip to conditional columns in Sale List * Add tooltip to conditional columns in Collection List * Add tooltip to conditional columns in Product List * Update snapshots * Improve component clarity * Change TableCellHeader to React.forwardRef component * Change TooltipTableCellHeader to use TableCellHeader * Remove RefTableCellHeader * Bump macaw * Update snapshots * Remove merge conflict leftovers * Add tooltip header to gift card list * Refactor gift card list tooltip Co-authored-by: Wojciech <wojciech.mista@hotmail.com>
This commit is contained in:
parent
f9e1bb0569
commit
519b816afa
16 changed files with 211 additions and 99 deletions
|
@ -2501,6 +2501,9 @@
|
||||||
"src_dot_components_dot_Timeline_dot_3028189627": {
|
"src_dot_components_dot_Timeline_dot_3028189627": {
|
||||||
"string": "Leave your note here..."
|
"string": "Leave your note here..."
|
||||||
},
|
},
|
||||||
|
"src_dot_components_dot_TooltipTableCellHeader_dot_noFilterSelected": {
|
||||||
|
"string": "Sorting by this column requires active filter: {filterName}"
|
||||||
|
},
|
||||||
"src_dot_components_dot_UserChip_dot_21332146": {
|
"src_dot_components_dot_UserChip_dot_21332146": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Log out"
|
"string": "Log out"
|
||||||
|
|
|
@ -9,12 +9,14 @@ import Skeleton from "@saleor/components/Skeleton";
|
||||||
import TableCellHeader from "@saleor/components/TableCellHeader";
|
import TableCellHeader from "@saleor/components/TableCellHeader";
|
||||||
import TableHead from "@saleor/components/TableHead";
|
import TableHead from "@saleor/components/TableHead";
|
||||||
import TablePagination from "@saleor/components/TablePagination";
|
import TablePagination from "@saleor/components/TablePagination";
|
||||||
|
import TooltipTableCellHeader from "@saleor/components/TooltipTableCellHeader";
|
||||||
|
import { commonTooltipMessages } from "@saleor/components/TooltipTableCellHeader/messages";
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
import { maybe, renderCollection } from "@saleor/misc";
|
import { maybe, renderCollection } from "@saleor/misc";
|
||||||
import { ChannelProps, ListActions, ListProps, SortPage } from "@saleor/types";
|
import { ChannelProps, ListActions, ListProps, SortPage } from "@saleor/types";
|
||||||
import { getArrowDirection } from "@saleor/utils/sort";
|
import { getArrowDirection } from "@saleor/utils/sort";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { CollectionList_collections_edges_node } from "../../types/CollectionList";
|
import { CollectionList_collections_edges_node } from "../../types/CollectionList";
|
||||||
import { messages } from "./messages";
|
import { messages } from "./messages";
|
||||||
|
@ -73,10 +75,12 @@ const CollectionList: React.FC<CollectionListProps> = props => {
|
||||||
selectedChannelId,
|
selectedChannelId,
|
||||||
toggle,
|
toggle,
|
||||||
toggleAll,
|
toggleAll,
|
||||||
toolbar
|
toolbar,
|
||||||
|
filterDependency
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResponsiveTable>
|
<ResponsiveTable>
|
||||||
|
@ -111,7 +115,7 @@ const CollectionList: React.FC<CollectionListProps> = props => {
|
||||||
>
|
>
|
||||||
<FormattedMessage defaultMessage="No. of Products" />
|
<FormattedMessage defaultMessage="No. of Products" />
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
<TableCellHeader
|
<TooltipTableCellHeader
|
||||||
direction={
|
direction={
|
||||||
sort.sort === CollectionListUrlSortField.available
|
sort.sort === CollectionListUrlSortField.available
|
||||||
? getArrowDirection(sort.asc)
|
? getArrowDirection(sort.asc)
|
||||||
|
@ -125,12 +129,15 @@ const CollectionList: React.FC<CollectionListProps> = props => {
|
||||||
!!selectedChannelId
|
!!selectedChannelId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
tooltip={intl.formatMessage(commonTooltipMessages.noFilterSelected, {
|
||||||
|
filterName: filterDependency.label
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Availability"
|
defaultMessage="Availability"
|
||||||
description="collection availability"
|
description="collection availability"
|
||||||
/>
|
/>
|
||||||
</TableCellHeader>
|
</TooltipTableCellHeader>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableFooter>
|
<TableFooter>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Card } from "@material-ui/core";
|
import { Card } from "@material-ui/core";
|
||||||
import { CollectionListUrlSortField } from "@saleor/collections/urls";
|
import { CollectionListUrlSortField } from "@saleor/collections/urls";
|
||||||
import { Container } from "@saleor/components/Container";
|
import { Container } from "@saleor/components/Container";
|
||||||
|
import { getByName } from "@saleor/components/Filter/utils";
|
||||||
import FilterBar from "@saleor/components/FilterBar";
|
import FilterBar from "@saleor/components/FilterBar";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
@ -57,6 +58,8 @@ const CollectionListPage: React.FC<CollectionListPageProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||||
|
|
||||||
|
const filterDependency = filterStructure.find(getByName("channel"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<PageHeader title={intl.formatMessage(sectionNames.collections)}>
|
<PageHeader title={intl.formatMessage(sectionNames.collections)}>
|
||||||
|
@ -97,6 +100,7 @@ const CollectionListPage: React.FC<CollectionListPageProps> = ({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
channelsCount={channelsCount}
|
channelsCount={channelsCount}
|
||||||
selectedChannelId={selectedChannelId}
|
selectedChannelId={selectedChannelId}
|
||||||
|
filterDependency={filterDependency}
|
||||||
{...listProps}
|
{...listProps}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -63,61 +63,64 @@ export interface TableCellHeaderProps extends TableCellProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TableCellHeader: React.FC<TableCellHeaderProps> = props => {
|
const TableCellHeader = React.forwardRef<unknown, TableCellHeaderProps>(
|
||||||
const classes = useStyles(props);
|
(props, ref) => {
|
||||||
const {
|
const classes = useStyles(props);
|
||||||
arrowPosition,
|
const {
|
||||||
children,
|
arrowPosition,
|
||||||
className,
|
children,
|
||||||
direction,
|
className,
|
||||||
textAlign,
|
direction,
|
||||||
disabled = false,
|
textAlign,
|
||||||
onClick,
|
disabled = false,
|
||||||
title,
|
onClick,
|
||||||
...rest
|
title,
|
||||||
} = props;
|
...rest
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableCell
|
<TableCell
|
||||||
{...rest}
|
{...rest}
|
||||||
onClick={e => {
|
innerRef={ref}
|
||||||
if (disabled || !onClick) {
|
onClick={e => {
|
||||||
e.preventDefault();
|
if (disabled || !onClick) {
|
||||||
} else {
|
e.preventDefault();
|
||||||
onClick(e);
|
} else {
|
||||||
}
|
onClick(e);
|
||||||
}}
|
}
|
||||||
className={classNames(classes.root, className, {
|
}}
|
||||||
[classes.disabled]: disabled,
|
className={classNames(classes.root, className, {
|
||||||
[classes.notSortable]: !onClick
|
[classes.disabled]: disabled,
|
||||||
})}
|
[classes.notSortable]: !onClick
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={classNames(classes.labelContainer, {
|
|
||||||
[classes.labelContainerActive]: !!direction && !!arrowPosition,
|
|
||||||
[classes.labelContainerCenter]: textAlign === "center",
|
|
||||||
[classes.labelContainerRight]: textAlign === "right"
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{!!direction && arrowPosition === "left" && (
|
<div
|
||||||
<ArrowSort
|
className={classNames(classes.labelContainer, {
|
||||||
className={classNames(classes.arrow, classes.arrowLeft, {
|
[classes.labelContainerActive]: !!direction && !!arrowPosition,
|
||||||
[classes.arrowUp]: direction === "asc"
|
[classes.labelContainerCenter]: textAlign === "center",
|
||||||
})}
|
[classes.labelContainerRight]: textAlign === "right"
|
||||||
/>
|
})}
|
||||||
)}
|
>
|
||||||
<div className={classes.label}>{children}</div>
|
{!!direction && arrowPosition === "left" && (
|
||||||
{!!direction && arrowPosition === "right" && (
|
<ArrowSort
|
||||||
<ArrowSort
|
className={classNames(classes.arrow, classes.arrowLeft, {
|
||||||
className={classNames(classes.arrow, {
|
[classes.arrowUp]: direction === "asc"
|
||||||
[classes.arrowUp]: direction === "asc"
|
})}
|
||||||
})}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
<div className={classes.label}>{children}</div>
|
||||||
</div>
|
{!!direction && arrowPosition === "right" && (
|
||||||
</TableCell>
|
<ArrowSort
|
||||||
);
|
className={classNames(classes.arrow, {
|
||||||
};
|
[classes.arrowUp]: direction === "asc"
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
TableCellHeader.displayName = "TableCellHeader";
|
TableCellHeader.displayName = "TableCellHeader";
|
||||||
TableCellHeader.defaultProps = {
|
TableCellHeader.defaultProps = {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Tooltip } from "@saleor/macaw-ui";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import TableCellHeader, { TableCellHeaderProps } from "../TableCellHeader";
|
||||||
|
|
||||||
|
interface TooltipTableCellHeaderProps extends TableCellHeaderProps {
|
||||||
|
tooltip?: string | React.ReactNodeArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TooltipTableCellHeader: React.FC<TooltipTableCellHeaderProps> = props => {
|
||||||
|
const { children, tooltip, disabled, ...rest } = props;
|
||||||
|
|
||||||
|
const tooltipDisabled = () => {
|
||||||
|
if (!tooltip) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !disabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={tooltip} placement="top" disabled={tooltipDisabled()}>
|
||||||
|
<TableCellHeader disabled={disabled} {...rest}>
|
||||||
|
{children}
|
||||||
|
</TableCellHeader>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TooltipTableCellHeader.displayName = "TooltipTableCellHeader";
|
||||||
|
export default TooltipTableCellHeader;
|
2
src/components/TooltipTableCellHeader/index.ts
Normal file
2
src/components/TooltipTableCellHeader/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./TooltipTableCellHeader";
|
||||||
|
export * from "./TooltipTableCellHeader";
|
8
src/components/TooltipTableCellHeader/messages.ts
Normal file
8
src/components/TooltipTableCellHeader/messages.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const commonTooltipMessages = defineMessages({
|
||||||
|
noFilterSelected: {
|
||||||
|
defaultMessage:
|
||||||
|
"Sorting by this column requires active filter: {filterName}"
|
||||||
|
}
|
||||||
|
});
|
|
@ -8,6 +8,8 @@ import Skeleton from "@saleor/components/Skeleton";
|
||||||
import TableCellHeader from "@saleor/components/TableCellHeader";
|
import TableCellHeader from "@saleor/components/TableCellHeader";
|
||||||
import TableHead from "@saleor/components/TableHead";
|
import TableHead from "@saleor/components/TableHead";
|
||||||
import TablePagination from "@saleor/components/TablePagination";
|
import TablePagination from "@saleor/components/TablePagination";
|
||||||
|
import TooltipTableCellHeader from "@saleor/components/TooltipTableCellHeader";
|
||||||
|
import { commonTooltipMessages } from "@saleor/components/TooltipTableCellHeader/messages";
|
||||||
import { SaleListUrlSortField } from "@saleor/discounts/urls";
|
import { SaleListUrlSortField } from "@saleor/discounts/urls";
|
||||||
import { canBeSorted } from "@saleor/discounts/views/SaleList/sort";
|
import { canBeSorted } from "@saleor/discounts/views/SaleList/sort";
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
@ -17,7 +19,7 @@ import { SaleType } from "@saleor/types/globalTypes";
|
||||||
import { getArrowDirection } from "@saleor/utils/sort";
|
import { getArrowDirection } from "@saleor/utils/sort";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { SaleList_sales_edges_node } from "../../types/SaleList";
|
import { SaleList_sales_edges_node } from "../../types/SaleList";
|
||||||
|
|
||||||
|
@ -83,10 +85,12 @@ const SaleList: React.FC<SaleListProps> = props => {
|
||||||
sort,
|
sort,
|
||||||
toggle,
|
toggle,
|
||||||
toggleAll,
|
toggleAll,
|
||||||
toolbar
|
toolbar,
|
||||||
|
filterDependency
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
const intl = useIntl();
|
||||||
const numberOfColumns = sales?.length === 0 ? 4 : 5;
|
const numberOfColumns = sales?.length === 0 ? 4 : 5;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -138,7 +142,7 @@ const SaleList: React.FC<SaleListProps> = props => {
|
||||||
>
|
>
|
||||||
<FormattedMessage defaultMessage="Ends" description="sale end date" />
|
<FormattedMessage defaultMessage="Ends" description="sale end date" />
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
<TableCellHeader
|
<TooltipTableCellHeader
|
||||||
direction={
|
direction={
|
||||||
sort.sort === SaleListUrlSortField.value
|
sort.sort === SaleListUrlSortField.value
|
||||||
? getArrowDirection(sort.asc)
|
? getArrowDirection(sort.asc)
|
||||||
|
@ -149,10 +153,13 @@ const SaleList: React.FC<SaleListProps> = props => {
|
||||||
disabled={
|
disabled={
|
||||||
!canBeSorted(SaleListUrlSortField.value, !!selectedChannelId)
|
!canBeSorted(SaleListUrlSortField.value, !!selectedChannelId)
|
||||||
}
|
}
|
||||||
|
tooltip={intl.formatMessage(commonTooltipMessages.noFilterSelected, {
|
||||||
|
filterName: filterDependency.label
|
||||||
|
})}
|
||||||
className={classes.colValue}
|
className={classes.colValue}
|
||||||
>
|
>
|
||||||
<FormattedMessage defaultMessage="Value" description="sale value" />
|
<FormattedMessage defaultMessage="Value" description="sale value" />
|
||||||
</TableCellHeader>
|
</TooltipTableCellHeader>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableFooter>
|
<TableFooter>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Card } from "@material-ui/core";
|
import { Card } from "@material-ui/core";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
|
import { getByName } from "@saleor/components/Filter/utils";
|
||||||
import FilterBar from "@saleor/components/FilterBar";
|
import FilterBar from "@saleor/components/FilterBar";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import { SaleListUrlSortField } from "@saleor/discounts/urls";
|
import { SaleListUrlSortField } from "@saleor/discounts/urls";
|
||||||
|
@ -51,6 +52,8 @@ const SaleListPage: React.FC<SaleListPageProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const structure = createFilterStructure(intl, filterOpts);
|
const structure = createFilterStructure(intl, filterOpts);
|
||||||
|
|
||||||
|
const filterDependency = structure.find(getByName("channel"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<PageHeader title={intl.formatMessage(sectionNames.sales)}>
|
<PageHeader title={intl.formatMessage(sectionNames.sales)}>
|
||||||
|
@ -78,7 +81,7 @@ const SaleListPage: React.FC<SaleListPageProps> = ({
|
||||||
onTabDelete={onTabDelete}
|
onTabDelete={onTabDelete}
|
||||||
onTabSave={onTabSave}
|
onTabSave={onTabSave}
|
||||||
/>
|
/>
|
||||||
<SaleList {...listProps} />
|
<SaleList filterDependency={filterDependency} {...listProps} />
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,6 +8,8 @@ import Skeleton from "@saleor/components/Skeleton";
|
||||||
import TableCellHeader from "@saleor/components/TableCellHeader";
|
import TableCellHeader from "@saleor/components/TableCellHeader";
|
||||||
import TableHead from "@saleor/components/TableHead";
|
import TableHead from "@saleor/components/TableHead";
|
||||||
import TablePagination from "@saleor/components/TablePagination";
|
import TablePagination from "@saleor/components/TablePagination";
|
||||||
|
import TooltipTableCellHeader from "@saleor/components/TooltipTableCellHeader";
|
||||||
|
import { commonTooltipMessages } from "@saleor/components/TooltipTableCellHeader/messages";
|
||||||
import { VoucherListUrlSortField } from "@saleor/discounts/urls";
|
import { VoucherListUrlSortField } from "@saleor/discounts/urls";
|
||||||
import { canBeSorted } from "@saleor/discounts/views/VoucherList/sort";
|
import { canBeSorted } from "@saleor/discounts/views/VoucherList/sort";
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
@ -18,7 +20,7 @@ import { getArrowDirection } from "@saleor/utils/sort";
|
||||||
import { getFooterColSpanWithBulkActions } from "@saleor/utils/tables";
|
import { getFooterColSpanWithBulkActions } from "@saleor/utils/tables";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { VoucherList_vouchers_edges_node } from "../../types/VoucherList";
|
import { VoucherList_vouchers_edges_node } from "../../types/VoucherList";
|
||||||
|
|
||||||
|
@ -101,10 +103,12 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
||||||
sort,
|
sort,
|
||||||
toggle,
|
toggle,
|
||||||
toggleAll,
|
toggleAll,
|
||||||
toolbar
|
toolbar,
|
||||||
|
filterDependency
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResponsiveTable>
|
<ResponsiveTable>
|
||||||
|
@ -128,7 +132,7 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
||||||
>
|
>
|
||||||
<FormattedMessage defaultMessage="Code" description="voucher code" />
|
<FormattedMessage defaultMessage="Code" description="voucher code" />
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
<TableCellHeader
|
<TooltipTableCellHeader
|
||||||
direction={
|
direction={
|
||||||
sort.sort === VoucherListUrlSortField.minSpent
|
sort.sort === VoucherListUrlSortField.minSpent
|
||||||
? getArrowDirection(sort.asc)
|
? getArrowDirection(sort.asc)
|
||||||
|
@ -140,12 +144,15 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
||||||
!canBeSorted(VoucherListUrlSortField.minSpent, !!selectedChannelId)
|
!canBeSorted(VoucherListUrlSortField.minSpent, !!selectedChannelId)
|
||||||
}
|
}
|
||||||
className={classes.colMinSpent}
|
className={classes.colMinSpent}
|
||||||
|
tooltip={intl.formatMessage(commonTooltipMessages.noFilterSelected, {
|
||||||
|
filterName: filterDependency.label
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Min. Spent"
|
defaultMessage="Min. Spent"
|
||||||
description="minimum amount of spent money to activate voucher"
|
description="minimum amount of spent money to activate voucher"
|
||||||
/>
|
/>
|
||||||
</TableCellHeader>
|
</TooltipTableCellHeader>
|
||||||
<TableCellHeader
|
<TableCellHeader
|
||||||
direction={
|
direction={
|
||||||
sort.sort === VoucherListUrlSortField.startDate
|
sort.sort === VoucherListUrlSortField.startDate
|
||||||
|
@ -176,7 +183,7 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
||||||
description="voucher is active until date"
|
description="voucher is active until date"
|
||||||
/>
|
/>
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
<TableCellHeader
|
<TooltipTableCellHeader
|
||||||
direction={
|
direction={
|
||||||
sort.sort === VoucherListUrlSortField.value
|
sort.sort === VoucherListUrlSortField.value
|
||||||
? getArrowDirection(sort.asc)
|
? getArrowDirection(sort.asc)
|
||||||
|
@ -188,12 +195,15 @@ const VoucherList: React.FC<VoucherListProps> = props => {
|
||||||
!canBeSorted(VoucherListUrlSortField.minSpent, !!selectedChannelId)
|
!canBeSorted(VoucherListUrlSortField.minSpent, !!selectedChannelId)
|
||||||
}
|
}
|
||||||
className={classes.colValue}
|
className={classes.colValue}
|
||||||
|
tooltip={intl.formatMessage(commonTooltipMessages.noFilterSelected, {
|
||||||
|
filterName: filterDependency.label
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Value"
|
defaultMessage="Value"
|
||||||
description="voucher value"
|
description="voucher value"
|
||||||
/>
|
/>
|
||||||
</TableCellHeader>
|
</TooltipTableCellHeader>
|
||||||
<TableCellHeader
|
<TableCellHeader
|
||||||
direction={
|
direction={
|
||||||
sort.sort === VoucherListUrlSortField.limit
|
sort.sort === VoucherListUrlSortField.limit
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Card } from "@material-ui/core";
|
import { Card } from "@material-ui/core";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
|
import { getByName } from "@saleor/components/Filter/utils";
|
||||||
import FilterBar from "@saleor/components/FilterBar";
|
import FilterBar from "@saleor/components/FilterBar";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import { VoucherListUrlSortField } from "@saleor/discounts/urls";
|
import { VoucherListUrlSortField } from "@saleor/discounts/urls";
|
||||||
|
@ -50,6 +51,8 @@ const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const structure = createFilterStructure(intl, filterOpts);
|
const structure = createFilterStructure(intl, filterOpts);
|
||||||
|
|
||||||
|
const filterDependency = structure.find(getByName("channel"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<PageHeader title={intl.formatMessage(sectionNames.vouchers)}>
|
<PageHeader title={intl.formatMessage(sectionNames.vouchers)}>
|
||||||
|
@ -80,7 +83,7 @@ const VoucherListPage: React.FC<VoucherListPageProps> = ({
|
||||||
onTabDelete={onTabDelete}
|
onTabDelete={onTabDelete}
|
||||||
onTabSave={onTabSave}
|
onTabSave={onTabSave}
|
||||||
/>
|
/>
|
||||||
<VoucherList {...listProps} />
|
<VoucherList filterDependency={filterDependency} {...listProps} />
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
|
@ -164,7 +164,7 @@ export function getFilterQueryParam(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const messages = defineMessages({
|
export const messages = defineMessages({
|
||||||
balanceAmountLabel: {
|
balanceAmountLabel: {
|
||||||
defaultMessage: "Amount",
|
defaultMessage: "Amount",
|
||||||
description: "amount filter label"
|
description: "amount filter label"
|
||||||
|
|
|
@ -5,6 +5,8 @@ import TableCellHeader, {
|
||||||
TableCellHeaderProps
|
TableCellHeaderProps
|
||||||
} from "@saleor/components/TableCellHeader";
|
} from "@saleor/components/TableCellHeader";
|
||||||
import TableHead from "@saleor/components/TableHead";
|
import TableHead from "@saleor/components/TableHead";
|
||||||
|
import TooltipTableCellHeader from "@saleor/components/TooltipTableCellHeader";
|
||||||
|
import { commonTooltipMessages } from "@saleor/components/TooltipTableCellHeader/messages";
|
||||||
import Label, {
|
import Label, {
|
||||||
LabelSizes
|
LabelSizes
|
||||||
} from "@saleor/orders/components/OrderHistory/Label";
|
} from "@saleor/orders/components/OrderHistory/Label";
|
||||||
|
@ -12,6 +14,7 @@ import { getArrowDirection } from "@saleor/utils/sort";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { MessageDescriptor, useIntl } from "react-intl";
|
import { MessageDescriptor, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { messages as filterLabels } from "../../GiftCardListSearchAndFilters/filters";
|
||||||
import { giftCardsListTableMessages as messages } from "../../messages";
|
import { giftCardsListTableMessages as messages } from "../../messages";
|
||||||
import useGiftCardListDialogs from "../../providers/GiftCardListDialogsProvider/hooks/useGiftCardListDialogs";
|
import useGiftCardListDialogs from "../../providers/GiftCardListDialogsProvider/hooks/useGiftCardListDialogs";
|
||||||
import useGiftCardListSort from "../../providers/GiftCardListDialogsProvider/hooks/useGiftCardListSort";
|
import useGiftCardListSort from "../../providers/GiftCardListDialogsProvider/hooks/useGiftCardListSort";
|
||||||
|
@ -27,7 +30,6 @@ interface HeaderItem {
|
||||||
options?: TableCellHeaderProps;
|
options?: TableCellHeaderProps;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
direction?: TableCellHeaderArrowDirection;
|
direction?: TableCellHeaderArrowDirection;
|
||||||
canBeSorted?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GiftCardsListTableHeaderProps {
|
interface GiftCardsListTableHeaderProps {
|
||||||
|
@ -68,19 +70,28 @@ const GiftCardsListTableHeader: React.FC<GiftCardsListTableHeaderProps> = ({
|
||||||
title: messages.giftCardsTableColumnCustomerTitle,
|
title: messages.giftCardsTableColumnCustomerTitle,
|
||||||
onClick: () => onSort(GiftCardUrlSortField.usedBy),
|
onClick: () => onSort(GiftCardUrlSortField.usedBy),
|
||||||
direction: getDirection(GiftCardUrlSortField.usedBy)
|
direction: getDirection(GiftCardUrlSortField.usedBy)
|
||||||
},
|
|
||||||
{
|
|
||||||
title: messages.giftCardsTableColumnBalanceTitle,
|
|
||||||
options: {
|
|
||||||
className: classes.colBalance,
|
|
||||||
textAlign: "right"
|
|
||||||
},
|
|
||||||
onClick: () => onSort(GiftCardUrlSortField.balance),
|
|
||||||
direction: getDirection(GiftCardUrlSortField.balance),
|
|
||||||
canBeSorted: canBeSorted(GiftCardUrlSortField.balance, isCurrencySelected)
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const headerTooltipItem: HeaderItem & {
|
||||||
|
disabled: boolean;
|
||||||
|
tooltip: string | React.ReactNodeArray;
|
||||||
|
} = {
|
||||||
|
title: messages.giftCardsTableColumnBalanceTitle,
|
||||||
|
options: {
|
||||||
|
className: classes.colBalance,
|
||||||
|
textAlign: "right"
|
||||||
|
},
|
||||||
|
onClick: () => onSort(GiftCardUrlSortField.balance),
|
||||||
|
direction: getDirection(GiftCardUrlSortField.balance),
|
||||||
|
disabled: !canBeSorted(GiftCardUrlSortField.balance, isCurrencySelected),
|
||||||
|
tooltip: intl.formatMessage(commonTooltipMessages.noFilterSelected, {
|
||||||
|
filterName: <b>{filterLabels.currencyLabel.defaultMessage}</b>
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
const { title, ...headerTooltipItemProps } = headerTooltipItem;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<colgroup>
|
<colgroup>
|
||||||
|
@ -105,18 +116,22 @@ const GiftCardsListTableHeader: React.FC<GiftCardsListTableHeaderProps> = ({
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{headerItems.map(
|
{headerItems.map(({ title, options, onClick, direction }) => (
|
||||||
({ title, options, onClick, direction, canBeSorted = true }) => (
|
<TableCellHeader
|
||||||
<TableCellHeader
|
{...options}
|
||||||
{...options}
|
onClick={onClick}
|
||||||
onClick={onClick}
|
direction={direction}
|
||||||
disabled={!canBeSorted}
|
key={title.defaultMessage}
|
||||||
direction={direction}
|
>
|
||||||
>
|
<Label text={intl.formatMessage(title)} size={LabelSizes.md} />
|
||||||
<Label text={intl.formatMessage(title)} size={LabelSizes.md} />
|
</TableCellHeader>
|
||||||
</TableCellHeader>
|
))}
|
||||||
)
|
<TooltipTableCellHeader {...headerTooltipItemProps}>
|
||||||
)}
|
<Label
|
||||||
|
text={intl.formatMessage(headerTooltipItem.title)}
|
||||||
|
size={LabelSizes.md}
|
||||||
|
/>
|
||||||
|
</TooltipTableCellHeader>
|
||||||
<TableCell className={classes.colDelete} />
|
<TableCell className={classes.colDelete} />
|
||||||
</TableHead>
|
</TableHead>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -17,6 +17,8 @@ import { AVATAR_MARGIN } from "@saleor/components/TableCellAvatar/Avatar";
|
||||||
import TableCellHeader from "@saleor/components/TableCellHeader";
|
import TableCellHeader from "@saleor/components/TableCellHeader";
|
||||||
import TableHead from "@saleor/components/TableHead";
|
import TableHead from "@saleor/components/TableHead";
|
||||||
import TablePagination from "@saleor/components/TablePagination";
|
import TablePagination from "@saleor/components/TablePagination";
|
||||||
|
import TooltipTableCellHeader from "@saleor/components/TooltipTableCellHeader";
|
||||||
|
import { commonTooltipMessages } from "@saleor/components/TooltipTableCellHeader/messages";
|
||||||
import { ProductListColumns } from "@saleor/config";
|
import { ProductListColumns } from "@saleor/config";
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
import { maybe, renderCollection } from "@saleor/misc";
|
import { maybe, renderCollection } from "@saleor/misc";
|
||||||
|
@ -35,7 +37,7 @@ import TDisplayColumn, {
|
||||||
import { getArrowDirection } from "@saleor/utils/sort";
|
import { getArrowDirection } from "@saleor/utils/sort";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { columnsMessages, messages } from "./messages";
|
import { columnsMessages, messages } from "./messages";
|
||||||
|
|
||||||
|
@ -137,10 +139,12 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
||||||
onUpdateListSettings,
|
onUpdateListSettings,
|
||||||
onRowClick,
|
onRowClick,
|
||||||
onSort,
|
onSort,
|
||||||
selectedChannelId
|
selectedChannelId,
|
||||||
|
filterDependency
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
const intl = useIntl();
|
||||||
const gridAttributesFromSettings = settings.columns.filter(
|
const gridAttributesFromSettings = settings.columns.filter(
|
||||||
isAttributeColumnValue
|
isAttributeColumnValue
|
||||||
);
|
);
|
||||||
|
@ -215,7 +219,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
||||||
column="availability"
|
column="availability"
|
||||||
displayColumns={settings.columns}
|
displayColumns={settings.columns}
|
||||||
>
|
>
|
||||||
<TableCellHeader
|
<TooltipTableCellHeader
|
||||||
data-test-id="colAvailabilityHeader"
|
data-test-id="colAvailabilityHeader"
|
||||||
className={classes.colPublished}
|
className={classes.colPublished}
|
||||||
direction={
|
direction={
|
||||||
|
@ -230,9 +234,13 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
||||||
!!selectedChannelId
|
!!selectedChannelId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
tooltip={intl.formatMessage(
|
||||||
|
commonTooltipMessages.noFilterSelected,
|
||||||
|
{ filterName: filterDependency.label }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...columnsMessages.availability} />
|
<FormattedMessage {...columnsMessages.availability} />
|
||||||
</TableCellHeader>
|
</TooltipTableCellHeader>
|
||||||
</DisplayColumn>
|
</DisplayColumn>
|
||||||
{gridAttributesFromSettings.map(gridAttributeFromSettings => {
|
{gridAttributesFromSettings.map(gridAttributeFromSettings => {
|
||||||
const attributeId = getAttributeIdFromColumnValue(
|
const attributeId = getAttributeIdFromColumnValue(
|
||||||
|
@ -278,7 +286,7 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
||||||
</TableCellHeader>
|
</TableCellHeader>
|
||||||
</DisplayColumn>
|
</DisplayColumn>
|
||||||
<DisplayColumn column="price" displayColumns={settings.columns}>
|
<DisplayColumn column="price" displayColumns={settings.columns}>
|
||||||
<TableCellHeader
|
<TooltipTableCellHeader
|
||||||
data-test-id="colPriceHeader"
|
data-test-id="colPriceHeader"
|
||||||
className={classes.colPrice}
|
className={classes.colPrice}
|
||||||
direction={
|
direction={
|
||||||
|
@ -291,9 +299,13 @@ export const ProductList: React.FC<ProductListProps> = props => {
|
||||||
disabled={
|
disabled={
|
||||||
!canBeSorted(ProductListUrlSortField.price, !!selectedChannelId)
|
!canBeSorted(ProductListUrlSortField.price, !!selectedChannelId)
|
||||||
}
|
}
|
||||||
|
tooltip={intl.formatMessage(
|
||||||
|
commonTooltipMessages.noFilterSelected,
|
||||||
|
{ filterName: filterDependency.label }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<FormattedMessage {...columnsMessages.price} />
|
<FormattedMessage {...columnsMessages.price} />
|
||||||
</TableCellHeader>
|
</TooltipTableCellHeader>
|
||||||
</DisplayColumn>
|
</DisplayColumn>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableFooter>
|
<TableFooter>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ColumnPicker, {
|
||||||
ColumnPickerChoice
|
ColumnPickerChoice
|
||||||
} from "@saleor/components/ColumnPicker";
|
} from "@saleor/components/ColumnPicker";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
|
import { getByName } from "@saleor/components/Filter/utils";
|
||||||
import FilterBar from "@saleor/components/FilterBar";
|
import FilterBar from "@saleor/components/FilterBar";
|
||||||
import LimitReachedAlert from "@saleor/components/LimitReachedAlert";
|
import LimitReachedAlert from "@saleor/components/LimitReachedAlert";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
@ -114,6 +115,8 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
||||||
|
|
||||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||||
|
|
||||||
|
const filterDependency = filterStructure.find(getByName("channel"));
|
||||||
|
|
||||||
const columns: ColumnPickerChoice[] = [
|
const columns: ColumnPickerChoice[] = [
|
||||||
{
|
{
|
||||||
label: intl.formatMessage(columnsMessages.price),
|
label: intl.formatMessage(columnsMessages.price),
|
||||||
|
@ -241,6 +244,7 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
||||||
channelsCount={channelsCount}
|
channelsCount={channelsCount}
|
||||||
selectedChannelId={selectedChannelId}
|
selectedChannelId={selectedChannelId}
|
||||||
onUpdateListSettings={onUpdateListSettings}
|
onUpdateListSettings={onUpdateListSettings}
|
||||||
|
filterDependency={filterDependency}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||||
import { MutationResult } from "react-apollo";
|
import { MutationResult } from "react-apollo";
|
||||||
|
|
||||||
import { IFilter } from "./components/Filter";
|
import { IFilter, IFilterElement } from "./components/Filter";
|
||||||
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
||||||
import { User_userPermissions } from "./fragments/types/User";
|
import { User_userPermissions } from "./fragments/types/User";
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ export interface ListProps<TColumns extends string = string> {
|
||||||
value: ListSettings<TColumns>[T]
|
value: ListSettings<TColumns>[T]
|
||||||
) => void;
|
) => void;
|
||||||
onListSettingsReset?: () => void;
|
onListSettingsReset?: () => void;
|
||||||
|
filterDependency?: IFilterElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SortPage<TSortKey extends string> {
|
export interface SortPage<TSortKey extends string> {
|
||||||
|
|
Loading…
Reference in a new issue