= ({
onZipCodeDelete={onZipCodeUnassign}
onZipCodeInclusionChange={() => undefined}
onZipCodeRangeAdd={onZipCodeAssign}
- zipCodes={rateExists ? rate?.zipCodeRules : zipCodes}
+ zipCodes={rate?.zipCodeRules}
+ />
+
+ edge.node
+ )}
+ onProductAssign={onProductAssign}
+ onProductUnassign={onProductUnassign}
+ disabled={disabled}
+ {...listProps}
/>
diff --git a/src/shipping/components/UnassignDialog/UnassignDialog.stories.tsx b/src/shipping/components/UnassignDialog/UnassignDialog.stories.tsx
new file mode 100644
index 000000000..f18f170a3
--- /dev/null
+++ b/src/shipping/components/UnassignDialog/UnassignDialog.stories.tsx
@@ -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", () =>
);
diff --git a/src/shipping/components/UnassignDialog/UnassignDialog.tsx b/src/shipping/components/UnassignDialog/UnassignDialog.tsx
new file mode 100644
index 000000000..ca2f71a5a
--- /dev/null
+++ b/src/shipping/components/UnassignDialog/UnassignDialog.tsx
@@ -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
= ({
+ closeModal,
+ confirmButtonState,
+ idsLength,
+ onConfirm,
+ open
+}) => {
+ const intl = useIntl();
+ return (
+
+
+ {idsLength}
+ }}
+ />
+
+
+ );
+};
+
+export default UnassignDialog;
diff --git a/src/shipping/components/UnassignDialog/index.ts b/src/shipping/components/UnassignDialog/index.ts
new file mode 100644
index 000000000..57f90cddb
--- /dev/null
+++ b/src/shipping/components/UnassignDialog/index.ts
@@ -0,0 +1,2 @@
+export * from "./UnassignDialog";
+export { default } from "./UnassignDialog";
diff --git a/src/shipping/fixtures.ts b/src/shipping/fixtures.ts
index 7045d9e0b..57a463517 100644
--- a/src/shipping/fixtures.ts
+++ b/src/shipping/fixtures.ts
@@ -1,5 +1,6 @@
-import { ShippingZoneDetailsFragment } from "@saleor/fragments/types/ShippingZoneDetailsFragment";
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";
@@ -1285,7 +1286,7 @@ export const shippingZones: ShippingZoneFragment[] = [
}
];
-export const shippingZone: ShippingZoneDetailsFragment = {
+export const shippingZone: ShippingZone_shippingZone = {
__typename: "ShippingZone",
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==",
maximumOrderWeight: {
__typename: "Weight",
@@ -1614,6 +1639,30 @@ export const shippingZone: ShippingZoneDetailsFragment = {
{
__typename: "ShippingMethod",
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==",
maximumOrderWeight: null,
minimumOrderWeight: {
@@ -1647,6 +1696,30 @@ export const shippingZone: ShippingZoneDetailsFragment = {
{
__typename: "ShippingMethod",
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==",
maximumOrderWeight: null,
minimumOrderWeight: {
@@ -1680,6 +1753,17 @@ export const shippingZone: ShippingZoneDetailsFragment = {
{
__typename: "ShippingMethod",
channelListings: [],
+ excludedProducts: {
+ __typename: "ProductCountableConnection",
+ edges: [],
+ pageInfo: {
+ __typename: "PageInfo",
+ endCursor: "",
+ hasNextPage: false,
+ hasPreviousPage: false,
+ startCursor: ""
+ }
+ },
id: "U2hpcHBpbmdNZXRob2Q6MQ==",
maximumOrderWeight: null,
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: ""
+ }
+ }
+];
diff --git a/src/shipping/mutations.ts b/src/shipping/mutations.ts
index 35c0f9438..8874db557 100644
--- a/src/shipping/mutations.ts
+++ b/src/shipping/mutations.ts
@@ -47,6 +47,14 @@ import {
ShippingMethodZipCodeRangeUnassign,
ShippingMethodZipCodeRangeUnassignVariables
} from "./types/ShippingMethodZipCodeRangeUnassign";
+import {
+ ShippingPriceExcludeProduct,
+ ShippingPriceExcludeProductVariables
+} from "./types/ShippingPriceExcludeProduct";
+import {
+ ShippingPriceRemoveProductFromExclude,
+ ShippingPriceRemoveProductFromExcludeVariables
+} from "./types/ShippingPriceRemoveProductFromExclude";
import {
UpdateDefaultWeightUnit,
UpdateDefaultWeightUnitVariables
@@ -297,3 +305,38 @@ export const useShippingMethodZipCodeRangeUnassign = makeMutation<
ShippingMethodZipCodeRangeUnassign,
ShippingMethodZipCodeRangeUnassignVariables
>(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);
diff --git a/src/shipping/queries.ts b/src/shipping/queries.ts
index 6f4eb71b3..5d288d90c 100644
--- a/src/shipping/queries.ts
+++ b/src/shipping/queries.ts
@@ -1,6 +1,6 @@
import { pageInfoFragment } from "@saleor/fragments/pageInfo";
import {
- shippingZoneDetailsFragment,
+ shippingMethodWithExcludedProductsFragment,
shippingZoneFragment
} from "@saleor/fragments/shipping";
import makeQuery from "@saleor/hooks/makeQuery";
@@ -36,10 +36,25 @@ export const useShippingZoneList = makeQuery<
>(shippingZones);
const shippingZone = gql`
- ${shippingZoneDetailsFragment}
- query ShippingZone($id: ID!) {
+ ${shippingZoneFragment}
+ ${shippingMethodWithExcludedProductsFragment}
+ query ShippingZone(
+ $id: ID!
+ $before: String
+ $after: String
+ $first: Int
+ $last: Int
+ ) {
shippingZone(id: $id) {
- ...ShippingZoneDetailsFragment
+ ...ShippingZoneFragment
+ default
+ shippingMethods {
+ ...ShippingMethodWithExcludedProductsFragment
+ }
+ warehouses {
+ id
+ name
+ }
}
}
`;
diff --git a/src/shipping/types/ShippingPriceExcludeProduct.ts b/src/shipping/types/ShippingPriceExcludeProduct.ts
new file mode 100644
index 000000000..cf70df077
--- /dev/null
+++ b/src/shipping/types/ShippingPriceExcludeProduct.ts
@@ -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;
+}
diff --git a/src/shipping/types/ShippingPriceRemoveProductFromExclude.ts b/src/shipping/types/ShippingPriceRemoveProductFromExclude.ts
new file mode 100644
index 000000000..1c55c5bf4
--- /dev/null
+++ b/src/shipping/types/ShippingPriceRemoveProductFromExclude.ts
@@ -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)[];
+}
diff --git a/src/shipping/types/ShippingZone.ts b/src/shipping/types/ShippingZone.ts
index 04bb69905..3d9724c80 100644
--- a/src/shipping/types/ShippingZone.ts
+++ b/src/shipping/types/ShippingZone.ts
@@ -67,6 +67,37 @@ export interface ShippingZone_shippingZone_shippingMethods_channelListings {
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 {
__typename: "ShippingMethod";
id: string;
@@ -76,6 +107,7 @@ export interface ShippingZone_shippingZone_shippingMethods {
name: string;
type: ShippingMethodTypeEnum | null;
channelListings: ShippingZone_shippingZone_shippingMethods_channelListings[] | null;
+ excludedProducts: ShippingZone_shippingZone_shippingMethods_excludedProducts | null;
}
export interface ShippingZone_shippingZone_warehouses {
@@ -100,4 +132,8 @@ export interface ShippingZone {
export interface ShippingZoneVariables {
id: string;
+ before?: string | null;
+ after?: string | null;
+ first?: number | null;
+ last?: number | null;
}
diff --git a/src/shipping/urls.ts b/src/shipping/urls.ts
index 2421f18a9..2f0fda05a 100644
--- a/src/shipping/urls.ts
+++ b/src/shipping/urls.ts
@@ -26,20 +26,30 @@ export type ShippingZoneUrlDialog =
| "remove"
| "remove-rate"
| "unassign-country";
+
+export type ShippingMethodActions = "assign-product" | "unassign-product";
+
export type ShippingZoneUrlQueryParams = Dialog &
SingleAction &
Partial<{
type: ShippingMethodTypeEnum;
- }>;
+ }> &
+ Pagination;
export const shippingZoneUrl = (
id: string,
params?: ShippingZoneUrlQueryParams
) => shippingZonePath(encodeURIComponent(id)) + "?" + stringifyQs(params);
type ZipCodeRangeActions = "add-range" | "remove-range";
-export type ShippingRateUrlDialog = ZipCodeRangeActions | "remove";
+export type ShippingRateUrlDialog =
+ | ZipCodeRangeActions
+ | "remove"
+ | ShippingMethodActions;
+
export type ShippingRateUrlQueryParams = Dialog &
- SingleAction;
+ SingleAction &
+ BulkAction &
+ Pagination;
export type ShippingRateCreateUrlDialog = ZipCodeRangeActions;
export type ShippingRateCreateUrlQueryParams = Dialog<
ShippingRateCreateUrlDialog
diff --git a/src/shipping/views/PriceRatesCreate/PriceRatesCreate.tsx b/src/shipping/views/PriceRatesCreate/PriceRatesCreate.tsx
index 3ce8f048c..05a481de8 100644
--- a/src/shipping/views/PriceRatesCreate/PriceRatesCreate.tsx
+++ b/src/shipping/views/PriceRatesCreate/PriceRatesCreate.tsx
@@ -7,7 +7,7 @@ import useChannels from "@saleor/hooks/useChannels";
import useNavigator from "@saleor/hooks/useNavigator";
import { sectionNames } from "@saleor/intl";
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 { useShippingRateCreator } from "@saleor/shipping/handlers";
import {
@@ -114,7 +114,7 @@ export const PriceRatesCreate: React.FC = ({
/>
)}
- = ({
onBack={handleBack}
errors={errors}
channelErrors={channelErrors}
- rate={null}
zipCodes={zipCodes}
openChannelsModal={handleChannelsModalOpen}
onChannelsChange={setCurrentChannels}
diff --git a/src/shipping/views/PriceRatesUpdate/PriceRatesUpdate.tsx b/src/shipping/views/PriceRatesUpdate/PriceRatesUpdate.tsx
index b83a646ea..deeb4f552 100644
--- a/src/shipping/views/PriceRatesUpdate/PriceRatesUpdate.tsx
+++ b/src/shipping/views/PriceRatesUpdate/PriceRatesUpdate.tsx
@@ -1,3 +1,4 @@
+import Button from "@material-ui/core/Button";
import { useChannelsList } from "@saleor/channels/queries";
import {
createShippingChannelsFromRate,
@@ -5,17 +6,26 @@ import {
} from "@saleor/channels/utils";
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
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 useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
+import usePaginator, {
+ createPaginationState
+} from "@saleor/hooks/usePaginator";
import { sectionNames } from "@saleor/intl";
import { commonMessages } from "@saleor/intl";
+import useProductSearch from "@saleor/searches/useProductSearch";
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
+import ShippingMethodProductsAddDialog from "@saleor/shipping/components/ShippingMethodProductsAddDialog";
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
import ShippingZoneRatesPage, {
FormData
} from "@saleor/shipping/components/ShippingZoneRatesPage";
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
+import UnassignDialog from "@saleor/shipping/components/UnassignDialog";
import {
getShippingMethodChannelVariables,
getUpdateShippingPriceRateVariables
@@ -23,9 +33,9 @@ import {
import {
useShippingMethodChannelListingUpdate,
useShippingMethodZipCodeRangeAssign,
- useShippingMethodZipCodeRangeUnassign
-} from "@saleor/shipping/mutations";
-import {
+ useShippingMethodZipCodeRangeUnassign,
+ useShippingPriceExcludeProduct,
+ useShippingPriceRemoveProductsFromExclude,
useShippingRateDelete,
useShippingRateUpdate
} from "@saleor/shipping/mutations";
@@ -39,7 +49,7 @@ import {
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import React from "react";
-import { useIntl } from "react-intl";
+import { FormattedMessage, useIntl } from "react-intl";
export interface PriceRatesUpdateProps {
id: string;
@@ -55,11 +65,19 @@ export const PriceRatesUpdate: React.FC = ({
const navigate = useNavigator();
const notify = useNotifier();
const intl = useIntl();
+ const paginate = usePaginator();
- const { data, loading } = useShippingZone({
+ const paginationState = createPaginationState(PAGINATE_BY, params);
+
+ const { data, loading, refetch } = useShippingZone({
displayLoader: true,
- variables: { id }
+ variables: { id, ...paginationState }
});
+ const {
+ loadMore,
+ search: productsSearch,
+ result: productsSearchOpts
+ } = useProductSearch({ variables: DEFAULT_INITIAL_SEARCH_DATA });
const [openModal, closeModal] = createDialogActionHandlers<
ShippingRateUrlDialog,
@@ -69,6 +87,17 @@ export const PriceRatesUpdate: React.FC = ({
const rate = data?.shippingZone?.shippingMethods.find(
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 [
@@ -98,6 +127,7 @@ export const PriceRatesUpdate: React.FC = ({
}
}
});
+
const [
unassignZipCodeRange,
unassignZipCodeRangeOpts
@@ -108,11 +138,32 @@ export const PriceRatesUpdate: React.FC = ({
status: "success",
text: intl.formatMessage(commonMessages.savedChanges)
});
+ }
+ }
+ });
+
+ 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(
rate?.channelListings
);
@@ -168,6 +219,18 @@ export const PriceRatesUpdate: React.FC = ({
}
};
+ 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));
return (
@@ -203,13 +266,35 @@ export const PriceRatesUpdate: React.FC = ({
open={params.action === "remove"}
name={rate?.name}
/>
+ handleProductUnassign(listElements)}
+ />
+ edge.node)
+ .filter(suggestedProduct => suggestedProduct.id)}
+ onClose={closeModal}
+ onFetch={productsSearch}
+ onFetchMore={loadMore}
+ onSubmit={handleProductAssign}
+ />
= ({
}
openChannelsModal={handleChannelsModalOpen}
onChannelsChange={setCurrentChannels}
+ onProductUnassign={handleProductUnassign}
+ onProductAssign={() => openModal("assign-product")}
variant={ShippingMethodTypeEnum.PRICE}
+ isChecked={isSelected}
+ selected={listElements.length}
+ toggle={toggle}
+ toggleAll={toggleAll}
+ onNextPage={loadNextPage}
+ onPreviousPage={loadPreviousPage}
+ pageInfo={pageInfo}
+ toolbar={
+
+ }
onZipCodeAssign={() => openModal("add-range")}
onZipCodeUnassign={id =>
openModal("remove-range", {
diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx
index 501b81cbe..33a66b200 100644
--- a/src/shipping/views/ShippingZoneDetails/index.tsx
+++ b/src/shipping/views/ShippingZoneDetails/index.tsx
@@ -3,8 +3,10 @@ import ActionDialog from "@saleor/components/ActionDialog";
import useAppChannel from "@saleor/components/AppLayout/AppChannelContext";
import NotFoundPage from "@saleor/components/NotFoundPage";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
+import { PAGINATE_BY } from "@saleor/config";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
+import { createPaginationState } from "@saleor/hooks/usePaginator";
import useShop from "@saleor/hooks/useShop";
import { commonMessages } from "@saleor/intl";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
@@ -53,6 +55,8 @@ const ShippingZoneDetails: React.FC = ({
const intl = useIntl();
const shop = useShop();
+ const paginationState = createPaginationState(PAGINATE_BY, params);
+
const { result: searchWarehousesOpts, loadMore, search } = useWarehouseSearch(
{
variables: DEFAULT_INITIAL_SEARCH_DATA
@@ -61,7 +65,7 @@ const ShippingZoneDetails: React.FC = ({
const { data, loading } = useShippingZone({
displayLoader: true,
- variables: { id }
+ variables: { id, ...paginationState }
});
const { channel } = useAppChannel();
diff --git a/src/shipping/views/WeightRatesCreate/WeightRatesCreate.tsx b/src/shipping/views/WeightRatesCreate/WeightRatesCreate.tsx
index 16bbd992d..fc16a78e3 100644
--- a/src/shipping/views/WeightRatesCreate/WeightRatesCreate.tsx
+++ b/src/shipping/views/WeightRatesCreate/WeightRatesCreate.tsx
@@ -10,7 +10,7 @@ import useChannels from "@saleor/hooks/useChannels";
import useNavigator from "@saleor/hooks/useNavigator";
import { sectionNames } from "@saleor/intl";
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 { useShippingRateCreator } from "@saleor/shipping/handlers";
import {
@@ -117,7 +117,7 @@ export const WeightRatesCreate: React.FC = ({
toggleAll={toggleAllChannels}
/>
)}
- = ({
onBack={handleBack}
errors={errors}
channelErrors={channelErrors}
- rate={null}
zipCodes={zipCodes}
openChannelsModal={handleChannelsModalOpen}
onChannelsChange={setCurrentChannels}
diff --git a/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx b/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx
index 2e6cbdb80..7216582b4 100644
--- a/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx
+++ b/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx
@@ -1,3 +1,4 @@
+import Button from "@material-ui/core/Button";
import { useChannelsList } from "@saleor/channels/queries";
import {
createShippingChannelsFromRate,
@@ -5,28 +6,39 @@ import {
} from "@saleor/channels/utils";
import ChannelsAvailabilityDialog from "@saleor/components/ChannelsAvailabilityDialog";
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 useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
+import usePaginator, {
+ createPaginationState
+} from "@saleor/hooks/usePaginator";
import { sectionNames } from "@saleor/intl";
import { commonMessages } from "@saleor/intl";
+import useProductSearch from "@saleor/searches/useProductSearch";
import DeleteShippingRateDialog from "@saleor/shipping/components/DeleteShippingRateDialog";
+import ShippingMethodProductsAddDialog from "@saleor/shipping/components/ShippingMethodProductsAddDialog";
import ShippingRateZipCodeRangeRemoveDialog from "@saleor/shipping/components/ShippingRateZipCodeRangeRemoveDialog";
import ShippingZoneRatesPage, {
FormData
} from "@saleor/shipping/components/ShippingZoneRatesPage";
import ShippingZoneZipCodeRangeDialog from "@saleor/shipping/components/ShippingZoneZipCodeRangeDialog";
+import UnassignDialog from "@saleor/shipping/components/UnassignDialog";
import {
getShippingMethodChannelVariables,
getUpdateShippingWeightRateVariables
} from "@saleor/shipping/handlers";
import {
+ useShippingMethodChannelListingUpdate,
useShippingMethodZipCodeRangeAssign,
useShippingMethodZipCodeRangeUnassign,
+ useShippingPriceExcludeProduct,
+ useShippingPriceRemoveProductsFromExclude,
useShippingRateDelete,
useShippingRateUpdate
} from "@saleor/shipping/mutations";
-import { useShippingMethodChannelListingUpdate } from "@saleor/shipping/mutations";
import { useShippingZone } from "@saleor/shipping/queries";
import {
ShippingRateUrlDialog,
@@ -37,7 +49,7 @@ import {
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import React from "react";
-import { useIntl } from "react-intl";
+import { FormattedMessage, useIntl } from "react-intl";
export interface WeightRatesUpdateProps {
id: string;
@@ -53,10 +65,13 @@ export const WeightRatesUpdate: React.FC = ({
const navigate = useNavigator();
const notify = useNotifier();
const intl = useIntl();
+ const paginate = usePaginator();
- const { data, loading } = useShippingZone({
+ const paginationState = createPaginationState(PAGINATE_BY, params);
+
+ const { data, loading, refetch } = useShippingZone({
displayLoader: true,
- variables: { id }
+ variables: { id, ...paginationState }
});
const [openModal, closeModal] = createDialogActionHandlers<
@@ -64,15 +79,55 @@ export const WeightRatesUpdate: React.FC = ({
ShippingRateUrlQueryParams
>(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(
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 [
updateShippingMethodChannelListing,
updateShippingMethodChannelListingOpts
] = 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(
rate?.channelListings
);
@@ -166,6 +221,18 @@ export const WeightRatesUpdate: React.FC = ({
}
};
+ 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));
return (
@@ -201,13 +268,35 @@ export const WeightRatesUpdate: React.FC = ({
open={params.action === "remove"}
name={rate?.name}
/>
+ handleProductUnassign(listElements)}
+ />
+ edge.node)
+ .filter(suggestedProduct => suggestedProduct.id)}
+ onClose={closeModal}
+ onFetch={productsSearch}
+ onFetchMore={loadMore}
+ onSubmit={handleProductAssign}
+ />
= ({
}
openChannelsModal={handleChannelsModalOpen}
onChannelsChange={setCurrentChannels}
+ onProductUnassign={handleProductUnassign}
+ onProductAssign={() => openModal("assign-product")}
variant={ShippingMethodTypeEnum.WEIGHT}
+ isChecked={isSelected}
+ selected={listElements.length}
+ toggle={toggle}
+ toggleAll={toggleAll}
+ onNextPage={loadNextPage}
+ onPreviousPage={loadPreviousPage}
+ pageInfo={pageInfo}
+ toolbar={
+
+ }
onZipCodeAssign={() => openModal("add-range")}
onZipCodeUnassign={id =>
openModal("remove-range", {
diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap
index a37ba2ea1..897a71360 100644
--- a/src/storybook/__snapshots__/Stories.test.ts.snap
+++ b/src/storybook/__snapshots__/Stories.test.ts.snap
@@ -13873,6 +13873,2835 @@ exports[`Storyshots Shipping / Pricing Card loading 1`] = `
`;
+exports[`Storyshots Shipping / ShippingMethodProducts default 1`] = `
+
+
+
+
+ Excluded Products
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ Selected 1 items
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+`;
+
+exports[`Storyshots Shipping / ShippingMethodProductsAddDialog default 1`] = `
+
+`;
+
+exports[`Storyshots Shipping / ShippingZoneRatesCreatePage page create price 1`] = `
+
+`;
+
+exports[`Storyshots Shipping / ShippingZoneRatesCreatePage page create weight 1`] = `
+
+`;
+
+exports[`Storyshots Shipping / ShippingZoneRatesCreatePage page loading 1`] = `
+
+`;
+
+exports[`Storyshots Shipping / UnassignDialog default 1`] = `
+
+`;
+
exports[`Storyshots SiteSettings / Add key dialog default 1`] = `
-
-
-
+
+ 1 Field
+
+
+
+
+
+
+
+
-
-
-
+ There is no private metadata created for this element.
+
+
+ Use the button below to add new metadata field
+
+
+
+
-
-
-
+
+ 1 Field
+
+
+
+
+
+
+
+
-
-
-
+ There is no private metadata created for this element.
+
+
+ Use the button below to add new metadata field
+
+
+
+
-
-
-
+
+ 1 Field
+
+
+
+
+
+
+
+
-
-
-
+ There is no private metadata created for this element.
+
+
+ Use the button below to add new metadata field
+
+
+
+
-
-
-
+
+ 1 Field
+
+
+
+
+
+
+
+
-
-
-
+ There is no private metadata created for this element.
+
+
+ Use the button below to add new metadata field
+
+
+
+
-
-
-
+
+ 1 Field
+
+
+
+
+
+
+
+
-
-
-
+ There is no private metadata created for this element.
+
+
+ Use the button below to add new metadata field
+
+
+
+
-
-
-
+
+ 1 Field
+
+
+
+
+
+
+
+
-
-
-
+ There is no private metadata created for this element.
+
+
+ Use the button below to add new metadata field
+
+
+
+
+
+
+
+
+
+ Excluded Products
+
+
+
+
+
+
+
+
@@ -196349,7 +200715,7 @@ exports[`Storyshots Views / Shipping / Shipping rate create weight rate 1`] = `
+
+
+
+
+
+ Excluded Products
+
+
+
+
+
+
+
+
@@ -197104,7 +201771,12 @@ exports[`Storyshots Views / Shipping / Shipping rate loading 1`] = `
-
-
-
-
-
-
-
-
- Available at 1 out of 3 channels
-
-
-
-
-
-
-
-
-
-