Excluded Products in shipping view (#866)
* Clean up stories * Add missing props * Add zip codes section (#861) * Add zip code listing * Add list wrapping * Update snapshots * Set up API data * Fix lgtm warning * Update snapshots * Run Actions on all PR * Checks on PR * Test envs on PR * Cleanup action on PR * Update messages Co-authored-by: Krzysztof Wolski <krzysztof.k.wolski@gmail.com> * Allow zip codes to be assigned to shipping method * Add zip code deletion (#871) * Add zip code range dialog * Fix path management * Use query params to handle modal actions * Allow zip codes to be assigned to shipping method * Make params optional * Fix types * Clean up urls * Add zip code range delete action * Update snapshots and messages * Update schema * Refresh zip code list after assigning them * Update types and snapshots * Update snapshots * Fix error message, checkbox default value (#880) * Fix error message, checkbox default value * Update snapshots * Update schema and types * Update stories * add excluded products section in shipping methods views * create UnassignDialog component * use priceRangeFragment in shipping queries * remove unneeded price from ShippingMethodAddProductsDialog * update messages in ShippingMethodProducts * updates after rebase * update snapshots, fix lint errors * fix ShippingMethodProductsAddDialog * update snapshots * small fix in ShippingMethodProducts * update snapshots after rebase * add handleClose func in ShippingMethodProductsAddDialog * Fix metadata not showing in category update * update snapshots again * update ShippingMethodProductsAddDialog * updates after rebase * update Price and Weight rates views Co-authored-by: dominik-zeglen <flesz3@o2.pl> Co-authored-by: Krzysztof Wolski <krzysztof.k.wolski@gmail.com> Co-authored-by: Tomasz Szymański <lime129@gmail.com> Co-authored-by: Magdalena Markusik <magdalena.markusik@mirumee.com>
This commit is contained in:
parent
f97ddd0128
commit
b774cc9002
32 changed files with 6931 additions and 848 deletions
|
@ -5349,6 +5349,33 @@
|
||||||
"context": "column title",
|
"context": "column title",
|
||||||
"string": "Channel name"
|
"string": "Channel name"
|
||||||
},
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProductsAddDialog_dot_2850255786": {
|
||||||
|
"string": "Search Products"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProductsAddDialog_dot_353369701": {
|
||||||
|
"string": "No products matching given query"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProductsAddDialog_dot_3756118423": {
|
||||||
|
"context": "dialog header",
|
||||||
|
"string": "Assign Products"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_1737533260": {
|
||||||
|
"string": "No Products"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_1781179817": {
|
||||||
|
"context": "section header",
|
||||||
|
"string": "Excluded Products"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_2100305525": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "Assign products"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_2697405188": {
|
||||||
|
"string": "Product Name"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_4190792473": {
|
||||||
|
"string": "Actions"
|
||||||
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingRateZipCodeRangeRemoveDialog_dot_1083561409": {
|
"src_dot_shipping_dot_components_dot_ShippingRateZipCodeRangeRemoveDialog_dot_1083561409": {
|
||||||
"string": "Are you sure you want to remove this ZIP-code rule?"
|
"string": "Are you sure you want to remove this ZIP-code rule?"
|
||||||
},
|
},
|
||||||
|
@ -5427,17 +5454,20 @@
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_579967655": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_579967655": {
|
||||||
"string": "Shipping rate name"
|
"string": "Shipping rate name"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneRatesPage_dot_1161979494": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneRatesCreatePage_dot_1161979494": {
|
||||||
"context": "page title",
|
"context": "page title",
|
||||||
"string": "Price Rate Create"
|
"string": "Price Rate Create"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneRatesPage_dot_1325966144": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneRatesCreatePage_dot_1325966144": {
|
||||||
"string": "Shipping"
|
"string": "Shipping"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneRatesPage_dot_3538551526": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneRatesCreatePage_dot_3538551526": {
|
||||||
"context": "page title",
|
"context": "page title",
|
||||||
"string": "Weight Rate Create"
|
"string": "Weight Rate Create"
|
||||||
},
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingZoneRatesPage_dot_1325966144": {
|
||||||
|
"string": "Shipping"
|
||||||
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_1134347598": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneRates_dot_1134347598": {
|
||||||
"context": "shipping method price",
|
"context": "shipping method price",
|
||||||
"string": "Price"
|
"string": "Price"
|
||||||
|
@ -5554,6 +5584,14 @@
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZonesList_dot_655374584": {
|
"src_dot_shipping_dot_components_dot_ShippingZonesList_dot_655374584": {
|
||||||
"string": "No shipping zones found"
|
"string": "No shipping zones found"
|
||||||
},
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_UnassignDialog_dot_1203193503": {
|
||||||
|
"context": "dialog header",
|
||||||
|
"string": "Unassign Products From Shipping"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_UnassignDialog_dot_3215481647": {
|
||||||
|
"context": "dialog content",
|
||||||
|
"string": "{counter,plural,one{Are you sure you want to unassign this product?} other{Are you sure you want to unassign {displayQuantity} products?}}"
|
||||||
|
},
|
||||||
"src_dot_shipping_dot_invalid": {
|
"src_dot_shipping_dot_invalid": {
|
||||||
"context": "error message",
|
"context": "error message",
|
||||||
"string": "Value is invalid"
|
"string": "Value is invalid"
|
||||||
|
@ -5587,6 +5625,10 @@
|
||||||
"src_dot_shipping_dot_views_dot_PriceRatesUpdate_dot_3823295269": {
|
"src_dot_shipping_dot_views_dot_PriceRatesUpdate_dot_3823295269": {
|
||||||
"string": "Manage Channel Availability"
|
"string": "Manage Channel Availability"
|
||||||
},
|
},
|
||||||
|
"src_dot_shipping_dot_views_dot_PriceRatesUpdate_dot_870815507": {
|
||||||
|
"context": "unassign products from shipping method, button",
|
||||||
|
"string": "Unassign"
|
||||||
|
},
|
||||||
"src_dot_shipping_dot_views_dot_ShippingZoneDetails_dot_1010705153": {
|
"src_dot_shipping_dot_views_dot_ShippingZoneDetails_dot_1010705153": {
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Delete Shipping Zone"
|
"string": "Delete Shipping Zone"
|
||||||
|
@ -5609,6 +5651,10 @@
|
||||||
"src_dot_shipping_dot_views_dot_WeightRatesUpdate_dot_3014453080": {
|
"src_dot_shipping_dot_views_dot_WeightRatesUpdate_dot_3014453080": {
|
||||||
"string": "Manage Channels Availability"
|
"string": "Manage Channels Availability"
|
||||||
},
|
},
|
||||||
|
"src_dot_shipping_dot_views_dot_WeightRatesUpdate_dot_870815507": {
|
||||||
|
"context": "unassign products from shipping method, button",
|
||||||
|
"string": "Unassign"
|
||||||
|
},
|
||||||
"src_dot_shipping_dot_weight": {
|
"src_dot_shipping_dot_weight": {
|
||||||
"context": "error message",
|
"context": "error message",
|
||||||
"string": "Maximum weight cannot be lower than minimum"
|
"string": "Maximum weight cannot be lower than minimum"
|
||||||
|
|
|
@ -75,9 +75,9 @@ function useCategoryUpdateForm(
|
||||||
// Need to make it function to always have description.current up to date
|
// Need to make it function to always have description.current up to date
|
||||||
const getData = (): CategoryUpdateData => ({
|
const getData = (): CategoryUpdateData => ({
|
||||||
...form.data,
|
...form.data,
|
||||||
...getMetadata(form.data, isMetadataModified, isPrivateMetadataModified),
|
|
||||||
description: description.current
|
description: description.current
|
||||||
});
|
});
|
||||||
|
|
||||||
const getSubmitData = (): CategoryUpdateData => ({
|
const getSubmitData = (): CategoryUpdateData => ({
|
||||||
...getData(),
|
...getData(),
|
||||||
...getMetadata(form.data, isMetadataModified, isPrivateMetadataModified)
|
...getMetadata(form.data, isMetadataModified, isPrivateMetadataModified)
|
||||||
|
|
|
@ -56,6 +56,36 @@ export const shippingMethodFragment = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
export const shippingMethodWithExcludedProductsFragment = gql`
|
||||||
|
${fragmentMoney}
|
||||||
|
${shippingMethodFragment}
|
||||||
|
fragment ShippingMethodWithExcludedProductsFragment on ShippingMethod {
|
||||||
|
...ShippingMethodFragment
|
||||||
|
excludedProducts(
|
||||||
|
before: $before
|
||||||
|
after: $after
|
||||||
|
first: $first
|
||||||
|
last: $last
|
||||||
|
) {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
hasPreviousPage
|
||||||
|
endCursor
|
||||||
|
startCursor
|
||||||
|
}
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
thumbnail {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const shippingZoneDetailsFragment = gql`
|
export const shippingZoneDetailsFragment = gql`
|
||||||
${shippingZoneFragment}
|
${shippingZoneFragment}
|
||||||
${shippingMethodFragment}
|
${shippingMethodFragment}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: ShippingMethodWithExcludedProductsFragment
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_zipCodeRules {
|
||||||
|
__typename: "ShippingMethodZipCodeRule";
|
||||||
|
id: string;
|
||||||
|
start: string | null;
|
||||||
|
end: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_minimumOrderWeight {
|
||||||
|
__typename: "Weight";
|
||||||
|
unit: WeightUnitsEnum;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_maximumOrderWeight {
|
||||||
|
__typename: "Weight";
|
||||||
|
unit: WeightUnitsEnum;
|
||||||
|
value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_channelListings_channel {
|
||||||
|
__typename: "Channel";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
currencyCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_channelListings_price {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_channelListings_minimumOrderPrice {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_channelListings_maximumOrderPrice {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_channelListings {
|
||||||
|
__typename: "ShippingMethodChannelListing";
|
||||||
|
id: string;
|
||||||
|
channel: ShippingMethodWithExcludedProductsFragment_channelListings_channel;
|
||||||
|
price: ShippingMethodWithExcludedProductsFragment_channelListings_price | null;
|
||||||
|
minimumOrderPrice: ShippingMethodWithExcludedProductsFragment_channelListings_minimumOrderPrice | null;
|
||||||
|
maximumOrderPrice: ShippingMethodWithExcludedProductsFragment_channelListings_maximumOrderPrice | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_excludedProducts_pageInfo {
|
||||||
|
__typename: "PageInfo";
|
||||||
|
hasNextPage: boolean;
|
||||||
|
hasPreviousPage: boolean;
|
||||||
|
endCursor: string | null;
|
||||||
|
startCursor: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_excludedProducts_edges_node_thumbnail {
|
||||||
|
__typename: "Image";
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_excludedProducts_edges_node {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
thumbnail: ShippingMethodWithExcludedProductsFragment_excludedProducts_edges_node_thumbnail | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_excludedProducts_edges {
|
||||||
|
__typename: "ProductCountableEdge";
|
||||||
|
node: ShippingMethodWithExcludedProductsFragment_excludedProducts_edges_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment_excludedProducts {
|
||||||
|
__typename: "ProductCountableConnection";
|
||||||
|
pageInfo: ShippingMethodWithExcludedProductsFragment_excludedProducts_pageInfo;
|
||||||
|
edges: ShippingMethodWithExcludedProductsFragment_excludedProducts_edges[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingMethodWithExcludedProductsFragment {
|
||||||
|
__typename: "ShippingMethod";
|
||||||
|
id: string;
|
||||||
|
zipCodeRules: (ShippingMethodWithExcludedProductsFragment_zipCodeRules | null)[] | null;
|
||||||
|
minimumOrderWeight: ShippingMethodWithExcludedProductsFragment_minimumOrderWeight | null;
|
||||||
|
maximumOrderWeight: ShippingMethodWithExcludedProductsFragment_maximumOrderWeight | null;
|
||||||
|
name: string;
|
||||||
|
type: ShippingMethodTypeEnum | null;
|
||||||
|
channelListings: ShippingMethodWithExcludedProductsFragment_channelListings[] | null;
|
||||||
|
excludedProducts: ShippingMethodWithExcludedProductsFragment_excludedProducts | null;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { shippingZone } from "@saleor/shipping/fixtures";
|
||||||
|
import Decorator from "@saleor/storybook//Decorator";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import ShippingMethodProducts, {
|
||||||
|
ShippingMethodProductsProps
|
||||||
|
} from "./ShippingMethodProducts";
|
||||||
|
|
||||||
|
const products = shippingZone.shippingMethods[0].excludedProducts.edges.map(
|
||||||
|
edge => edge.node
|
||||||
|
);
|
||||||
|
|
||||||
|
const props: ShippingMethodProductsProps = {
|
||||||
|
disabled: false,
|
||||||
|
isChecked: () => undefined,
|
||||||
|
onNextPage: () => undefined,
|
||||||
|
onPreviousPage: () => undefined,
|
||||||
|
onProductAssign: () => undefined,
|
||||||
|
onProductUnassign: () => undefined,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false
|
||||||
|
},
|
||||||
|
products,
|
||||||
|
selected: products.length,
|
||||||
|
toggle: () => undefined,
|
||||||
|
toggleAll: () => undefined,
|
||||||
|
toolbar: () => undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Shipping / ShippingMethodProducts", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("default", () => <ShippingMethodProducts {...props} />);
|
|
@ -0,0 +1,171 @@
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
|
import Card from "@material-ui/core/Card";
|
||||||
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import TableBody from "@material-ui/core/TableBody";
|
||||||
|
import TableCell from "@material-ui/core/TableCell";
|
||||||
|
import TableFooter from "@material-ui/core/TableFooter";
|
||||||
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
|
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 TableCellAvatar from "@saleor/components/TableCellAvatar";
|
||||||
|
import TableHead from "@saleor/components/TableHead";
|
||||||
|
import TablePagination from "@saleor/components/TablePagination";
|
||||||
|
import { renderCollection } from "@saleor/misc";
|
||||||
|
import { ShippingZone_shippingZone_shippingMethods_excludedProducts_edges_node } from "@saleor/shipping/types/ShippingZone";
|
||||||
|
import { ListActions, ListProps } from "@saleor/types";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
colAction: {
|
||||||
|
"&:last-child": {
|
||||||
|
paddingRight: theme.spacing(3)
|
||||||
|
},
|
||||||
|
textAlign: "right",
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
colName: {
|
||||||
|
width: "auto"
|
||||||
|
},
|
||||||
|
colProductName: {
|
||||||
|
paddingLeft: 0
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
tableLayout: "fixed"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "ShippingMethodProducts" }
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface ShippingMethodProductsProps
|
||||||
|
extends Pick<ListProps, Exclude<keyof ListProps, "onRowClick">>,
|
||||||
|
ListActions {
|
||||||
|
products: ShippingZone_shippingZone_shippingMethods_excludedProducts_edges_node[];
|
||||||
|
onProductAssign: () => void;
|
||||||
|
onProductUnassign: (ids: string[]) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberOfColumns = 3;
|
||||||
|
|
||||||
|
const ShippingMethodProducts: React.FC<ShippingMethodProductsProps> = props => {
|
||||||
|
const {
|
||||||
|
disabled,
|
||||||
|
pageInfo,
|
||||||
|
products,
|
||||||
|
onNextPage,
|
||||||
|
onPreviousPage,
|
||||||
|
onProductAssign,
|
||||||
|
onProductUnassign,
|
||||||
|
isChecked,
|
||||||
|
selected,
|
||||||
|
toggle,
|
||||||
|
toggleAll,
|
||||||
|
toolbar
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const classes = useStyles(props);
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Excluded Products",
|
||||||
|
description: "section header"
|
||||||
|
})}
|
||||||
|
toolbar={
|
||||||
|
<Button color="primary" variant="text" onClick={onProductAssign}>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Assign products"
|
||||||
|
description="button"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ResponsiveTable className={classes.table}>
|
||||||
|
{!!products?.length && (
|
||||||
|
<>
|
||||||
|
<TableHead
|
||||||
|
colSpan={numberOfColumns}
|
||||||
|
selected={selected}
|
||||||
|
disabled={disabled}
|
||||||
|
items={products}
|
||||||
|
toggleAll={toggleAll}
|
||||||
|
toolbar={toolbar}
|
||||||
|
>
|
||||||
|
<TableCell className={classes.colProductName}>
|
||||||
|
<FormattedMessage defaultMessage="Product Name" />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className={classes.colAction}>
|
||||||
|
<FormattedMessage defaultMessage="Actions" />
|
||||||
|
</TableCell>
|
||||||
|
</TableHead>
|
||||||
|
<TableFooter>
|
||||||
|
<TableRow>
|
||||||
|
<TablePagination
|
||||||
|
colSpan={numberOfColumns}
|
||||||
|
hasNextPage={
|
||||||
|
pageInfo && !disabled ? pageInfo.hasNextPage : false
|
||||||
|
}
|
||||||
|
onNextPage={onNextPage}
|
||||||
|
hasPreviousPage={
|
||||||
|
pageInfo && !disabled ? pageInfo.hasPreviousPage : false
|
||||||
|
}
|
||||||
|
onPreviousPage={onPreviousPage}
|
||||||
|
/>
|
||||||
|
</TableRow>
|
||||||
|
</TableFooter>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<TableBody>
|
||||||
|
{products?.length === 0 ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={5}>
|
||||||
|
<FormattedMessage defaultMessage="No Products" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
renderCollection(products, product => {
|
||||||
|
const isSelected = product ? isChecked(product.id) : false;
|
||||||
|
return (
|
||||||
|
<TableRow key={product ? product.id : "skeleton"}>
|
||||||
|
<TableCell padding="checkbox">
|
||||||
|
<Checkbox
|
||||||
|
checked={isSelected}
|
||||||
|
disabled={disabled}
|
||||||
|
disableClickPropagation
|
||||||
|
onChange={() => toggle(product.id)}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
<TableCellAvatar
|
||||||
|
className={classes.colName}
|
||||||
|
thumbnail={product?.thumbnail?.url}
|
||||||
|
>
|
||||||
|
{product?.name ? (
|
||||||
|
<Typography variant="body2">{product.name}</Typography>
|
||||||
|
) : (
|
||||||
|
<Skeleton />
|
||||||
|
)}
|
||||||
|
</TableCellAvatar>
|
||||||
|
<TableCell className={classes.colAction}>
|
||||||
|
<IconButton onClick={() => onProductUnassign([product.id])}>
|
||||||
|
<DeleteIcon color="primary" />
|
||||||
|
</IconButton>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</ResponsiveTable>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
ShippingMethodProducts.displayName = "ShippingMethodProducts";
|
||||||
|
export default ShippingMethodProducts;
|
2
src/shipping/components/ShippingMethodProducts/index.ts
Normal file
2
src/shipping/components/ShippingMethodProducts/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./ShippingMethodProducts";
|
||||||
|
export { default } from "./ShippingMethodProducts";
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { products } from "@saleor/shipping/fixtures";
|
||||||
|
import Decorator from "@saleor/storybook//Decorator";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import ShippingMethodProductsAddDialog, {
|
||||||
|
ShippingMethodProductsAddDialogProps
|
||||||
|
} from "./ShippingMethodProductsAddDialog";
|
||||||
|
|
||||||
|
const props: ShippingMethodProductsAddDialogProps = {
|
||||||
|
confirmButtonState: "default",
|
||||||
|
hasMore: false,
|
||||||
|
loading: false,
|
||||||
|
onClose: () => undefined,
|
||||||
|
onFetch: () => undefined,
|
||||||
|
onFetchMore: () => undefined,
|
||||||
|
onSubmit: () => undefined,
|
||||||
|
open: true,
|
||||||
|
products
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Shipping / ShippingMethodProductsAddDialog", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("default", () => <ShippingMethodProductsAddDialog {...props} />);
|
|
@ -0,0 +1,242 @@
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
|
import CircularProgress from "@material-ui/core/CircularProgress";
|
||||||
|
import Dialog from "@material-ui/core/Dialog";
|
||||||
|
import DialogActions from "@material-ui/core/DialogActions";
|
||||||
|
import DialogContent from "@material-ui/core/DialogContent";
|
||||||
|
import DialogTitle from "@material-ui/core/DialogTitle";
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import TableBody from "@material-ui/core/TableBody";
|
||||||
|
import TableCell from "@material-ui/core/TableCell";
|
||||||
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
|
import TextField from "@material-ui/core/TextField";
|
||||||
|
import Checkbox from "@saleor/components/Checkbox";
|
||||||
|
import ConfirmButton, {
|
||||||
|
ConfirmButtonTransitionState
|
||||||
|
} from "@saleor/components/ConfirmButton";
|
||||||
|
import ResponsiveTable from "@saleor/components/ResponsiveTable";
|
||||||
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
|
import TableCellAvatar from "@saleor/components/TableCellAvatar";
|
||||||
|
import useSearchQuery from "@saleor/hooks/useSearchQuery";
|
||||||
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { renderCollection } from "@saleor/misc";
|
||||||
|
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
|
||||||
|
import { ShippingPriceExcludeProduct } from "@saleor/shipping/types/ShippingPriceExcludeProduct";
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
|
import React from "react";
|
||||||
|
import { MutationFetchResult } from "react-apollo";
|
||||||
|
import InfiniteScroll from "react-infinite-scroller";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
avatar: {
|
||||||
|
paddingLeft: 0,
|
||||||
|
width: 64
|
||||||
|
},
|
||||||
|
colName: {
|
||||||
|
paddingLeft: 0
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
overflowY: "scroll"
|
||||||
|
},
|
||||||
|
loadMoreLoaderContainer: {
|
||||||
|
alignItems: "center",
|
||||||
|
display: "flex",
|
||||||
|
height: theme.spacing(3),
|
||||||
|
justifyContent: "center",
|
||||||
|
marginTop: theme.spacing(3)
|
||||||
|
},
|
||||||
|
overflow: {
|
||||||
|
overflowY: "visible"
|
||||||
|
},
|
||||||
|
productCheckboxCell: {
|
||||||
|
"&:first-child": {
|
||||||
|
paddingLeft: 0,
|
||||||
|
paddingRight: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "ShippingMethodProductsAddDialog" }
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface ShippingMethodProductsAddDialogProps extends FetchMoreProps {
|
||||||
|
confirmButtonState: ConfirmButtonTransitionState;
|
||||||
|
open: boolean;
|
||||||
|
products: SearchProducts_search_edges_node[];
|
||||||
|
onClose: () => void;
|
||||||
|
onFetch: (query: string) => void;
|
||||||
|
onSubmit: (
|
||||||
|
ids: string[]
|
||||||
|
) => Promise<MutationFetchResult<ShippingPriceExcludeProduct>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleProductAssign = (
|
||||||
|
product: SearchProducts_search_edges_node,
|
||||||
|
isSelected: boolean,
|
||||||
|
selectedProducts: SearchProducts_search_edges_node[],
|
||||||
|
setSelectedProducts: (data: SearchProducts_search_edges_node[]) => void
|
||||||
|
) => {
|
||||||
|
if (isSelected) {
|
||||||
|
setSelectedProducts(
|
||||||
|
selectedProducts.filter(
|
||||||
|
selectedProduct => selectedProduct.id !== product.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setSelectedProducts([...selectedProducts, product]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ShippingMethodProductsAddDialog: React.FC<ShippingMethodProductsAddDialogProps> = props => {
|
||||||
|
const {
|
||||||
|
confirmButtonState,
|
||||||
|
open,
|
||||||
|
loading,
|
||||||
|
hasMore,
|
||||||
|
products,
|
||||||
|
onFetch,
|
||||||
|
onFetchMore,
|
||||||
|
onClose,
|
||||||
|
onSubmit
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const classes = useStyles(props);
|
||||||
|
const intl = useIntl();
|
||||||
|
const [query, onQueryChange, resetQuery] = useSearchQuery(onFetch);
|
||||||
|
const [selectedProducts, setSelectedProducts] = React.useState<
|
||||||
|
SearchProducts_search_edges_node[]
|
||||||
|
>([]);
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
onSubmit(selectedProducts.map(product => product.id)).then(() => {
|
||||||
|
setSelectedProducts([]);
|
||||||
|
resetQuery();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
onClose();
|
||||||
|
setSelectedProducts([]);
|
||||||
|
resetQuery();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
onClose={handleClose}
|
||||||
|
open={open}
|
||||||
|
classes={{ paper: classes.overflow }}
|
||||||
|
fullWidth
|
||||||
|
maxWidth="sm"
|
||||||
|
>
|
||||||
|
<DialogTitle>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Assign Products"
|
||||||
|
description="dialog header"
|
||||||
|
/>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent className={classes.overflow}>
|
||||||
|
<TextField
|
||||||
|
name="query"
|
||||||
|
value={query}
|
||||||
|
onChange={onQueryChange}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
defaultMessage: "Search Products"
|
||||||
|
})}
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
defaultMessage: "Search Products"
|
||||||
|
})}
|
||||||
|
fullWidth
|
||||||
|
InputProps={{
|
||||||
|
autoComplete: "off",
|
||||||
|
endAdornment: loading && <CircularProgress size={16} />
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogContent className={classes.content}>
|
||||||
|
<InfiniteScroll
|
||||||
|
pageStart={0}
|
||||||
|
loadMore={onFetchMore}
|
||||||
|
hasMore={hasMore}
|
||||||
|
useWindow={false}
|
||||||
|
loader={
|
||||||
|
<div key="loader" className={classes.loadMoreLoaderContainer}>
|
||||||
|
<CircularProgress size={16} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
threshold={10}
|
||||||
|
>
|
||||||
|
<ResponsiveTable key="table">
|
||||||
|
<TableBody>
|
||||||
|
{renderCollection(
|
||||||
|
products,
|
||||||
|
(product, productIndex) => {
|
||||||
|
const isSelected = selectedProducts.some(
|
||||||
|
selectedProduct => selectedProduct.id === product.id
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<React.Fragment
|
||||||
|
key={product ? product.id : `skeleton-${productIndex}`}
|
||||||
|
>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
padding="checkbox"
|
||||||
|
className={classes.productCheckboxCell}
|
||||||
|
>
|
||||||
|
{product && (
|
||||||
|
<Checkbox
|
||||||
|
checked={isSelected}
|
||||||
|
disabled={loading}
|
||||||
|
onChange={() =>
|
||||||
|
handleProductAssign(
|
||||||
|
product,
|
||||||
|
isSelected,
|
||||||
|
selectedProducts,
|
||||||
|
setSelectedProducts
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
<TableCellAvatar
|
||||||
|
className={classes.avatar}
|
||||||
|
thumbnail={product?.thumbnail?.url}
|
||||||
|
/>
|
||||||
|
<TableCell className={classes.colName} colSpan={2}>
|
||||||
|
{product?.name || <Skeleton />}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={4}>
|
||||||
|
<FormattedMessage defaultMessage="No products matching given query" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</ResponsiveTable>
|
||||||
|
</InfiniteScroll>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleClose}>
|
||||||
|
<FormattedMessage {...buttonMessages.back} />
|
||||||
|
</Button>
|
||||||
|
<ConfirmButton
|
||||||
|
transitionState={confirmButtonState}
|
||||||
|
color="primary"
|
||||||
|
variant="contained"
|
||||||
|
type="submit"
|
||||||
|
disabled={loading || !selectedProducts?.length}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
<FormattedMessage {...buttonMessages.confirm} />
|
||||||
|
</ConfirmButton>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
ShippingMethodProductsAddDialog.displayName = "ShippingMethodProductsAddDialog";
|
||||||
|
export default ShippingMethodProductsAddDialog;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./ShippingMethodProductsAddDialog";
|
||||||
|
export { default } from "./ShippingMethodProductsAddDialog";
|
|
@ -0,0 +1,87 @@
|
||||||
|
import Decorator from "@saleor/storybook//Decorator";
|
||||||
|
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import ShippingZoneRatesCreatePage, {
|
||||||
|
ShippingZoneRatesCreatePageProps
|
||||||
|
} from "./ShippingZoneRatesCreatePage";
|
||||||
|
|
||||||
|
const channels = [
|
||||||
|
{
|
||||||
|
currency: "USD",
|
||||||
|
id: "1",
|
||||||
|
maxValue: "10",
|
||||||
|
minValue: "0",
|
||||||
|
name: "channel",
|
||||||
|
price: "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
currency: "USD",
|
||||||
|
id: "2",
|
||||||
|
maxValue: "20",
|
||||||
|
minValue: "1",
|
||||||
|
name: "test",
|
||||||
|
price: "6"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const defaultChannels = [
|
||||||
|
{
|
||||||
|
currency: "USD",
|
||||||
|
id: "1",
|
||||||
|
maxValue: "",
|
||||||
|
minValue: "",
|
||||||
|
name: "channel",
|
||||||
|
price: ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const props: ShippingZoneRatesCreatePageProps = {
|
||||||
|
allChannelsCount: 3,
|
||||||
|
channelErrors: [],
|
||||||
|
disabled: false,
|
||||||
|
errors: [],
|
||||||
|
onBack: () => undefined,
|
||||||
|
onChannelsChange: () => undefined,
|
||||||
|
onDelete: () => undefined,
|
||||||
|
onSubmit: () => undefined,
|
||||||
|
onZipCodeAssign: () => undefined,
|
||||||
|
onZipCodeUnassign: () => undefined,
|
||||||
|
openChannelsModal: () => undefined,
|
||||||
|
saveButtonBarState: "default",
|
||||||
|
shippingChannels: defaultChannels,
|
||||||
|
variant: ShippingMethodTypeEnum.PRICE,
|
||||||
|
zipCodes: [
|
||||||
|
{
|
||||||
|
__typename: "ShippingMethodZipCodeRule",
|
||||||
|
end: "51-200",
|
||||||
|
id: "1",
|
||||||
|
start: "51-220"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "ShippingMethodZipCodeRule",
|
||||||
|
end: "31-101",
|
||||||
|
id: "1",
|
||||||
|
start: "44-205"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Shipping / ShippingZoneRatesCreatePage page", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("create price", () => <ShippingZoneRatesCreatePage {...props} />)
|
||||||
|
.add("loading", () => (
|
||||||
|
<ShippingZoneRatesCreatePage
|
||||||
|
{...props}
|
||||||
|
disabled={true}
|
||||||
|
saveButtonBarState={"loading"}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
.add("create weight", () => (
|
||||||
|
<ShippingZoneRatesCreatePage
|
||||||
|
{...props}
|
||||||
|
shippingChannels={channels}
|
||||||
|
variant={ShippingMethodTypeEnum.WEIGHT}
|
||||||
|
/>
|
||||||
|
));
|
|
@ -0,0 +1,190 @@
|
||||||
|
import { ChannelShippingData } from "@saleor/channels/utils";
|
||||||
|
import AppHeader from "@saleor/components/AppHeader";
|
||||||
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
|
import ChannelsAvailability from "@saleor/components/ChannelsAvailability";
|
||||||
|
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||||
|
import Container from "@saleor/components/Container";
|
||||||
|
import Form from "@saleor/components/Form";
|
||||||
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
|
import { ShippingChannelsErrorFragment } from "@saleor/fragments/types/ShippingChannelsErrorFragment";
|
||||||
|
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
||||||
|
import { ShippingMethodFragment_zipCodeRules } from "@saleor/fragments/types/ShippingMethodFragment";
|
||||||
|
import { validatePrice } from "@saleor/products/utils/validation";
|
||||||
|
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||||
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||||
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||||
|
import ShippingZoneInfo from "@saleor/shipping/components/ShippingZoneInfo";
|
||||||
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||||
|
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import ShippingZoneZipCodes, {
|
||||||
|
ZipCodeInclusion
|
||||||
|
} from "../ShippingZoneZipCodes";
|
||||||
|
|
||||||
|
export interface FormData {
|
||||||
|
channelListings: ChannelShippingData[];
|
||||||
|
includeZipCodes: ZipCodeInclusion;
|
||||||
|
name: string;
|
||||||
|
noLimits: boolean;
|
||||||
|
minValue: string;
|
||||||
|
maxValue: string;
|
||||||
|
type: ShippingMethodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingZoneRatesCreatePageProps {
|
||||||
|
allChannelsCount?: number;
|
||||||
|
shippingChannels: ChannelShippingData[];
|
||||||
|
disabled: boolean;
|
||||||
|
hasChannelChanged?: boolean;
|
||||||
|
zipCodes?: ShippingMethodFragment_zipCodeRules[];
|
||||||
|
channelErrors: ShippingChannelsErrorFragment[];
|
||||||
|
errors: ShippingErrorFragment[];
|
||||||
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
|
onBack: () => void;
|
||||||
|
onDelete?: () => void;
|
||||||
|
onSubmit: (data: FormData) => void;
|
||||||
|
onZipCodeAssign: () => void;
|
||||||
|
onZipCodeUnassign: (id: string) => void;
|
||||||
|
onChannelsChange: (data: ChannelShippingData[]) => void;
|
||||||
|
openChannelsModal: () => void;
|
||||||
|
variant: ShippingMethodTypeEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePageProps> = ({
|
||||||
|
allChannelsCount,
|
||||||
|
shippingChannels,
|
||||||
|
channelErrors,
|
||||||
|
disabled,
|
||||||
|
errors,
|
||||||
|
hasChannelChanged,
|
||||||
|
onBack,
|
||||||
|
onDelete,
|
||||||
|
onSubmit,
|
||||||
|
onChannelsChange,
|
||||||
|
onZipCodeAssign,
|
||||||
|
onZipCodeUnassign,
|
||||||
|
openChannelsModal,
|
||||||
|
saveButtonBarState,
|
||||||
|
variant,
|
||||||
|
zipCodes
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const isPriceVariant = variant === ShippingMethodTypeEnum.PRICE;
|
||||||
|
const initialForm: FormData = {
|
||||||
|
channelListings: shippingChannels,
|
||||||
|
includeZipCodes: ZipCodeInclusion.Include,
|
||||||
|
maxValue: "",
|
||||||
|
minValue: "",
|
||||||
|
name: "",
|
||||||
|
noLimits: false,
|
||||||
|
type: null
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
|
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||||
|
const handleChannelsChange = createChannelsChangeHandler(
|
||||||
|
shippingChannels,
|
||||||
|
onChannelsChange,
|
||||||
|
triggerChange
|
||||||
|
);
|
||||||
|
const formDisabled = data.channelListings?.some(channel =>
|
||||||
|
validatePrice(channel.price)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<AppHeader onBack={onBack}>
|
||||||
|
<FormattedMessage defaultMessage="Shipping" />
|
||||||
|
</AppHeader>
|
||||||
|
<PageHeader
|
||||||
|
title={
|
||||||
|
isPriceVariant
|
||||||
|
? intl.formatMessage({
|
||||||
|
defaultMessage: "Price Rate Create",
|
||||||
|
description: "page title"
|
||||||
|
})
|
||||||
|
: intl.formatMessage({
|
||||||
|
defaultMessage: "Weight Rate Create",
|
||||||
|
description: "page title"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Grid>
|
||||||
|
<div>
|
||||||
|
<ShippingZoneInfo
|
||||||
|
data={data}
|
||||||
|
disabled={disabled}
|
||||||
|
errors={errors}
|
||||||
|
onChange={change}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
{isPriceVariant ? (
|
||||||
|
<OrderValue
|
||||||
|
channels={data.channelListings}
|
||||||
|
errors={channelErrors}
|
||||||
|
noLimits={data.noLimits}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={change}
|
||||||
|
onChannelsChange={handleChannelsChange}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<OrderWeight
|
||||||
|
noLimits={data.noLimits}
|
||||||
|
disabled={disabled}
|
||||||
|
minValue={data.minValue}
|
||||||
|
maxValue={data.maxValue}
|
||||||
|
onChange={change}
|
||||||
|
errors={errors}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<CardSpacer />
|
||||||
|
<PricingCard
|
||||||
|
channels={data.channelListings}
|
||||||
|
onChange={handleChannelsChange}
|
||||||
|
disabled={disabled}
|
||||||
|
errors={channelErrors}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<ShippingZoneZipCodes
|
||||||
|
data={data}
|
||||||
|
disabled={disabled}
|
||||||
|
onZipCodeDelete={onZipCodeUnassign}
|
||||||
|
onZipCodeInclusionChange={() => undefined}
|
||||||
|
onZipCodeRangeAdd={onZipCodeAssign}
|
||||||
|
zipCodes={zipCodes}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ChannelsAvailability
|
||||||
|
allChannelsCount={allChannelsCount}
|
||||||
|
selectedChannelsCount={shippingChannels?.length}
|
||||||
|
channelsList={data.channelListings.map(channel => ({
|
||||||
|
id: channel.id,
|
||||||
|
name: channel.name
|
||||||
|
}))}
|
||||||
|
openModal={openChannelsModal}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
<SaveButtonBar
|
||||||
|
disabled={
|
||||||
|
disabled || formDisabled || (!hasChanged && !hasChannelChanged)
|
||||||
|
}
|
||||||
|
onCancel={onBack}
|
||||||
|
onDelete={onDelete}
|
||||||
|
onSave={submit}
|
||||||
|
state={saveButtonBarState}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShippingZoneRatesCreatePage;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./ShippingZoneRatesCreatePage";
|
||||||
|
export { default } from "./ShippingZoneRatesCreatePage";
|
|
@ -43,31 +43,26 @@ const props: ShippingZoneRatesPageProps = {
|
||||||
channelErrors: [],
|
channelErrors: [],
|
||||||
disabled: false,
|
disabled: false,
|
||||||
errors: [],
|
errors: [],
|
||||||
|
isChecked: () => undefined,
|
||||||
onBack: () => undefined,
|
onBack: () => undefined,
|
||||||
onChannelsChange: () => undefined,
|
onChannelsChange: () => undefined,
|
||||||
onDelete: () => undefined,
|
onDelete: () => undefined,
|
||||||
|
onNextPage: () => undefined,
|
||||||
|
onPreviousPage: () => undefined,
|
||||||
|
onProductAssign: () => undefined,
|
||||||
|
onProductUnassign: () => undefined,
|
||||||
onSubmit: () => undefined,
|
onSubmit: () => undefined,
|
||||||
onZipCodeAssign: () => undefined,
|
onZipCodeAssign: () => undefined,
|
||||||
onZipCodeUnassign: () => undefined,
|
onZipCodeUnassign: () => undefined,
|
||||||
openChannelsModal: () => undefined,
|
openChannelsModal: () => undefined,
|
||||||
rate: null,
|
rate: shippingZone.shippingMethods[0],
|
||||||
saveButtonBarState: "default",
|
saveButtonBarState: "default",
|
||||||
|
selected: 0,
|
||||||
shippingChannels: defaultChannels,
|
shippingChannels: defaultChannels,
|
||||||
variant: ShippingMethodTypeEnum.PRICE,
|
toggle: () => undefined,
|
||||||
zipCodes: [
|
toggleAll: () => undefined,
|
||||||
{
|
toolbar: () => undefined,
|
||||||
__typename: "ShippingMethodZipCodeRule",
|
variant: ShippingMethodTypeEnum.PRICE
|
||||||
end: "51-200",
|
|
||||||
id: "1",
|
|
||||||
start: "51-220"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
__typename: "ShippingMethodZipCodeRule",
|
|
||||||
end: "31-101",
|
|
||||||
id: "1",
|
|
||||||
start: "44-205"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
storiesOf("Views / Shipping / Shipping rate", module)
|
storiesOf("Views / Shipping / Shipping rate", module)
|
||||||
|
@ -95,10 +90,6 @@ storiesOf("Views / Shipping / Shipping rate", module)
|
||||||
<ShippingZoneRatesPage
|
<ShippingZoneRatesPage
|
||||||
{...props}
|
{...props}
|
||||||
shippingChannels={channels}
|
shippingChannels={channels}
|
||||||
rate={shippingZone.shippingMethods[0]}
|
|
||||||
variant={ShippingMethodTypeEnum.WEIGHT}
|
variant={ShippingMethodTypeEnum.WEIGHT}
|
||||||
/>
|
/>
|
||||||
))
|
|
||||||
.add("no zip codes", () => (
|
|
||||||
<ShippingZoneRatesPage {...props} zipCodes={[]} />
|
|
||||||
));
|
));
|
||||||
|
|
|
@ -10,19 +10,18 @@ import PageHeader from "@saleor/components/PageHeader";
|
||||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
import { ShippingChannelsErrorFragment } from "@saleor/fragments/types/ShippingChannelsErrorFragment";
|
import { ShippingChannelsErrorFragment } from "@saleor/fragments/types/ShippingChannelsErrorFragment";
|
||||||
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
||||||
import {
|
|
||||||
ShippingMethodFragment,
|
|
||||||
ShippingMethodFragment_zipCodeRules
|
|
||||||
} from "@saleor/fragments/types/ShippingMethodFragment";
|
|
||||||
import { validatePrice } from "@saleor/products/utils/validation";
|
import { validatePrice } from "@saleor/products/utils/validation";
|
||||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||||
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||||
|
import ShippingMethodProducts from "@saleor/shipping/components/ShippingMethodProducts";
|
||||||
import ShippingZoneInfo from "@saleor/shipping/components/ShippingZoneInfo";
|
import ShippingZoneInfo from "@saleor/shipping/components/ShippingZoneInfo";
|
||||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||||
|
import { ShippingZone_shippingZone_shippingMethods } from "@saleor/shipping/types/ShippingZone";
|
||||||
|
import { ListActions, ListProps } from "@saleor/types";
|
||||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
import ShippingZoneZipCodes, {
|
import ShippingZoneZipCodes, {
|
||||||
ZipCodeInclusion
|
ZipCodeInclusion
|
||||||
|
@ -38,13 +37,14 @@ export interface FormData {
|
||||||
type: ShippingMethodTypeEnum;
|
type: ShippingMethodTypeEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShippingZoneRatesPageProps {
|
export interface ShippingZoneRatesPageProps
|
||||||
|
extends Pick<ListProps, Exclude<keyof ListProps, "onRowClick">>,
|
||||||
|
ListActions {
|
||||||
allChannelsCount?: number;
|
allChannelsCount?: number;
|
||||||
shippingChannels: ChannelShippingData[];
|
shippingChannels: ChannelShippingData[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
hasChannelChanged?: boolean;
|
hasChannelChanged?: boolean;
|
||||||
rate: ShippingMethodFragment | null;
|
rate: ShippingZone_shippingZone_shippingMethods;
|
||||||
zipCodes?: ShippingMethodFragment_zipCodeRules[];
|
|
||||||
channelErrors: ShippingChannelsErrorFragment[];
|
channelErrors: ShippingChannelsErrorFragment[];
|
||||||
errors: ShippingErrorFragment[];
|
errors: ShippingErrorFragment[];
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
|
@ -55,6 +55,8 @@ export interface ShippingZoneRatesPageProps {
|
||||||
onZipCodeUnassign: (id: string) => void;
|
onZipCodeUnassign: (id: string) => void;
|
||||||
onChannelsChange: (data: ChannelShippingData[]) => void;
|
onChannelsChange: (data: ChannelShippingData[]) => void;
|
||||||
openChannelsModal: () => void;
|
openChannelsModal: () => void;
|
||||||
|
onProductAssign: () => void;
|
||||||
|
onProductUnassign: (ids: string[]) => void;
|
||||||
variant: ShippingMethodTypeEnum;
|
variant: ShippingMethodTypeEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +73,14 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
onChannelsChange,
|
onChannelsChange,
|
||||||
onZipCodeAssign,
|
onZipCodeAssign,
|
||||||
onZipCodeUnassign,
|
onZipCodeUnassign,
|
||||||
|
onProductAssign,
|
||||||
|
onProductUnassign,
|
||||||
openChannelsModal,
|
openChannelsModal,
|
||||||
rate,
|
rate,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
variant,
|
variant,
|
||||||
zipCodes
|
...listProps
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
|
||||||
const isPriceVariant = variant === ShippingMethodTypeEnum.PRICE;
|
const isPriceVariant = variant === ShippingMethodTypeEnum.PRICE;
|
||||||
const initialForm: FormData = {
|
const initialForm: FormData = {
|
||||||
channelListings: shippingChannels,
|
channelListings: shippingChannels,
|
||||||
|
@ -89,8 +92,6 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
type: rate?.type || null
|
type: rate?.type || null
|
||||||
};
|
};
|
||||||
|
|
||||||
const rateExists = rate !== null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, hasChanged, submit, triggerChange }) => {
|
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||||
|
@ -108,20 +109,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
<FormattedMessage defaultMessage="Shipping" />
|
<FormattedMessage defaultMessage="Shipping" />
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
<PageHeader
|
<PageHeader title={rate?.name} />
|
||||||
title={
|
|
||||||
rate?.name ||
|
|
||||||
(isPriceVariant
|
|
||||||
? intl.formatMessage({
|
|
||||||
defaultMessage: "Price Rate Create",
|
|
||||||
description: "page title"
|
|
||||||
})
|
|
||||||
: intl.formatMessage({
|
|
||||||
defaultMessage: "Weight Rate Create",
|
|
||||||
description: "page title"
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<ShippingZoneInfo
|
<ShippingZoneInfo
|
||||||
|
@ -164,7 +152,17 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
onZipCodeDelete={onZipCodeUnassign}
|
onZipCodeDelete={onZipCodeUnassign}
|
||||||
onZipCodeInclusionChange={() => undefined}
|
onZipCodeInclusionChange={() => undefined}
|
||||||
onZipCodeRangeAdd={onZipCodeAssign}
|
onZipCodeRangeAdd={onZipCodeAssign}
|
||||||
zipCodes={rateExists ? rate?.zipCodeRules : zipCodes}
|
zipCodes={rate?.zipCodeRules}
|
||||||
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<ShippingMethodProducts
|
||||||
|
products={rate?.excludedProducts?.edges.map(
|
||||||
|
edge => edge.node
|
||||||
|
)}
|
||||||
|
onProductAssign={onProductAssign}
|
||||||
|
onProductUnassign={onProductUnassign}
|
||||||
|
disabled={disabled}
|
||||||
|
{...listProps}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import Decorator from "@saleor/storybook//Decorator";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import UnassignDialog, { UnassignDialogProps } from "./UnassignDialog";
|
||||||
|
|
||||||
|
const props: UnassignDialogProps = {
|
||||||
|
closeModal: () => undefined,
|
||||||
|
confirmButtonState: "default",
|
||||||
|
idsLength: 2,
|
||||||
|
onConfirm: () => undefined,
|
||||||
|
open: true
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Shipping / UnassignDialog", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("default", () => <UnassignDialog {...props} />);
|
48
src/shipping/components/UnassignDialog/UnassignDialog.tsx
Normal file
48
src/shipping/components/UnassignDialog/UnassignDialog.tsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import DialogContentText from "@material-ui/core/DialogContentText";
|
||||||
|
import ActionDialog from "@saleor/components/ActionDialog";
|
||||||
|
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
export interface UnassignDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
confirmButtonState: ConfirmButtonTransitionState;
|
||||||
|
idsLength: number;
|
||||||
|
closeModal: () => void;
|
||||||
|
onConfirm: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const UnassignDialog: React.FC<UnassignDialogProps> = ({
|
||||||
|
closeModal,
|
||||||
|
confirmButtonState,
|
||||||
|
idsLength,
|
||||||
|
onConfirm,
|
||||||
|
open
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
return (
|
||||||
|
<ActionDialog
|
||||||
|
open={open}
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Unassign Products From Shipping",
|
||||||
|
description: "dialog header"
|
||||||
|
})}
|
||||||
|
confirmButtonState={confirmButtonState}
|
||||||
|
onClose={closeModal}
|
||||||
|
onConfirm={onConfirm}
|
||||||
|
>
|
||||||
|
<DialogContentText>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="{counter,plural,one{Are you sure you want to unassign this product?} other{Are you sure you want to unassign {displayQuantity} products?}}"
|
||||||
|
description="dialog content"
|
||||||
|
values={{
|
||||||
|
counter: idsLength,
|
||||||
|
displayQuantity: <strong>{idsLength}</strong>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DialogContentText>
|
||||||
|
</ActionDialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UnassignDialog;
|
2
src/shipping/components/UnassignDialog/index.ts
Normal file
2
src/shipping/components/UnassignDialog/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./UnassignDialog";
|
||||||
|
export { default } from "./UnassignDialog";
|
|
@ -1,5 +1,6 @@
|
||||||
import { ShippingZoneDetailsFragment } from "@saleor/fragments/types/ShippingZoneDetailsFragment";
|
|
||||||
import { ShippingZoneFragment } from "@saleor/fragments/types/ShippingZoneFragment";
|
import { ShippingZoneFragment } from "@saleor/fragments/types/ShippingZoneFragment";
|
||||||
|
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
|
||||||
|
import { ShippingZone_shippingZone } from "@saleor/shipping/types/ShippingZone";
|
||||||
|
|
||||||
import { ShippingMethodTypeEnum, WeightUnitsEnum } from "../types/globalTypes";
|
import { ShippingMethodTypeEnum, WeightUnitsEnum } from "../types/globalTypes";
|
||||||
|
|
||||||
|
@ -1285,7 +1286,7 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const shippingZone: ShippingZoneDetailsFragment = {
|
export const shippingZone: ShippingZone_shippingZone = {
|
||||||
__typename: "ShippingZone",
|
__typename: "ShippingZone",
|
||||||
countries: [
|
countries: [
|
||||||
{
|
{
|
||||||
|
@ -1577,6 +1578,30 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
excludedProducts: {
|
||||||
|
__typename: "ProductCountableConnection",
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
__typename: "ProductCountableEdge",
|
||||||
|
node: {
|
||||||
|
__typename: "Product",
|
||||||
|
id: "1",
|
||||||
|
name: "Apple Juice",
|
||||||
|
thumbnail: {
|
||||||
|
__typename: "Image",
|
||||||
|
url: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pageInfo: {
|
||||||
|
__typename: "PageInfo",
|
||||||
|
endCursor: "",
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
id: "U2hpcHBpbmdNZXRob2Q6NA==",
|
id: "U2hpcHBpbmdNZXRob2Q6NA==",
|
||||||
maximumOrderWeight: {
|
maximumOrderWeight: {
|
||||||
__typename: "Weight",
|
__typename: "Weight",
|
||||||
|
@ -1614,6 +1639,30 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethod",
|
__typename: "ShippingMethod",
|
||||||
channelListings: [],
|
channelListings: [],
|
||||||
|
excludedProducts: {
|
||||||
|
__typename: "ProductCountableConnection",
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
__typename: "ProductCountableEdge",
|
||||||
|
node: {
|
||||||
|
__typename: "Product",
|
||||||
|
id: "1",
|
||||||
|
name: "Apple Juice",
|
||||||
|
thumbnail: {
|
||||||
|
__typename: "Image",
|
||||||
|
url: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pageInfo: {
|
||||||
|
__typename: "PageInfo",
|
||||||
|
endCursor: "",
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
id: "U2hpcHBpbmdNZXRob2Q6Mw==",
|
id: "U2hpcHBpbmdNZXRob2Q6Mw==",
|
||||||
maximumOrderWeight: null,
|
maximumOrderWeight: null,
|
||||||
minimumOrderWeight: {
|
minimumOrderWeight: {
|
||||||
|
@ -1647,6 +1696,30 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethod",
|
__typename: "ShippingMethod",
|
||||||
channelListings: [],
|
channelListings: [],
|
||||||
|
excludedProducts: {
|
||||||
|
__typename: "ProductCountableConnection",
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
__typename: "ProductCountableEdge",
|
||||||
|
node: {
|
||||||
|
__typename: "Product",
|
||||||
|
id: "1",
|
||||||
|
name: "Apple Juice",
|
||||||
|
thumbnail: {
|
||||||
|
__typename: "Image",
|
||||||
|
url: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pageInfo: {
|
||||||
|
__typename: "PageInfo",
|
||||||
|
endCursor: "",
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
id: "U2hpcHBpbmdNZXRob2Q6Mg==",
|
id: "U2hpcHBpbmdNZXRob2Q6Mg==",
|
||||||
maximumOrderWeight: null,
|
maximumOrderWeight: null,
|
||||||
minimumOrderWeight: {
|
minimumOrderWeight: {
|
||||||
|
@ -1680,6 +1753,17 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
||||||
{
|
{
|
||||||
__typename: "ShippingMethod",
|
__typename: "ShippingMethod",
|
||||||
channelListings: [],
|
channelListings: [],
|
||||||
|
excludedProducts: {
|
||||||
|
__typename: "ProductCountableConnection",
|
||||||
|
edges: [],
|
||||||
|
pageInfo: {
|
||||||
|
__typename: "PageInfo",
|
||||||
|
endCursor: "",
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
id: "U2hpcHBpbmdNZXRob2Q6MQ==",
|
id: "U2hpcHBpbmdNZXRob2Q6MQ==",
|
||||||
maximumOrderWeight: null,
|
maximumOrderWeight: null,
|
||||||
minimumOrderWeight: {
|
minimumOrderWeight: {
|
||||||
|
@ -1724,3 +1808,24 @@ export const shippingZone: ShippingZoneDetailsFragment = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const products: SearchProducts_search_edges_node[] = [
|
||||||
|
{
|
||||||
|
__typename: "Product",
|
||||||
|
id: "1",
|
||||||
|
name: "Apple Juice",
|
||||||
|
thumbnail: {
|
||||||
|
__typename: "Image",
|
||||||
|
url: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "Product",
|
||||||
|
id: "2",
|
||||||
|
name: "Banana Juice",
|
||||||
|
thumbnail: {
|
||||||
|
__typename: "Image",
|
||||||
|
url: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
|
@ -47,6 +47,14 @@ import {
|
||||||
ShippingMethodZipCodeRangeUnassign,
|
ShippingMethodZipCodeRangeUnassign,
|
||||||
ShippingMethodZipCodeRangeUnassignVariables
|
ShippingMethodZipCodeRangeUnassignVariables
|
||||||
} from "./types/ShippingMethodZipCodeRangeUnassign";
|
} from "./types/ShippingMethodZipCodeRangeUnassign";
|
||||||
|
import {
|
||||||
|
ShippingPriceExcludeProduct,
|
||||||
|
ShippingPriceExcludeProductVariables
|
||||||
|
} from "./types/ShippingPriceExcludeProduct";
|
||||||
|
import {
|
||||||
|
ShippingPriceRemoveProductFromExclude,
|
||||||
|
ShippingPriceRemoveProductFromExcludeVariables
|
||||||
|
} from "./types/ShippingPriceRemoveProductFromExclude";
|
||||||
import {
|
import {
|
||||||
UpdateDefaultWeightUnit,
|
UpdateDefaultWeightUnit,
|
||||||
UpdateDefaultWeightUnitVariables
|
UpdateDefaultWeightUnitVariables
|
||||||
|
@ -297,3 +305,38 @@ export const useShippingMethodZipCodeRangeUnassign = makeMutation<
|
||||||
ShippingMethodZipCodeRangeUnassign,
|
ShippingMethodZipCodeRangeUnassign,
|
||||||
ShippingMethodZipCodeRangeUnassignVariables
|
ShippingMethodZipCodeRangeUnassignVariables
|
||||||
>(shippingMethodZipCodeRulesDelete);
|
>(shippingMethodZipCodeRulesDelete);
|
||||||
|
|
||||||
|
export const shippingPriceExcludeProducts = gql`
|
||||||
|
${shippingErrorFragment}
|
||||||
|
mutation ShippingPriceExcludeProduct(
|
||||||
|
$id: ID!
|
||||||
|
$input: ShippingPriceExcludeProductsInput!
|
||||||
|
) {
|
||||||
|
shippingPriceExcludeProducts(id: $id, input: $input) {
|
||||||
|
errors: shippingErrors {
|
||||||
|
...ShippingErrorFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useShippingPriceExcludeProduct = makeMutation<
|
||||||
|
ShippingPriceExcludeProduct,
|
||||||
|
ShippingPriceExcludeProductVariables
|
||||||
|
>(shippingPriceExcludeProducts);
|
||||||
|
|
||||||
|
export const shippingPriceRemoveProductsFromExclude = gql`
|
||||||
|
${shippingErrorFragment}
|
||||||
|
mutation ShippingPriceRemoveProductFromExclude($id: ID!, $products: [ID]!) {
|
||||||
|
shippingPriceRemoveProductFromExclude(id: $id, products: $products) {
|
||||||
|
errors: shippingErrors {
|
||||||
|
...ShippingErrorFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useShippingPriceRemoveProductsFromExclude = makeMutation<
|
||||||
|
ShippingPriceRemoveProductFromExclude,
|
||||||
|
ShippingPriceRemoveProductFromExcludeVariables
|
||||||
|
>(shippingPriceRemoveProductsFromExclude);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { pageInfoFragment } from "@saleor/fragments/pageInfo";
|
import { pageInfoFragment } from "@saleor/fragments/pageInfo";
|
||||||
import {
|
import {
|
||||||
shippingZoneDetailsFragment,
|
shippingMethodWithExcludedProductsFragment,
|
||||||
shippingZoneFragment
|
shippingZoneFragment
|
||||||
} from "@saleor/fragments/shipping";
|
} from "@saleor/fragments/shipping";
|
||||||
import makeQuery from "@saleor/hooks/makeQuery";
|
import makeQuery from "@saleor/hooks/makeQuery";
|
||||||
|
@ -36,10 +36,25 @@ export const useShippingZoneList = makeQuery<
|
||||||
>(shippingZones);
|
>(shippingZones);
|
||||||
|
|
||||||
const shippingZone = gql`
|
const shippingZone = gql`
|
||||||
${shippingZoneDetailsFragment}
|
${shippingZoneFragment}
|
||||||
query ShippingZone($id: ID!) {
|
${shippingMethodWithExcludedProductsFragment}
|
||||||
|
query ShippingZone(
|
||||||
|
$id: ID!
|
||||||
|
$before: String
|
||||||
|
$after: String
|
||||||
|
$first: Int
|
||||||
|
$last: Int
|
||||||
|
) {
|
||||||
shippingZone(id: $id) {
|
shippingZone(id: $id) {
|
||||||
...ShippingZoneDetailsFragment
|
...ShippingZoneFragment
|
||||||
|
default
|
||||||
|
shippingMethods {
|
||||||
|
...ShippingMethodWithExcludedProductsFragment
|
||||||
|
}
|
||||||
|
warehouses {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
29
src/shipping/types/ShippingPriceExcludeProduct.ts
Normal file
29
src/shipping/types/ShippingPriceExcludeProduct.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { ShippingPriceExcludeProductsInput, ShippingErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: ShippingPriceExcludeProduct
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface ShippingPriceExcludeProduct_shippingPriceExcludeProducts_errors {
|
||||||
|
__typename: "ShippingError";
|
||||||
|
code: ShippingErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceExcludeProduct_shippingPriceExcludeProducts {
|
||||||
|
__typename: "ShippingPriceExcludeProducts";
|
||||||
|
errors: ShippingPriceExcludeProduct_shippingPriceExcludeProducts_errors[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceExcludeProduct {
|
||||||
|
shippingPriceExcludeProducts: ShippingPriceExcludeProduct_shippingPriceExcludeProducts | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceExcludeProductVariables {
|
||||||
|
id: string;
|
||||||
|
input: ShippingPriceExcludeProductsInput;
|
||||||
|
}
|
29
src/shipping/types/ShippingPriceRemoveProductFromExclude.ts
Normal file
29
src/shipping/types/ShippingPriceRemoveProductFromExclude.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { ShippingErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: ShippingPriceRemoveProductFromExclude
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface ShippingPriceRemoveProductFromExclude_shippingPriceRemoveProductFromExclude_errors {
|
||||||
|
__typename: "ShippingError";
|
||||||
|
code: ShippingErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceRemoveProductFromExclude_shippingPriceRemoveProductFromExclude {
|
||||||
|
__typename: "ShippingPriceRemoveProductFromExclude";
|
||||||
|
errors: ShippingPriceRemoveProductFromExclude_shippingPriceRemoveProductFromExclude_errors[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceRemoveProductFromExclude {
|
||||||
|
shippingPriceRemoveProductFromExclude: ShippingPriceRemoveProductFromExclude_shippingPriceRemoveProductFromExclude | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceRemoveProductFromExcludeVariables {
|
||||||
|
id: string;
|
||||||
|
products: (string | null)[];
|
||||||
|
}
|
|
@ -67,6 +67,37 @@ export interface ShippingZone_shippingZone_shippingMethods_channelListings {
|
||||||
maximumOrderPrice: ShippingZone_shippingZone_shippingMethods_channelListings_maximumOrderPrice | null;
|
maximumOrderPrice: ShippingZone_shippingZone_shippingMethods_channelListings_maximumOrderPrice | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShippingZone_shippingZone_shippingMethods_excludedProducts_pageInfo {
|
||||||
|
__typename: "PageInfo";
|
||||||
|
hasNextPage: boolean;
|
||||||
|
hasPreviousPage: boolean;
|
||||||
|
endCursor: string | null;
|
||||||
|
startCursor: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingZone_shippingZone_shippingMethods_excludedProducts_edges_node_thumbnail {
|
||||||
|
__typename: "Image";
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingZone_shippingZone_shippingMethods_excludedProducts_edges_node {
|
||||||
|
__typename: "Product";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
thumbnail: ShippingZone_shippingZone_shippingMethods_excludedProducts_edges_node_thumbnail | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingZone_shippingZone_shippingMethods_excludedProducts_edges {
|
||||||
|
__typename: "ProductCountableEdge";
|
||||||
|
node: ShippingZone_shippingZone_shippingMethods_excludedProducts_edges_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShippingZone_shippingZone_shippingMethods_excludedProducts {
|
||||||
|
__typename: "ProductCountableConnection";
|
||||||
|
pageInfo: ShippingZone_shippingZone_shippingMethods_excludedProducts_pageInfo;
|
||||||
|
edges: ShippingZone_shippingZone_shippingMethods_excludedProducts_edges[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ShippingZone_shippingZone_shippingMethods {
|
export interface ShippingZone_shippingZone_shippingMethods {
|
||||||
__typename: "ShippingMethod";
|
__typename: "ShippingMethod";
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -76,6 +107,7 @@ export interface ShippingZone_shippingZone_shippingMethods {
|
||||||
name: string;
|
name: string;
|
||||||
type: ShippingMethodTypeEnum | null;
|
type: ShippingMethodTypeEnum | null;
|
||||||
channelListings: ShippingZone_shippingZone_shippingMethods_channelListings[] | null;
|
channelListings: ShippingZone_shippingZone_shippingMethods_channelListings[] | null;
|
||||||
|
excludedProducts: ShippingZone_shippingZone_shippingMethods_excludedProducts | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShippingZone_shippingZone_warehouses {
|
export interface ShippingZone_shippingZone_warehouses {
|
||||||
|
@ -100,4 +132,8 @@ export interface ShippingZone {
|
||||||
|
|
||||||
export interface ShippingZoneVariables {
|
export interface ShippingZoneVariables {
|
||||||
id: string;
|
id: string;
|
||||||
|
before?: string | null;
|
||||||
|
after?: string | null;
|
||||||
|
first?: number | null;
|
||||||
|
last?: number | null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,30 @@ export type ShippingZoneUrlDialog =
|
||||||
| "remove"
|
| "remove"
|
||||||
| "remove-rate"
|
| "remove-rate"
|
||||||
| "unassign-country";
|
| "unassign-country";
|
||||||
|
|
||||||
|
export type ShippingMethodActions = "assign-product" | "unassign-product";
|
||||||
|
|
||||||
export type ShippingZoneUrlQueryParams = Dialog<ShippingZoneUrlDialog> &
|
export type ShippingZoneUrlQueryParams = Dialog<ShippingZoneUrlDialog> &
|
||||||
SingleAction &
|
SingleAction &
|
||||||
Partial<{
|
Partial<{
|
||||||
type: ShippingMethodTypeEnum;
|
type: ShippingMethodTypeEnum;
|
||||||
}>;
|
}> &
|
||||||
|
Pagination;
|
||||||
export const shippingZoneUrl = (
|
export const shippingZoneUrl = (
|
||||||
id: string,
|
id: string,
|
||||||
params?: ShippingZoneUrlQueryParams
|
params?: ShippingZoneUrlQueryParams
|
||||||
) => shippingZonePath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
) => shippingZonePath(encodeURIComponent(id)) + "?" + stringifyQs(params);
|
||||||
|
|
||||||
type ZipCodeRangeActions = "add-range" | "remove-range";
|
type ZipCodeRangeActions = "add-range" | "remove-range";
|
||||||
export type ShippingRateUrlDialog = ZipCodeRangeActions | "remove";
|
export type ShippingRateUrlDialog =
|
||||||
|
| ZipCodeRangeActions
|
||||||
|
| "remove"
|
||||||
|
| ShippingMethodActions;
|
||||||
|
|
||||||
export type ShippingRateUrlQueryParams = Dialog<ShippingRateUrlDialog> &
|
export type ShippingRateUrlQueryParams = Dialog<ShippingRateUrlDialog> &
|
||||||
SingleAction;
|
SingleAction &
|
||||||
|
BulkAction &
|
||||||
|
Pagination;
|
||||||
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions;
|
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions;
|
||||||
export type ShippingRateCreateUrlQueryParams = Dialog<
|
export type ShippingRateCreateUrlQueryParams = Dialog<
|
||||||
ShippingRateCreateUrlDialog
|
ShippingRateCreateUrlDialog
|
||||||
|
|
|
@ -7,7 +7,7 @@ import useChannels from "@saleor/hooks/useChannels";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||||
import ShippingZoneRatesPage from "@saleor/shipping/components/ShippingZoneRatesPage";
|
import ShippingZoneRatesCreatePage from "@saleor/shipping/components/ShippingZoneRatesCreatePage";
|
||||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||||
import { useShippingRateCreator } from "@saleor/shipping/handlers";
|
import { useShippingRateCreator } from "@saleor/shipping/handlers";
|
||||||
import {
|
import {
|
||||||
|
@ -114,7 +114,7 @@ export const PriceRatesCreate: React.FC<PriceRatesCreateProps> = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ShippingZoneRatesPage
|
<ShippingZoneRatesCreatePage
|
||||||
allChannelsCount={allChannels?.length}
|
allChannelsCount={allChannels?.length}
|
||||||
shippingChannels={currentChannels}
|
shippingChannels={currentChannels}
|
||||||
disabled={channelsLoading || status === "loading"}
|
disabled={channelsLoading || status === "loading"}
|
||||||
|
@ -123,7 +123,6 @@ export const PriceRatesCreate: React.FC<PriceRatesCreateProps> = ({
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
channelErrors={channelErrors}
|
channelErrors={channelErrors}
|
||||||
rate={null}
|
|
||||||
zipCodes={zipCodes}
|
zipCodes={zipCodes}
|
||||||
openChannelsModal={handleChannelsModalOpen}
|
openChannelsModal={handleChannelsModalOpen}
|
||||||
onChannelsChange={setCurrentChannels}
|
onChannelsChange={setCurrentChannels}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
import { useChannelsList } from "@saleor/channels/queries";
|
import { useChannelsList } from "@saleor/channels/queries";
|
||||||
import {
|
import {
|
||||||
createShippingChannelsFromRate,
|
createShippingChannelsFromRate,
|
||||||
|
@ -5,17 +6,26 @@ import {
|
||||||
} from "@saleor/channels/utils";
|
} from "@saleor/channels/utils";
|
||||||
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
||||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||||
|
import { PAGINATE_BY } from "@saleor/config";
|
||||||
|
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||||
import useChannels from "@saleor/hooks/useChannels";
|
import useChannels from "@saleor/hooks/useChannels";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import usePaginator, {
|
||||||
|
createPaginationState
|
||||||
|
} from "@saleor/hooks/usePaginator";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import useProductSearch from "@saleor/searches/useProductSearch";
|
||||||
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
|
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
|
||||||
|
import ShippingMethodProductsAddDialog from "@saleor/shipping/components/ShippingMethodProductsAddDialog";
|
||||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||||
import ShippingZoneRatesPage, {
|
import ShippingZoneRatesPage, {
|
||||||
FormData
|
FormData
|
||||||
} from "@saleor/shipping/components/ShippingZoneRatesPage";
|
} from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||||
|
import UnassignDialog from "@saleor/shipping/components/UnassignDialog";
|
||||||
import {
|
import {
|
||||||
getShippingMethodChannelVariables,
|
getShippingMethodChannelVariables,
|
||||||
getUpdateShippingPriceRateVariables
|
getUpdateShippingPriceRateVariables
|
||||||
|
@ -23,9 +33,9 @@ import {
|
||||||
import {
|
import {
|
||||||
useShippingMethodChannelListingUpdate,
|
useShippingMethodChannelListingUpdate,
|
||||||
useShippingMethodZipCodeRangeAssign,
|
useShippingMethodZipCodeRangeAssign,
|
||||||
useShippingMethodZipCodeRangeUnassign
|
useShippingMethodZipCodeRangeUnassign,
|
||||||
} from "@saleor/shipping/mutations";
|
useShippingPriceExcludeProduct,
|
||||||
import {
|
useShippingPriceRemoveProductsFromExclude,
|
||||||
useShippingRateDelete,
|
useShippingRateDelete,
|
||||||
useShippingRateUpdate
|
useShippingRateUpdate
|
||||||
} from "@saleor/shipping/mutations";
|
} from "@saleor/shipping/mutations";
|
||||||
|
@ -39,7 +49,7 @@ import {
|
||||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
export interface PriceRatesUpdateProps {
|
export interface PriceRatesUpdateProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -55,11 +65,19 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const paginate = usePaginator();
|
||||||
|
|
||||||
const { data, loading } = useShippingZone({
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
|
|
||||||
|
const { data, loading, refetch } = useShippingZone({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
variables: { id }
|
variables: { id, ...paginationState }
|
||||||
});
|
});
|
||||||
|
const {
|
||||||
|
loadMore,
|
||||||
|
search: productsSearch,
|
||||||
|
result: productsSearchOpts
|
||||||
|
} = useProductSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA });
|
||||||
|
|
||||||
const [openModal, closeModal] = createDialogActionHandlers<
|
const [openModal, closeModal] = createDialogActionHandlers<
|
||||||
ShippingRateUrlDialog,
|
ShippingRateUrlDialog,
|
||||||
|
@ -69,6 +87,17 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
const rate = data?.shippingZone?.shippingMethods.find(
|
const rate = data?.shippingZone?.shippingMethods.find(
|
||||||
rate => rate.id === rateId
|
rate => rate.id === rateId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions(
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||||
|
rate?.excludedProducts.pageInfo,
|
||||||
|
paginationState,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
const { data: channelsData } = useChannelsList({});
|
const { data: channelsData } = useChannelsList({});
|
||||||
|
|
||||||
const [
|
const [
|
||||||
|
@ -98,6 +127,7 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const [
|
const [
|
||||||
unassignZipCodeRange,
|
unassignZipCodeRange,
|
||||||
unassignZipCodeRangeOpts
|
unassignZipCodeRangeOpts
|
||||||
|
@ -108,11 +138,32 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
status: "success",
|
status: "success",
|
||||||
text: intl.formatMessage(commonMessages.savedChanges)
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const [
|
||||||
|
unassignProduct,
|
||||||
|
unassignProductOpts
|
||||||
|
] = useShippingPriceRemoveProductsFromExclude({
|
||||||
|
onCompleted: data => {
|
||||||
|
if (data.shippingPriceRemoveProductFromExclude.errors.length === 0) {
|
||||||
|
handleSuccess();
|
||||||
|
refetch();
|
||||||
closeModal();
|
closeModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [assignProduct, assignProductOpts] = useShippingPriceExcludeProduct({
|
||||||
|
onCompleted: data => {
|
||||||
|
if (data.shippingPriceExcludeProducts.errors.length === 0) {
|
||||||
|
handleSuccess();
|
||||||
|
refetch();
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
const shippingChannels = createShippingChannelsFromRate(
|
const shippingChannels = createShippingChannelsFromRate(
|
||||||
rate?.channelListings
|
rate?.channelListings
|
||||||
);
|
);
|
||||||
|
@ -168,6 +219,18 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleProductAssign = (ids: string[]) =>
|
||||||
|
assignProduct({
|
||||||
|
variables: { id: rateId, input: { products: ids } }
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleProductUnassign = (ids: string[]) => {
|
||||||
|
unassignProduct({
|
||||||
|
variables: { id: rateId, products: ids }
|
||||||
|
});
|
||||||
|
reset();
|
||||||
|
};
|
||||||
|
|
||||||
const handleBack = () => navigate(shippingZoneUrl(id));
|
const handleBack = () => navigate(shippingZoneUrl(id));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -203,13 +266,35 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
open={params.action === "remove"}
|
open={params.action === "remove"}
|
||||||
name={rate?.name}
|
name={rate?.name}
|
||||||
/>
|
/>
|
||||||
|
<UnassignDialog
|
||||||
|
open={params.action === "unassign-product" && !!listElements.length}
|
||||||
|
idsLength={listElements.length}
|
||||||
|
confirmButtonState={unassignProductOpts.status}
|
||||||
|
closeModal={closeModal}
|
||||||
|
onConfirm={() => handleProductUnassign(listElements)}
|
||||||
|
/>
|
||||||
|
<ShippingMethodProductsAddDialog
|
||||||
|
confirmButtonState={assignProductOpts.status}
|
||||||
|
loading={productsSearchOpts.loading}
|
||||||
|
open={params.action === "assign-product"}
|
||||||
|
hasMore={productsSearchOpts.data?.search?.pageInfo.hasNextPage}
|
||||||
|
products={productsSearchOpts.data?.search?.edges
|
||||||
|
.map(edge => edge.node)
|
||||||
|
.filter(suggestedProduct => suggestedProduct.id)}
|
||||||
|
onClose={closeModal}
|
||||||
|
onFetch={productsSearch}
|
||||||
|
onFetchMore={loadMore}
|
||||||
|
onSubmit={handleProductAssign}
|
||||||
|
/>
|
||||||
<ShippingZoneRatesPage
|
<ShippingZoneRatesPage
|
||||||
allChannelsCount={allChannels?.length}
|
allChannelsCount={allChannels?.length}
|
||||||
shippingChannels={currentChannels}
|
shippingChannels={currentChannels}
|
||||||
disabled={
|
disabled={
|
||||||
loading ||
|
loading ||
|
||||||
updateShippingRateOpts?.status === "loading" ||
|
updateShippingRateOpts?.status === "loading" ||
|
||||||
updateShippingMethodChannelListingOpts?.status === "loading"
|
updateShippingMethodChannelListingOpts?.status === "loading" ||
|
||||||
|
unassignProductOpts?.status === "loading" ||
|
||||||
|
assignProductOpts?.status === "loading"
|
||||||
}
|
}
|
||||||
hasChannelChanged={shippingChannels?.length !== currentChannels?.length}
|
hasChannelChanged={shippingChannels?.length !== currentChannels?.length}
|
||||||
saveButtonBarState={updateShippingRateOpts.status}
|
saveButtonBarState={updateShippingRateOpts.status}
|
||||||
|
@ -224,7 +309,24 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
|
||||||
}
|
}
|
||||||
openChannelsModal={handleChannelsModalOpen}
|
openChannelsModal={handleChannelsModalOpen}
|
||||||
onChannelsChange={setCurrentChannels}
|
onChannelsChange={setCurrentChannels}
|
||||||
|
onProductUnassign={handleProductUnassign}
|
||||||
|
onProductAssign={() => openModal("assign-product")}
|
||||||
variant={ShippingMethodTypeEnum.PRICE}
|
variant={ShippingMethodTypeEnum.PRICE}
|
||||||
|
isChecked={isSelected}
|
||||||
|
selected={listElements.length}
|
||||||
|
toggle={toggle}
|
||||||
|
toggleAll={toggleAll}
|
||||||
|
onNextPage={loadNextPage}
|
||||||
|
onPreviousPage={loadPreviousPage}
|
||||||
|
pageInfo={pageInfo}
|
||||||
|
toolbar={
|
||||||
|
<Button color="primary" onClick={() => openModal("unassign-product")}>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Unassign"
|
||||||
|
description="unassign products from shipping method, button"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
onZipCodeAssign={() => openModal("add-range")}
|
onZipCodeAssign={() => openModal("add-range")}
|
||||||
onZipCodeUnassign={id =>
|
onZipCodeUnassign={id =>
|
||||||
openModal("remove-range", {
|
openModal("remove-range", {
|
||||||
|
|
|
@ -3,8 +3,10 @@ import ActionDialog from "@saleor/components/ActionDialog";
|
||||||
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
|
||||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||||
|
import { PAGINATE_BY } from "@saleor/config";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { createPaginationState } from "@saleor/hooks/usePaginator";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
|
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
|
||||||
|
@ -53,6 +55,8 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const shop = useShop();
|
const shop = useShop();
|
||||||
|
|
||||||
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
|
|
||||||
const { result: searchWarehousesOpts, loadMore, search } = useWarehouseSearch(
|
const { result: searchWarehousesOpts, loadMore, search } = useWarehouseSearch(
|
||||||
{
|
{
|
||||||
variables: DEFAULT_INITIAL_SEARCH_DATA
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
|
@ -61,7 +65,7 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
||||||
|
|
||||||
const { data, loading } = useShippingZone({
|
const { data, loading } = useShippingZone({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
variables: { id }
|
variables: { id, ...paginationState }
|
||||||
});
|
});
|
||||||
const { channel } = useAppChannel();
|
const { channel } = useAppChannel();
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import useChannels from "@saleor/hooks/useChannels";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||||
import ShippingZoneRatesPage from "@saleor/shipping/components/ShippingZoneRatesPage";
|
import ShippingZoneRatesCreatePage from "@saleor/shipping/components/ShippingZoneRatesCreatePage";
|
||||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||||
import { useShippingRateCreator } from "@saleor/shipping/handlers";
|
import { useShippingRateCreator } from "@saleor/shipping/handlers";
|
||||||
import {
|
import {
|
||||||
|
@ -117,7 +117,7 @@ export const WeightRatesCreate: React.FC<WeightRatesCreateProps> = ({
|
||||||
toggleAll={toggleAllChannels}
|
toggleAll={toggleAllChannels}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ShippingZoneRatesPage
|
<ShippingZoneRatesCreatePage
|
||||||
allChannelsCount={allChannels?.length}
|
allChannelsCount={allChannels?.length}
|
||||||
shippingChannels={currentChannels}
|
shippingChannels={currentChannels}
|
||||||
disabled={channelsLoading || status === "loading"}
|
disabled={channelsLoading || status === "loading"}
|
||||||
|
@ -126,7 +126,6 @@ export const WeightRatesCreate: React.FC<WeightRatesCreateProps> = ({
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
channelErrors={channelErrors}
|
channelErrors={channelErrors}
|
||||||
rate={null}
|
|
||||||
zipCodes={zipCodes}
|
zipCodes={zipCodes}
|
||||||
openChannelsModal={handleChannelsModalOpen}
|
openChannelsModal={handleChannelsModalOpen}
|
||||||
onChannelsChange={setCurrentChannels}
|
onChannelsChange={setCurrentChannels}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
import { useChannelsList } from "@saleor/channels/queries";
|
import { useChannelsList } from "@saleor/channels/queries";
|
||||||
import {
|
import {
|
||||||
createShippingChannelsFromRate,
|
createShippingChannelsFromRate,
|
||||||
|
@ -5,28 +6,39 @@ import {
|
||||||
} from "@saleor/channels/utils";
|
} from "@saleor/channels/utils";
|
||||||
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
|
||||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
|
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||||
|
import { PAGINATE_BY } from "@saleor/config";
|
||||||
|
import useBulkActions from "@saleor/hooks/useBulkActions";
|
||||||
import useChannels from "@saleor/hooks/useChannels";
|
import useChannels from "@saleor/hooks/useChannels";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import usePaginator, {
|
||||||
|
createPaginationState
|
||||||
|
} from "@saleor/hooks/usePaginator";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import useProductSearch from "@saleor/searches/useProductSearch";
|
||||||
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
|
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
|
||||||
|
import ShippingMethodProductsAddDialog from "@saleor/shipping/components/ShippingMethodProductsAddDialog";
|
||||||
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
|
||||||
import ShippingZoneRatesPage, {
|
import ShippingZoneRatesPage, {
|
||||||
FormData
|
FormData
|
||||||
} from "@saleor/shipping/components/ShippingZoneRatesPage";
|
} from "@saleor/shipping/components/ShippingZoneRatesPage";
|
||||||
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
|
||||||
|
import UnassignDialog from "@saleor/shipping/components/UnassignDialog";
|
||||||
import {
|
import {
|
||||||
getShippingMethodChannelVariables,
|
getShippingMethodChannelVariables,
|
||||||
getUpdateShippingWeightRateVariables
|
getUpdateShippingWeightRateVariables
|
||||||
} from "@saleor/shipping/handlers";
|
} from "@saleor/shipping/handlers";
|
||||||
import {
|
import {
|
||||||
|
useShippingMethodChannelListingUpdate,
|
||||||
useShippingMethodZipCodeRangeAssign,
|
useShippingMethodZipCodeRangeAssign,
|
||||||
useShippingMethodZipCodeRangeUnassign,
|
useShippingMethodZipCodeRangeUnassign,
|
||||||
|
useShippingPriceExcludeProduct,
|
||||||
|
useShippingPriceRemoveProductsFromExclude,
|
||||||
useShippingRateDelete,
|
useShippingRateDelete,
|
||||||
useShippingRateUpdate
|
useShippingRateUpdate
|
||||||
} from "@saleor/shipping/mutations";
|
} from "@saleor/shipping/mutations";
|
||||||
import { useShippingMethodChannelListingUpdate } from "@saleor/shipping/mutations";
|
|
||||||
import { useShippingZone } from "@saleor/shipping/queries";
|
import { useShippingZone } from "@saleor/shipping/queries";
|
||||||
import {
|
import {
|
||||||
ShippingRateUrlDialog,
|
ShippingRateUrlDialog,
|
||||||
|
@ -37,7 +49,7 @@ import {
|
||||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
export interface WeightRatesUpdateProps {
|
export interface WeightRatesUpdateProps {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -53,10 +65,13 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const paginate = usePaginator();
|
||||||
|
|
||||||
const { data, loading } = useShippingZone({
|
const paginationState = createPaginationState(PAGINATE_BY, params);
|
||||||
|
|
||||||
|
const { data, loading, refetch } = useShippingZone({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
variables: { id }
|
variables: { id, ...paginationState }
|
||||||
});
|
});
|
||||||
|
|
||||||
const [openModal, closeModal] = createDialogActionHandlers<
|
const [openModal, closeModal] = createDialogActionHandlers<
|
||||||
|
@ -64,15 +79,55 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
||||||
ShippingRateUrlQueryParams
|
ShippingRateUrlQueryParams
|
||||||
>(navigate, params => shippingWeightRatesEditUrl(id, rateId, params), params);
|
>(navigate, params => shippingWeightRatesEditUrl(id, rateId, params), params);
|
||||||
|
|
||||||
|
const {
|
||||||
|
loadMore,
|
||||||
|
search: productsSearch,
|
||||||
|
result: productsSearchOpts
|
||||||
|
} = useProductSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA });
|
||||||
|
|
||||||
const rate = data?.shippingZone?.shippingMethods.find(
|
const rate = data?.shippingZone?.shippingMethods.find(
|
||||||
rate => rate.id === rateId
|
rate => rate.id === rateId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions(
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
|
||||||
|
rate?.excludedProducts.pageInfo,
|
||||||
|
paginationState,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
const { data: channelsData } = useChannelsList({});
|
const { data: channelsData } = useChannelsList({});
|
||||||
const [
|
const [
|
||||||
updateShippingMethodChannelListing,
|
updateShippingMethodChannelListing,
|
||||||
updateShippingMethodChannelListingOpts
|
updateShippingMethodChannelListingOpts
|
||||||
] = useShippingMethodChannelListingUpdate({});
|
] = useShippingMethodChannelListingUpdate({});
|
||||||
|
|
||||||
|
const [
|
||||||
|
unassignProduct,
|
||||||
|
unassignProductOpts
|
||||||
|
] = useShippingPriceRemoveProductsFromExclude({
|
||||||
|
onCompleted: data => {
|
||||||
|
if (data.shippingPriceRemoveProductFromExclude.errors.length === 0) {
|
||||||
|
handleSuccess();
|
||||||
|
refetch();
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const [assignProduct, assignProductOpts] = useShippingPriceExcludeProduct({
|
||||||
|
onCompleted: data => {
|
||||||
|
if (data.shippingPriceExcludeProducts.errors.length === 0) {
|
||||||
|
handleSuccess();
|
||||||
|
refetch();
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const shippingChannels = createShippingChannelsFromRate(
|
const shippingChannels = createShippingChannelsFromRate(
|
||||||
rate?.channelListings
|
rate?.channelListings
|
||||||
);
|
);
|
||||||
|
@ -166,6 +221,18 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleProductAssign = (ids: string[]) =>
|
||||||
|
assignProduct({
|
||||||
|
variables: { id: rateId, input: { products: ids } }
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleProductUnassign = (ids: string[]) => {
|
||||||
|
unassignProduct({
|
||||||
|
variables: { id: rateId, products: ids }
|
||||||
|
});
|
||||||
|
reset();
|
||||||
|
};
|
||||||
|
|
||||||
const handleBack = () => navigate(shippingZoneUrl(id));
|
const handleBack = () => navigate(shippingZoneUrl(id));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -201,13 +268,35 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
||||||
open={params.action === "remove"}
|
open={params.action === "remove"}
|
||||||
name={rate?.name}
|
name={rate?.name}
|
||||||
/>
|
/>
|
||||||
|
<UnassignDialog
|
||||||
|
open={params.action === "unassign-product" && !!listElements.length}
|
||||||
|
idsLength={listElements.length}
|
||||||
|
confirmButtonState={unassignProductOpts.status}
|
||||||
|
closeModal={closeModal}
|
||||||
|
onConfirm={() => handleProductUnassign(listElements)}
|
||||||
|
/>
|
||||||
|
<ShippingMethodProductsAddDialog
|
||||||
|
confirmButtonState={assignProductOpts.status}
|
||||||
|
loading={productsSearchOpts.loading}
|
||||||
|
open={params.action === "assign-product"}
|
||||||
|
hasMore={productsSearchOpts.data?.search?.pageInfo.hasNextPage}
|
||||||
|
products={productsSearchOpts.data?.search?.edges
|
||||||
|
.map(edge => edge.node)
|
||||||
|
.filter(suggestedProduct => suggestedProduct.id)}
|
||||||
|
onClose={closeModal}
|
||||||
|
onFetch={productsSearch}
|
||||||
|
onFetchMore={loadMore}
|
||||||
|
onSubmit={handleProductAssign}
|
||||||
|
/>
|
||||||
<ShippingZoneRatesPage
|
<ShippingZoneRatesPage
|
||||||
allChannelsCount={allChannels?.length}
|
allChannelsCount={allChannels?.length}
|
||||||
shippingChannels={currentChannels}
|
shippingChannels={currentChannels}
|
||||||
disabled={
|
disabled={
|
||||||
loading ||
|
loading ||
|
||||||
updateShippingRateOpts?.status === "loading" ||
|
updateShippingRateOpts?.status === "loading" ||
|
||||||
updateShippingMethodChannelListingOpts?.status === "loading"
|
updateShippingMethodChannelListingOpts?.status === "loading" ||
|
||||||
|
unassignProductOpts?.status === "loading" ||
|
||||||
|
assignProductOpts?.status === "loading"
|
||||||
}
|
}
|
||||||
hasChannelChanged={shippingChannels?.length !== currentChannels?.length}
|
hasChannelChanged={shippingChannels?.length !== currentChannels?.length}
|
||||||
saveButtonBarState={updateShippingRateOpts.status}
|
saveButtonBarState={updateShippingRateOpts.status}
|
||||||
|
@ -222,7 +311,24 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
|
||||||
}
|
}
|
||||||
openChannelsModal={handleChannelsModalOpen}
|
openChannelsModal={handleChannelsModalOpen}
|
||||||
onChannelsChange={setCurrentChannels}
|
onChannelsChange={setCurrentChannels}
|
||||||
|
onProductUnassign={handleProductUnassign}
|
||||||
|
onProductAssign={() => openModal("assign-product")}
|
||||||
variant={ShippingMethodTypeEnum.WEIGHT}
|
variant={ShippingMethodTypeEnum.WEIGHT}
|
||||||
|
isChecked={isSelected}
|
||||||
|
selected={listElements.length}
|
||||||
|
toggle={toggle}
|
||||||
|
toggleAll={toggleAll}
|
||||||
|
onNextPage={loadNextPage}
|
||||||
|
onPreviousPage={loadPreviousPage}
|
||||||
|
pageInfo={pageInfo}
|
||||||
|
toolbar={
|
||||||
|
<Button color="primary" onClick={() => openModal("unassign-product")}>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Unassign"
|
||||||
|
description="unassign products from shipping method, button"
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
onZipCodeAssign={() => openModal("add-range")}
|
onZipCodeAssign={() => openModal("add-range")}
|
||||||
onZipCodeUnassign={id =>
|
onZipCodeUnassign={id =>
|
||||||
openModal("remove-range", {
|
openModal("remove-range", {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1689,6 +1689,10 @@ export interface ShippingMethodChannelListingInput {
|
||||||
removeChannels?: string[] | null;
|
removeChannels?: string[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShippingPriceExcludeProductsInput {
|
||||||
|
products: (string | null)[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface ShippingPriceInput {
|
export interface ShippingPriceInput {
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
minimumOrderWeight?: any | null;
|
minimumOrderWeight?: any | null;
|
||||||
|
|
Loading…
Reference in a new issue