Improve limit messages (#1274)
This commit is contained in:
parent
034eea0dcd
commit
6d3e346a19
11 changed files with 1762 additions and 59 deletions
|
@ -56,12 +56,18 @@ export const ChannelsListPage: React.FC<ChannelsListPageProps> = ({
|
|||
</Backlink>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(sectionNames.channels)}
|
||||
limit={
|
||||
hasLimits(limits, "channels") && {
|
||||
data: limits,
|
||||
key: "channels",
|
||||
text: "channels used"
|
||||
}
|
||||
limitText={
|
||||
hasLimits(limits, "channels") &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count}/{max} channels used",
|
||||
description: "created channels counter"
|
||||
},
|
||||
{
|
||||
count: limits.currentUsage.channels,
|
||||
max: limits.allowedUsage.channels
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<Button
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import { Typography } from "@material-ui/core";
|
||||
import { LimitInfoFragment } from "@saleor/fragments/types/LimitInfoFragment";
|
||||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
import React from "react";
|
||||
|
||||
import ExtendedPageHeader from "../ExtendedPageHeader";
|
||||
import { RefreshLimits_shop_limits } from "../Shop/types/RefreshLimits";
|
||||
import Skeleton from "../Skeleton";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
|
@ -40,27 +38,16 @@ const useStyles = makeStyles(
|
|||
{ name: "PageHeader" }
|
||||
);
|
||||
|
||||
interface LimitInfo {
|
||||
data: RefreshLimits_shop_limits;
|
||||
key: keyof LimitInfoFragment;
|
||||
text: string;
|
||||
}
|
||||
interface PageHeaderProps {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
inline?: boolean;
|
||||
limit?: LimitInfo;
|
||||
limitText?: string;
|
||||
title?: React.ReactNode;
|
||||
}
|
||||
|
||||
function formatLimit(limit: LimitInfo): string {
|
||||
return `${limit.data.currentUsage[limit.key]}/${
|
||||
limit.data.allowedUsage[limit.key]
|
||||
} ${limit.text}`;
|
||||
}
|
||||
|
||||
const PageHeader: React.FC<PageHeaderProps> = props => {
|
||||
const { children, className, inline, limit, title } = props;
|
||||
const { children, className, inline, limitText, title } = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
|
||||
|
@ -76,9 +63,9 @@ const PageHeader: React.FC<PageHeaderProps> = props => {
|
|||
}
|
||||
>
|
||||
<div className={classes.root}>
|
||||
{limit && (
|
||||
{limitText && (
|
||||
<Typography className={classes.limit} color="textSecondary">
|
||||
{formatLimit(limit)}
|
||||
{limitText}
|
||||
</Typography>
|
||||
)}
|
||||
{children}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Button, Card } from "@material-ui/core";
|
|||
import Container from "@saleor/components/Container";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import { RefreshLimits_shop_limits } from "@saleor/components/Shop/types/RefreshLimits";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { OrderDraftListUrlSortField } from "@saleor/orders/urls";
|
||||
import {
|
||||
|
@ -11,11 +12,13 @@ import {
|
|||
SortPage,
|
||||
TabPageProps
|
||||
} from "@saleor/types";
|
||||
import { hasLimits, isLimitReached } from "@saleor/utils/limits";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { OrderDraftList_draftOrders_edges_node } from "../../types/OrderDraftList";
|
||||
import OrderDraftList from "../OrderDraftList";
|
||||
import OrderLimitReached from "../OrderLimitReached";
|
||||
import {
|
||||
createFilterStructure,
|
||||
OrderDraftFilterKeys,
|
||||
|
@ -28,6 +31,7 @@ export interface OrderDraftListPageProps
|
|||
FilterPageProps<OrderDraftFilterKeys, OrderDraftListFilterOpts>,
|
||||
SortPage<OrderDraftListUrlSortField>,
|
||||
TabPageProps {
|
||||
limits: RefreshLimits_shop_limits;
|
||||
orders: OrderDraftList_draftOrders_edges_node[];
|
||||
}
|
||||
|
||||
|
@ -36,6 +40,7 @@ const OrderDraftListPage: React.FC<OrderDraftListPageProps> = ({
|
|||
disabled,
|
||||
filterOpts,
|
||||
initialSearch,
|
||||
limits,
|
||||
onAdd,
|
||||
onAll,
|
||||
onFilterChange,
|
||||
|
@ -48,14 +53,30 @@ const OrderDraftListPage: React.FC<OrderDraftListPageProps> = ({
|
|||
}) => {
|
||||
const intl = useIntl();
|
||||
const structure = createFilterStructure(intl, filterOpts);
|
||||
const limitsReached = isLimitReached(limits, "orders");
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.draftOrders)}>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(sectionNames.draftOrders)}
|
||||
limitText={
|
||||
hasLimits(limits, "orders") &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count}/{max} orders",
|
||||
description: "placed orders counter"
|
||||
},
|
||||
{
|
||||
count: limits.currentUsage.orders,
|
||||
max: limits.allowedUsage.orders
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
disabled={disabled}
|
||||
disabled={disabled || limitsReached}
|
||||
onClick={onAdd}
|
||||
>
|
||||
<FormattedMessage
|
||||
|
@ -64,6 +85,7 @@ const OrderDraftListPage: React.FC<OrderDraftListPageProps> = ({
|
|||
/>
|
||||
</Button>
|
||||
</PageHeader>
|
||||
{limitsReached && <OrderLimitReached />}
|
||||
<Card>
|
||||
<FilterBar
|
||||
allTabLabel={intl.formatMessage({
|
||||
|
|
21
src/orders/components/OrderLimitReached.tsx
Normal file
21
src/orders/components/OrderLimitReached.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import LimitReachedAlert from "@saleor/components/LimitReachedAlert";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
export const OrderLimitReached: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<LimitReachedAlert
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Order limit reached",
|
||||
description: "alert"
|
||||
})}
|
||||
>
|
||||
<FormattedMessage defaultMessage="You have reached your order limit, you will be billed extra for orders above limit. If you would like to up your limit, contact your administration staff about raising your limits." />
|
||||
</LimitReachedAlert>
|
||||
);
|
||||
};
|
||||
|
||||
OrderLimitReached.displayName = "OrderLimitReached";
|
||||
export default OrderLimitReached;
|
|
@ -2,18 +2,18 @@ import { Button, Card } from "@material-ui/core";
|
|||
import CardMenu from "@saleor/components/CardMenu";
|
||||
import Container from "@saleor/components/Container";
|
||||
import FilterBar from "@saleor/components/FilterBar";
|
||||
import LimitReachedAlert from "@saleor/components/LimitReachedAlert";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import { RefreshLimits_shop_limits } from "@saleor/components/Shop/types/RefreshLimits";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { makeStyles } from "@saleor/macaw-ui";
|
||||
import { OrderListUrlSortField } from "@saleor/orders/urls";
|
||||
import { FilterPageProps, PageListProps, SortPage } from "@saleor/types";
|
||||
import { isLimitReached } from "@saleor/utils/limits";
|
||||
import { hasLimits, isLimitReached } from "@saleor/utils/limits";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import { OrderList_orders_edges_node } from "../../types/OrderList";
|
||||
import OrderLimitReached from "../OrderLimitReached";
|
||||
import OrderList from "../OrderList";
|
||||
import {
|
||||
createFilterStructure,
|
||||
|
@ -58,10 +58,26 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
const intl = useIntl();
|
||||
const classes = useStyles({});
|
||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||
const limitsReached = isLimitReached(limits, "orders");
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<PageHeader title={intl.formatMessage(sectionNames.orders)}>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(sectionNames.orders)}
|
||||
limitText={
|
||||
hasLimits(limits, "orders") &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count}/{max} orders",
|
||||
description: "placed order counter"
|
||||
},
|
||||
{
|
||||
count: limits.currentUsage.orders,
|
||||
max: limits.allowedUsage.orders
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
{!!onSettingsOpen && (
|
||||
<CardMenu
|
||||
className={classes.settings}
|
||||
|
@ -77,6 +93,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
/>
|
||||
)}
|
||||
<Button
|
||||
disabled={limitsReached}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={onAdd}
|
||||
|
@ -88,16 +105,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
|||
/>
|
||||
</Button>
|
||||
</PageHeader>
|
||||
{isLimitReached(limits, "orders") && (
|
||||
<LimitReachedAlert
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Order limit reached",
|
||||
description: "alert"
|
||||
})}
|
||||
>
|
||||
<FormattedMessage defaultMessage="You have reached your order limit, you will be billed extra for orders above limit. If you would like to up your limit, contact your administration staff about raising your limits." />
|
||||
</LimitReachedAlert>
|
||||
)}
|
||||
{limitsReached && <OrderLimitReached />}
|
||||
<Card>
|
||||
<FilterBar
|
||||
currentTab={currentTab}
|
||||
|
|
|
@ -7,6 +7,7 @@ import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
|
|||
import SaveFilterTabDialog, {
|
||||
SaveFilterTabDialogFormData
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import { useShopLimitsQuery } from "@saleor/components/Shop/query";
|
||||
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
|
@ -81,6 +82,11 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
});
|
||||
|
||||
const { channel, availableChannels } = useAppChannel();
|
||||
const limitOpts = useShopLimitsQuery({
|
||||
variables: {
|
||||
orders: true
|
||||
}
|
||||
});
|
||||
|
||||
const tabs = getFilterTabs();
|
||||
|
||||
|
@ -183,6 +189,7 @@ export const OrderDraftList: React.FC<OrderDraftListProps> = ({ params }) => {
|
|||
<OrderDraftListPage
|
||||
currentTab={currentTab}
|
||||
filterOpts={getFilterOpts(params)}
|
||||
limits={limitOpts.data?.shop.limits}
|
||||
initialSearch={params.query || ""}
|
||||
onSearchChange={handleSearchChange}
|
||||
onFilterChange={changeFilters}
|
||||
|
|
|
@ -134,12 +134,18 @@ export const ProductListPage: React.FC<ProductListPageProps> = props => {
|
|||
<Container>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(sectionNames.products)}
|
||||
limit={
|
||||
hasLimits(limits, "productVariants") && {
|
||||
data: limits,
|
||||
key: "productVariants",
|
||||
text: "SKUs used"
|
||||
}
|
||||
limitText={
|
||||
hasLimits(limits, "productVariants") &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count}/{max} SKUs used",
|
||||
description: "created products counter"
|
||||
},
|
||||
{
|
||||
count: limits.currentUsage.productVariants,
|
||||
max: limits.allowedUsage.productVariants
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<CardMenu
|
||||
|
|
|
@ -64,12 +64,18 @@ const StaffListPage: React.FC<StaffListPageProps> = ({
|
|||
</Backlink>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(sectionNames.staff)}
|
||||
limit={
|
||||
hasLimits(limits, "staffUsers") && {
|
||||
data: limits,
|
||||
key: "staffUsers",
|
||||
text: "members"
|
||||
}
|
||||
limitText={
|
||||
hasLimits(limits, "staffUsers") &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count}/{max} members",
|
||||
description: "used staff users counter"
|
||||
},
|
||||
{
|
||||
count: limits.currentUsage.staffUsers,
|
||||
max: limits.allowedUsage.staffUsers
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<Button
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,8 @@ import React from "react";
|
|||
|
||||
import {
|
||||
filterPageProps,
|
||||
limits,
|
||||
limitsReached,
|
||||
listActionsProps,
|
||||
pageListProps,
|
||||
searchPageProps,
|
||||
|
@ -36,6 +38,7 @@ const props: OrderDraftListPageProps = {
|
|||
value: undefined
|
||||
}
|
||||
},
|
||||
limits,
|
||||
onAdd: () => undefined,
|
||||
orders,
|
||||
sort: {
|
||||
|
@ -50,4 +53,7 @@ storiesOf("Views / Orders / Draft order list", module)
|
|||
.add("loading", () => (
|
||||
<OrderDraftListPage {...props} disabled orders={undefined} />
|
||||
))
|
||||
.add("when no data", () => <OrderDraftListPage {...props} orders={[]} />);
|
||||
.add("when no data", () => <OrderDraftListPage {...props} orders={[]} />)
|
||||
.add("limits reached", () => (
|
||||
<OrderDraftListPage {...props} limits={limitsReached} />
|
||||
));
|
||||
|
|
|
@ -65,12 +65,18 @@ export const WarehouseListPage: React.FC<WarehouseListPageProps> = ({
|
|||
</Backlink>
|
||||
<PageHeader
|
||||
title={intl.formatMessage(sectionNames.warehouses)}
|
||||
limit={
|
||||
hasLimits(limits, "warehouses") && {
|
||||
data: limits,
|
||||
key: "warehouses",
|
||||
text: "warehouses used"
|
||||
}
|
||||
limitText={
|
||||
hasLimits(limits, "warehouses") &&
|
||||
intl.formatMessage(
|
||||
{
|
||||
defaultMessage: "{count}/{max} warehouses used",
|
||||
description: "used warehouses counter"
|
||||
},
|
||||
{
|
||||
count: limits.currentUsage.warehouses,
|
||||
max: limits.allowedUsage.warehouses
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<Button
|
||||
|
|
Loading…
Reference in a new issue