Add allocation strategies with sortable warehouses (#2258)

* Add allocation strategy options in channel view

* Update schema with channel allocation strategy

* Reorder channel warehouses after channel saving

* Refactor and clean code of allocation strategy options

* Update schema with allocation strategy

* Trigger CI

* Update allocation starategy options UI

* Update allocation strategy messages

* Trigger CI

* Fix shipping zones and warehouses cards style

* Fix message

* Fix snapshots

Co-authored-by: Michał Droń <dron.official@yahoo.com>
This commit is contained in:
Dawid 2022-08-29 12:35:55 +01:00 committed by GitHub
parent 9dc3bf4949
commit e610aefcfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 4003 additions and 1368 deletions

View file

@ -2478,6 +2478,29 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "AllocationStrategyEnum",
"description": "Determine the allocation strategy for the channel.\n\n PRIORITIZE_SORTING_ORDER - the allocation is prioritized by the warehouses' sort\n order within the channel\n\n PRIORITIZE_HIGH_STOCK - the allocation is prioritized by the highest available\n quantity in stocks\n ",
"fields": null,
"inputFields": null,
"interfaces": null,
"enumValues": [
{
"name": "PRIORITIZE_SORTING_ORDER",
"description": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "PRIORITIZE_HIGH_STOCK",
"description": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "App",
@ -12182,6 +12205,22 @@
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "stockSettings",
"description": "Define the stock setting for this channel.\n\nAdded in Saleor 3.7.\n\nNote: this API is currently in Feature Preview and can be subject to changes at later point.\n\nRequires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER.",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "StockSettings",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
@ -12355,6 +12394,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "stockSettings",
"description": "The channel stock settings.\n\nAdded in Saleor 3.7.\n\nNote: this API is currently in Feature Preview and can be subject to changes at later point.",
"type": {
"kind": "INPUT_OBJECT",
"name": "StockSettingsInput",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "addShippingZones",
"description": "List of shipping zones to assign to the channel.",
@ -12943,6 +12994,53 @@
],
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ChannelReorderWarehouses",
"description": "Reorder the warehouses of a channel.\n\nAdded in Saleor 3.7.\n\nNote: this API is currently in Feature Preview and can be subject to changes at later point. \n\nRequires one of the following permissions: MANAGE_CHANNELS.",
"fields": [
{
"name": "channel",
"description": "Channel within the warehouses are reordered.",
"args": [],
"type": {
"kind": "OBJECT",
"name": "Channel",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "ChannelError",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "ChannelStatusChanged",
@ -13109,6 +13207,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "stockSettings",
"description": "The channel stock settings.\n\nAdded in Saleor 3.7.\n\nNote: this API is currently in Feature Preview and can be subject to changes at later point.",
"type": {
"kind": "INPUT_OBJECT",
"name": "StockSettingsInput",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "addShippingZones",
"description": "List of shipping zones to assign to the channel.",
@ -51670,6 +51780,59 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "channelReorderWarehouses",
"description": "Reorder the warehouses of a channel.\n\nAdded in Saleor 3.7.\n\nNote: this API is currently in Feature Preview and can be subject to changes at later point. \n\nRequires one of the following permissions: MANAGE_CHANNELS.",
"args": [
{
"name": "channelId",
"description": "ID of a channel.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "moves",
"description": "The list of reordering operations for given channel warehouses.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "ReorderInput",
"ofType": null
}
}
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"type": {
"kind": "OBJECT",
"name": "ChannelReorderWarehouses",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "attributeCreate",
"description": "Creates an attribute.",
@ -59493,6 +59656,18 @@
"defaultValue": "false",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "trackingNumber",
"description": "Fulfillment tracking number.\n\nAdded in Saleor 3.6.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
@ -76932,6 +77107,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Variant name.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "trackInventory",
"description": "Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item.",
@ -77554,6 +77741,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Variant name.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "trackInventory",
"description": "Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item.",
@ -78019,6 +78218,18 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "name",
"description": "Variant name.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "trackInventory",
"description": "Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item.",
@ -93712,6 +93923,60 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "StockSettings",
"description": "Represents the channel stock settings.\n\nAdded in Saleor 3.7.\n\nNote: this API is currently in Feature Preview and can be subject to changes at later point.",
"fields": [
{
"name": "allocationStrategy",
"description": "Allocation strategy options. Strategy defines the preference of warehouses for allocations and reservations.",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "AllocationStrategyEnum",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "INPUT_OBJECT",
"name": "StockSettingsInput",
"description": null,
"fields": null,
"inputFields": [
{
"name": "allocationStrategy",
"description": "Allocation strategy options. Strategy defines the preference of warehouses for allocations and reservations.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "ENUM",
"name": "AllocationStrategyEnum",
"ofType": null
}
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "ENUM",
"name": "StorePaymentMethodEnum",
@ -96905,6 +97170,9 @@
"description": "List of all user's addresses.",
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
@ -96916,6 +97184,7 @@
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
@ -102864,15 +103133,15 @@
},
{
"name": "secretKey",
"description": "Used to create a hash signature with each payload.\n\nIf not set, since Saleor 3.5, your payload will be signed using private key used also to sign JWT tokens.",
"description": "Used to create a hash signature for each payload.",
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
"isDeprecated": true,
"deprecationReason": "This field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS."
},
{
"name": "subscriptionQuery",
@ -103085,7 +103354,7 @@
},
{
"name": "secretKey",
"description": "The secret key used to create a hash signature with each payload.",
"description": "The secret key used to create a hash signature with each payload.\n\nDEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.",
"type": {
"kind": "SCALAR",
"name": "String",
@ -105465,7 +105734,7 @@
},
{
"name": "secretKey",
"description": "Use to create a hash signature with each payload.",
"description": "Use to create a hash signature with each payload.\n\nDEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.",
"type": {
"kind": "SCALAR",
"name": "String",

View file

@ -166,6 +166,10 @@
"context": "header, allocated product quantity",
"string": "Allocated"
},
"/DzBc6": {
"context": "section description",
"string": "Strategy defines the preference of warehouses for stock allocations and reservations."
},
"/JENWS": {
"string": "Reduced Tax Rates"
},
@ -735,6 +739,10 @@
"context": "notification",
"string": "Removed pages"
},
"423QsF": {
"context": "option title",
"string": "Prioritize warehouses with highest stock"
},
"43AOvZ": {
"context": "alert group message",
"string": "You will not be able to finalize this draft because:"
@ -2104,6 +2112,10 @@
"context": "selected customer gift card is sent to subtitle",
"string": "Selected customer will be sent the generated gift card code. Someone else can redeem the gift card code. Gift card will be assigned to account which redeemed the code."
},
"FSOOH7": {
"context": "option title",
"string": "Prioritize warehouses by sorting order"
},
"FSinkL": {
"context": "variant stock status",
"string": "Available inventory at:"
@ -2112,6 +2124,10 @@
"context": "ExitFormPrompt title",
"string": "You have unsaved changes"
},
"FYfoiF": {
"context": "section name",
"string": "Allocation strategy"
},
"Fbr4Vp": {
"context": "dialog header",
"string": "Permissions"
@ -2207,6 +2223,10 @@
"context": "tab name",
"string": "All Collections"
},
"G5NKx6": {
"context": "tooltip",
"string": "Checkout reservation time threshold is enabled in settings."
},
"G7mu0y": {
"string": "The GraphQL API is beta quality. It is not fully optimized and some mutations or queries may be missing."
},
@ -2388,6 +2408,10 @@
"HMD+ib": {
"string": "Last order"
},
"HN1Gvw": {
"context": "option description",
"string": "Allocate order-line to a warehouse with the most stock. If not enough stock is available in a single warehouse, the remaining quantity is allocated in the next warehouse with the most stock and repeated if necessary."
},
"HP6m+q": {
"string": "Attributes and Product Types"
},
@ -2576,10 +2600,6 @@
"context": "change warehouse dialog description",
"string": "Choose warehouse from which you want to fulfill {productName}"
},
"ImTelT": {
"context": "card subtitle",
"string": "Select warehouses that will be used in this channel. You can assign warehouses to multiple channels."
},
"IoCMjg": {
"context": "no collections",
"string": "No collections found"
@ -4679,6 +4699,10 @@
"context": "imperial unit system",
"string": "Imperial"
},
"YiC3cn": {
"context": "option description",
"string": "Allocate stock in the first warehouse in the list assigned to this channel. If stock is insufficient, the remaining quantity is allocated in the next warehouse on the list and repeated if necessary."
},
"YicEbK": {
"string": "Search Atrtibuttes"
},
@ -5750,6 +5774,10 @@
"context": "voucher country range",
"string": "Countries"
},
"icb1fc": {
"context": "tooltip",
"string": "Stock allocations occur when:"
},
"icz/jb": {
"context": "customer",
"string": "Join Date"
@ -6616,6 +6644,10 @@
"context": "key-value field input",
"string": "Key"
},
"q5Lfp4": {
"context": "tooltip",
"string": "Order contains products that have \"Track inventory\" enabled."
},
"q8ep2I": {
"context": "dialog header",
"string": "Delete Customers"
@ -7253,6 +7285,10 @@
"v1pNHW": {
"string": "Attribute Class"
},
"v2+u4c": {
"context": "card subtitle",
"string": "Assign and sort warehouses that will be used in this channel (warehouses can be assigned in multiple channels)."
},
"v3WWK+": {
"string": "Status is invalid"
},

View file

@ -411,6 +411,21 @@ type Allocation implements Node {
warehouse: Warehouse!
}
"""
Determine the allocation strategy for the channel.
PRIORITIZE_SORTING_ORDER - the allocation is prioritized by the warehouses' sort
order within the channel
PRIORITIZE_HIGH_STOCK - the allocation is prioritized by the highest available
quantity in stocks
"""
enum AllocationStrategyEnum {
PRIORITIZE_SORTING_ORDER
PRIORITIZE_HIGH_STOCK
}
"""Represents app data."""
type App implements Node & ObjectWithMetadata {
id: ID!
@ -2540,6 +2555,17 @@ type Channel implements Node {
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
availableShippingMethodsPerCountry(countries: [CountryCode!]): [ShippingMethodsPerCountry!]
"""
Define the stock setting for this channel.
Added in Saleor 3.7.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER.
"""
stockSettings: StockSettings!
}
"""
@ -2569,6 +2595,15 @@ input ChannelCreateInput {
"""isActive flag."""
isActive: Boolean
"""
The channel stock settings.
Added in Saleor 3.7.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
stockSettings: StockSettingsInput
"""List of shipping zones to assign to the channel."""
addShippingZones: [ID!]
@ -2708,6 +2743,21 @@ enum ChannelErrorCode {
DUPLICATED_INPUT_ITEM
}
"""
Reorder the warehouses of a channel.
Added in Saleor 3.7.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
Requires one of the following permissions: MANAGE_CHANNELS.
"""
type ChannelReorderWarehouses {
"""Channel within the warehouses are reordered."""
channel: Channel
errors: [ChannelError!]!
}
"""
Event sent when channel status has changed.
@ -2747,6 +2797,15 @@ input ChannelUpdateInput {
"""isActive flag."""
isActive: Boolean
"""
The channel stock settings.
Added in Saleor 3.7.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
stockSettings: StockSettingsInput
"""List of shipping zones to assign to the channel."""
addShippingZones: [ID!]
@ -11485,6 +11544,23 @@ type Mutation {
id: ID!
): ChannelDeactivate
"""
Reorder the warehouses of a channel.
Added in Saleor 3.7.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
Requires one of the following permissions: MANAGE_CHANNELS.
"""
channelReorderWarehouses(
"""ID of a channel."""
channelId: ID!
"""The list of reordering operations for given channel warehouses."""
moves: [ReorderInput!]!
): ChannelReorderWarehouses
"""Creates an attribute."""
attributeCreate(
"""Fields required to create an attribute."""
@ -13182,6 +13258,13 @@ input OrderFulfillInput {
"""If true, then allow proceed fulfillment when stock is exceeded."""
allowStockToBeExceeded: Boolean = false
"""
Fulfillment tracking number.
Added in Saleor 3.6.
"""
trackingNumber: String
}
input OrderFulfillLineInput {
@ -17016,6 +17099,9 @@ input ProductVariantBulkCreateInput {
"""Stock keeping unit."""
sku: String
"""Variant name."""
name: String
"""
Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item.
"""
@ -17154,6 +17240,9 @@ input ProductVariantCreateInput {
"""Stock keeping unit."""
sku: String
"""Variant name."""
name: String
"""
Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item.
"""
@ -17267,6 +17356,9 @@ input ProductVariantInput {
"""Stock keeping unit."""
sku: String
"""Variant name."""
name: String
"""
Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item.
"""
@ -21050,6 +21142,27 @@ input StockInput {
quantity: Int!
}
"""
Represents the channel stock settings.
Added in Saleor 3.7.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
type StockSettings {
"""
Allocation strategy options. Strategy defines the preference of warehouses for allocations and reservations.
"""
allocationStrategy: AllocationStrategyEnum!
}
input StockSettingsInput {
"""
Allocation strategy options. Strategy defines the preference of warehouses for allocations and reservations.
"""
allocationStrategy: AllocationStrategyEnum!
}
"""Enum representing the type of a payment storage in a gateway."""
enum StorePaymentMethodEnum {
"""
@ -21753,7 +21866,7 @@ type User implements Node & ObjectWithMetadata {
isActive: Boolean!
"""List of all user's addresses."""
addresses: [Address!]
addresses: [Address!]!
"""Returns the last open checkout of this user."""
checkout: Checkout @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `checkoutTokens` field to fetch the user checkouts.")
@ -22981,12 +23094,8 @@ type Webhook implements Node {
"""Informs if webhook is activated."""
isActive: Boolean!
"""
Used to create a hash signature with each payload.
If not set, since Saleor 3.5, your payload will be signed using private key used also to sign JWT tokens.
"""
secretKey: String
"""Used to create a hash signature for each payload."""
secretKey: String @deprecated(reason: "This field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.")
"""Used to define payloads for specific events."""
subscriptionQuery: String
@ -23029,7 +23138,11 @@ input WebhookCreateInput {
"""Determine if webhook will be set active or not."""
isActive: Boolean
"""The secret key used to create a hash signature with each payload."""
"""
The secret key used to create a hash signature with each payload.
DEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.
"""
secretKey: String
"""
@ -23917,7 +24030,11 @@ input WebhookUpdateInput {
"""Determine if webhook will be set active or not."""
isActive: Boolean
"""Use to create a hash signature with each payload."""
"""
Use to create a hash signature with each payload.
DEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.
"""
secretKey: String
"""

View file

@ -1,10 +1,13 @@
import { Accordion, Divider, Typography } from "@material-ui/core";
import Skeleton from "@saleor/components/Skeleton";
import { ReorderEvent } from "@saleor/types";
import React from "react";
import { defineMessages, useIntl } from "react-intl";
import AssignmentListFooter from "./AssignmentListFooter";
import AssignmentListHeader from "./AssignmentListHeader";
import Item from "./Item";
import SortableContainer from "./SortableContainer";
import { useExpanderStyles, useStyles } from "./styles";
import { AssignmentListProps } from "./types";
@ -17,21 +20,61 @@ const messages = defineMessages({
});
const AssignmentList: React.FC<AssignmentListProps> = props => {
const { items, itemsName, totalCount = 0, removeItem } = props;
const {
items,
itemsName,
totalCount = 0,
loading,
removeItem,
reorderItem,
} = props;
const intl = useIntl();
const classes = useStyles();
const expanderClasses = useExpanderStyles();
const handleSortStart = () => {
document.body.classList.add(classes.grabbing);
};
const handleSortEnd = (event: ReorderEvent) => {
document.body.classList.remove(classes.grabbing);
reorderItem(event);
};
const hasMoreItemsToBeSelected = totalCount !== items.length;
return (
<Accordion classes={expanderClasses}>
<AssignmentListHeader assignCount={items.length} itemsName={itemsName} />
<AssignmentListHeader
assignCount={items.length}
itemsName={itemsName}
loading={loading}
/>
<Divider />
{items.map(item => (
<Item key={item.id} item={item} onDelete={removeItem} />
{loading ? (
<Skeleton className={classes.skeleton} />
) : (
<>
<SortableContainer
axis="xy"
lockAxis="xy"
useDragHandle
onSortStart={handleSortStart}
onSortEnd={handleSortEnd}
>
<div>
{items.map((item, itemIndex) => (
<Item
key={itemIndex}
index={itemIndex}
item={item}
onDelete={removeItem}
sortable={!!reorderItem}
/>
))}
</div>
</SortableContainer>
{hasMoreItemsToBeSelected ? (
<AssignmentListFooter {...props} />
) : (
@ -45,6 +88,8 @@ const AssignmentList: React.FC<AssignmentListProps> = props => {
})}
</Typography>
)}
</>
)}
</Accordion>
);
};

View file

@ -1,5 +1,6 @@
import { AccordionSummary, Typography } from "@material-ui/core";
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
import Skeleton from "@saleor/components/Skeleton";
import IconChevronDown from "@saleor/icons/ChevronDown";
import React from "react";
@ -8,20 +9,26 @@ import { useHeaderStyles } from "./styles";
interface AssignmentListHeaderProps {
assignCount: number;
itemsName: string;
loading: boolean;
}
const AssignmentListHeader: React.FC<AssignmentListHeaderProps> = ({
assignCount,
itemsName,
loading,
}) => {
const classes = useHeaderStyles();
return (
<div className={classes.container}>
<AccordionSummary expandIcon={<IconChevronDown />} classes={classes}>
{loading ? (
<Skeleton className={classes.skeleton} />
) : (
<Typography variant="subtitle2" color="textSecondary">
{`${assignCount} ${itemsName.toLowerCase()}`}
</Typography>
)}
</AccordionSummary>
<HorizontalSpacer spacing={1.5} />
</div>

View file

@ -1,28 +1,41 @@
import { Divider, Typography } from "@material-ui/core";
import DeletableItem from "@saleor/components/DeletableItem";
import React from "react";
import { SortableElement, SortableElementProps } from "react-sortable-hoc";
import SortableHandle from "./SortableHandle";
import { useStyles } from "./styles";
import { AssignItem } from "./types";
interface ItemProps {
interface ItemProps extends SortableElementProps {
item: AssignItem;
sortable?: boolean;
onDelete: (id: string) => void;
}
const Item: React.FC<ItemProps> = ({ item, onDelete }) => {
const Item = SortableElement(
({ item, sortable = false, onDelete }: ItemProps) => {
const { id, name } = item;
const classes = useStyles();
return (
<>
<div className={classes.container}>
<div className={classes.containerContent}>
{sortable && (
<SortableHandle
className={classes.sortableHandle}
data-test-id="button-drag-handle"
/>
)}
<Typography>{name}</Typography>
</div>
<DeletableItem id={id} onDelete={onDelete} />
</div>
<Divider />
</>
);
};
},
);
export default Item;

View file

@ -0,0 +1,14 @@
import {
SortableContainer as SortableContainerHoc,
SortableContainerProps as SortableContainerHocProps,
} from "react-sortable-hoc";
interface SortableContainerProps extends SortableContainerHocProps {
children: React.ReactElement;
}
const SortableContainer = SortableContainerHoc(
({ children }: SortableContainerProps) => children,
);
export default SortableContainer;

View file

@ -0,0 +1,32 @@
import { DragIcon, makeStyles } from "@saleor/macaw-ui";
import classNames from "classnames";
import React from "react";
import { SortableHandle as SortableHandleHoc } from "react-sortable-hoc";
const useStyles = makeStyles(
{
drag: {
cursor: "grab",
},
},
{ name: "SortableHandle" },
);
interface SortableHandleProps {
className?: string;
}
const SortableHandle = SortableHandleHoc((props: SortableHandleProps) => {
const { className, ...restProps } = props;
const classes = useStyles(props);
return (
<DragIcon
className={classNames(classes.drag, className)}
tabIndex={0}
{...restProps}
/>
);
});
export default SortableHandle;

View file

@ -28,6 +28,10 @@ export const useHeaderStyles = makeStyles(
flexDirection: "row",
alignItems: "center",
},
skeleton: {
width: "100%",
marginRight: theme.spacing(4),
},
// empty expanded needed for mui to use root styles
expanded: {},
root: {
@ -61,6 +65,17 @@ export const useStyles = makeStyles(
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
background: theme.palette.background.paper,
},
containerContent: {
display: "flex",
overflow: "auto",
},
sortableHandle: {
marginRight: theme.spacing(1),
},
grabbing: {
cursor: "grabbing",
},
root: {
paddingRight: theme.spacing(1),
@ -68,6 +83,9 @@ export const useStyles = makeStyles(
infoMessage: {
padding: theme.spacing(3),
},
skeleton: {
margin: theme.spacing(4, 0),
},
}),
{ name: "AssignmentList" },
);

View file

@ -1,4 +1,4 @@
import { FetchMoreProps } from "@saleor/types";
import { FetchMoreProps, ReorderAction } from "@saleor/types";
export interface AssignItem {
id: string;
@ -13,7 +13,9 @@ export interface AssignmentListProps {
totalCount: number;
inputName: string;
dataTestId: string;
loading: boolean;
addItem: (id: string) => void;
removeItem: (id: string) => void;
reorderItem?: ReorderAction;
searchItems: (searchPhrase: string) => void;
}

View file

@ -0,0 +1,106 @@
import { Card, CardContent, Typography } from "@material-ui/core";
import HelpOutline from "@material-ui/icons/HelpOutline";
import CardTitle from "@saleor/components/CardTitle";
import PreviewPill from "@saleor/components/PreviewPill";
import RadioGroupField from "@saleor/components/RadioGroupField";
import { AllocationStrategyEnum, StockSettingsInput } from "@saleor/graphql";
import { Tooltip } from "@saleor/macaw-ui";
import React from "react";
import { FormattedMessage } from "react-intl";
import { messages } from "./messages";
import { useStyles } from "./styles";
const strategyOptions = [
{
title: messages.prioritizeBySortOrder,
subtitle: messages.prioritizeBySortOrderDescription,
type: AllocationStrategyEnum.PRIORITIZE_SORTING_ORDER,
},
{
title: messages.prioritizeByHighestStock,
subtitle: messages.prioritizeByHighestStockDescription,
type: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
];
interface ChannelAllocationStrategyProps {
data?: StockSettingsInput;
disabled: boolean;
onChange: (event: React.ChangeEvent<any>) => void;
}
const ChannelAllocationStrategy: React.FC<ChannelAllocationStrategyProps> = ({
data,
disabled,
onChange,
}) => {
const classes = useStyles();
return (
<Card>
<CardTitle
title={
<div className={classes.preview}>
<FormattedMessage {...messages.allocationStrategy} />
<PreviewPill />
</div>
}
/>
<CardContent>
<RadioGroupField
label={
<Typography>
<FormattedMessage {...messages.allocationStrategyDescription} />
<Tooltip
title={
<>
<FormattedMessage {...messages.allocaationMayOccur} />
<ul>
<li>
<FormattedMessage
{...messages.allocaationMayOccurWithTrackInventory}
/>
</li>
<li>
<FormattedMessage
{...messages.allocaationMayOccurWithReservationTime}
/>
</li>
</ul>
</>
}
>
<HelpOutline className={classes.tooltipIcon} />
</Tooltip>
</Typography>
}
choices={strategyOptions.map(option => ({
label: (
<div
className={classes.option}
data-test-id={`channel-allocation-strategy-option-${option.type}`}
>
<Typography variant="body1">
<FormattedMessage {...option.title} />
</Typography>
{option.subtitle && (
<Typography color="textSecondary" variant="caption">
<FormattedMessage {...option.subtitle} />
</Typography>
)}
</div>
),
value: option.type,
}))}
disabled={disabled}
name="allocationStrategy"
value={data?.allocationStrategy}
onChange={onChange}
/>
</CardContent>
</Card>
);
};
ChannelAllocationStrategy.displayName = "ChannelAllocationStrategy";
export default ChannelAllocationStrategy;

View file

@ -0,0 +1,2 @@
export * from "./ChannelAllocationStrategy";
export { default } from "./ChannelAllocationStrategy";

View file

@ -0,0 +1,54 @@
import { defineMessages } from "react-intl";
export const messages = defineMessages({
allocationStrategy: {
defaultMessage: "Allocation strategy",
id: "FYfoiF",
description: "section name",
},
allocationStrategyDescription: {
defaultMessage:
"Strategy defines the preference of warehouses for stock allocations and reservations.",
id: "/DzBc6",
description: "section description",
},
prioritizeBySortOrder: {
defaultMessage: "Prioritize warehouses by sorting order",
id: "FSOOH7",
description: "option title",
},
prioritizeBySortOrderDescription: {
defaultMessage:
"Allocate stock in the first warehouse in the list assigned to this channel. If stock is insufficient, the remaining quantity is allocated in the next warehouse on the list and repeated if necessary.",
id: "YiC3cn",
description: "option description",
},
prioritizeByHighestStock: {
defaultMessage: "Prioritize warehouses with highest stock",
id: "423QsF",
description: "option title",
},
prioritizeByHighestStockDescription: {
defaultMessage:
"Allocate order-line to a warehouse with the most stock. If not enough stock is available in a single warehouse, the remaining quantity is allocated in the next warehouse with the most stock and repeated if necessary.",
id: "HN1Gvw",
description: "option description",
},
allocaationMayOccur: {
defaultMessage: "Stock allocations occur when:",
description: "tooltip",
id: "icb1fc",
},
allocaationMayOccurWithTrackInventory: {
defaultMessage:
'Order contains products that have "Track inventory" enabled.',
description: "tooltip",
id: "q5Lfp4",
},
allocaationMayOccurWithReservationTime: {
defaultMessage:
"Checkout reservation time threshold is enabled in settings.",
description: "tooltip",
id: "G5NKx6",
},
});

View file

@ -0,0 +1,26 @@
import { makeStyles } from "@saleor/macaw-ui";
export const useStyles = makeStyles(
theme => ({
option: {
marginTop: theme.spacing(-0.25),
marginBottom: theme.spacing(),
},
tooltipIcon: {
fill: "#28234A",
fillOpacity: 0.6,
"&:hover": {
fillOpacity: 1,
},
position: "absolute",
padding: theme.spacing(0.25),
},
preview: {
display: "flex",
gap: theme.spacing(1),
flexWrap: "wrap",
alignItems: "center",
},
}),
{ name: "ChannelAllocationStrategy" },
);

View file

@ -1,5 +1,5 @@
import { countries } from "@saleor/fixtures";
import { CountryCode } from "@saleor/graphql";
import { AllocationStrategyEnum, CountryCode } from "@saleor/graphql";
import Decorator from "@saleor/storybook/Decorator";
import { storiesOf } from "@storybook/react";
import React from "react";
@ -17,6 +17,31 @@ const props: ChannelFormProps = {
name: "Test",
slug: "test",
defaultCountry: CountryCode.PL,
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
warehousesToDisplay: [
{
__typename: "Warehouse",
id: "1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "2",
name: "Warehouse 2",
},
],
shippingZonesToDisplay: [
{
__typename: "ShippingZone",
id: "1",
name: "Shipping Zone 1",
},
{
__typename: "ShippingZone",
id: "2",
name: "Shipping Zone 2",
},
],
},
disabled: false,
errors: [],

View file

@ -5,13 +5,21 @@ import {
TextField,
Typography,
} from "@material-ui/core";
import {
ChannelShippingZones,
ChannelWarehouses,
} from "@saleor/channels/pages/ChannelDetailsPage/types";
import CardSpacer from "@saleor/components/CardSpacer";
import CardTitle from "@saleor/components/CardTitle";
import FormSpacer from "@saleor/components/FormSpacer";
import SingleAutocompleteSelectField, {
SingleAutocompleteChoiceType,
} from "@saleor/components/SingleAutocompleteSelectField";
import { ChannelErrorFragment, CountryCode } from "@saleor/graphql";
import {
ChannelErrorFragment,
CountryCode,
StockSettingsInput,
} from "@saleor/graphql";
import useClipboard from "@saleor/hooks/useClipboard";
import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
import { commonMessages } from "@saleor/intl";
@ -23,7 +31,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import { useStyles } from "../styles";
import { ExtendedFormHelperTextProps } from "./types";
export interface FormData {
export interface FormData extends StockSettingsInput {
name: string;
currencyCode: string;
slug: string;
@ -31,6 +39,8 @@ export interface FormData {
shippingZonesIdsToRemove: string[];
warehousesIdsToAdd: string[];
warehousesIdsToRemove: string[];
shippingZonesToDisplay: ChannelShippingZones;
warehousesToDisplay: ChannelWarehouses;
defaultCountry: CountryCode;
}

View file

@ -31,6 +31,7 @@ const baseProps: ShippingZonesProps = {
shippingZones: [],
shippingZonesChoices: shippingZones as ChannelShippingZones,
totalCount: 10,
loading: false,
};
storiesOf("Shipping zones", module)
@ -41,4 +42,5 @@ storiesOf("Shipping zones", module)
{...baseProps}
shippingZones={shippingZones as ChannelShippingZones}
/>
));
))
.add("loading", () => <ShippingZones {...baseProps} loading={true} />);

View file

@ -5,23 +5,16 @@ import { SearchShippingZonesQuery } from "@saleor/graphql";
import { sectionNames } from "@saleor/intl";
import { FetchMoreProps, RelayToFlat } from "@saleor/types";
import React from "react";
import { defineMessages, useIntl } from "react-intl";
import { useIntl } from "react-intl";
import AssignmentList from "../AssignmentList";
const messages = defineMessages({
subtitle: {
id: "Ic7Wln",
defaultMessage:
"Select shipping zones that will be supplied via this channel. You can assign shipping zones to multiple channels.",
description: "card subtitle",
},
});
import { messages } from "./messages";
export interface ShippingZonesProps {
addShippingZone: (id: string) => void;
removeShippingZone: (id: string) => void;
searchShippingZones: (searchPhrase: string) => void;
loading: boolean;
totalCount: number;
fetchMoreShippingZones: FetchMoreProps;
shippingZones: ChannelShippingZones;
@ -33,6 +26,7 @@ const ShippingZones: React.FC<ShippingZonesProps> = props => {
addShippingZone,
removeShippingZone,
searchShippingZones,
loading,
totalCount,
fetchMoreShippingZones,
shippingZones,
@ -48,6 +42,7 @@ const ShippingZones: React.FC<ShippingZonesProps> = props => {
<Typography>{intl.formatMessage(messages.subtitle)}</Typography>
</CardContent>
<AssignmentList
loading={loading}
items={shippingZones}
itemsChoices={shippingZonesChoices}
addItem={addShippingZone}

View file

@ -0,0 +1,10 @@
import { defineMessages } from "react-intl";
export const messages = defineMessages({
subtitle: {
id: "Ic7Wln",
defaultMessage:
"Select shipping zones that will be supplied via this channel. You can assign shipping zones to multiple channels.",
description: "card subtitle",
},
});

View file

@ -1,19 +0,0 @@
import { makeStyles } from "@saleor/macaw-ui";
const useStyles = makeStyles(
theme => ({
container: {
padding: theme.spacing(1, 0),
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
root: {
paddingRight: theme.spacing(1),
},
}),
{ name: "ShippingZones" },
);
export default useStyles;

View file

@ -28,9 +28,11 @@ const baseProps: WarehousesProps = {
onFetchMore: () => undefined,
totalCount: 0,
},
reorderWarehouses: () => undefined,
warehouses: [],
warehousesChoices: warehouses as ChannelWarehouses,
totalCount: 10,
loading: false,
};
storiesOf("Warehouses", module)
@ -38,4 +40,5 @@ storiesOf("Warehouses", module)
.add("with no options selected", () => <Warehouses {...baseProps} />)
.add("with options selected", () => (
<Warehouses {...baseProps} warehouses={warehouses as ChannelWarehouses} />
));
))
.add("loading", () => <Warehouses {...baseProps} loading={true} />);

View file

@ -3,25 +3,19 @@ import { ChannelWarehouses } from "@saleor/channels/pages/ChannelDetailsPage/typ
import CardTitle from "@saleor/components/CardTitle";
import { SearchWarehousesQuery } from "@saleor/graphql";
import { sectionNames } from "@saleor/intl";
import { FetchMoreProps, RelayToFlat } from "@saleor/types";
import { FetchMoreProps, RelayToFlat, ReorderAction } from "@saleor/types";
import React from "react";
import { defineMessages, useIntl } from "react-intl";
import { useIntl } from "react-intl";
import AssignmentList from "../AssignmentList";
const messages = defineMessages({
subtitle: {
id: "ImTelT",
defaultMessage:
"Select warehouses that will be used in this channel. You can assign warehouses to multiple channels.",
description: "card subtitle",
},
});
import { messages } from "./messages";
export interface WarehousesProps {
addWarehouse: (id: string) => void;
removeWarehouse: (id: string) => void;
searchWarehouses: (searchPhrase: string) => void;
reorderWarehouses: ReorderAction;
loading: boolean;
totalCount: number;
fetchMoreWarehouses: FetchMoreProps;
warehouses: ChannelWarehouses;
@ -33,6 +27,8 @@ const Warehouses: React.FC<WarehousesProps> = props => {
addWarehouse,
removeWarehouse,
searchWarehouses,
reorderWarehouses,
loading,
totalCount,
fetchMoreWarehouses,
warehouses,
@ -48,11 +44,13 @@ const Warehouses: React.FC<WarehousesProps> = props => {
<Typography>{intl.formatMessage(messages.subtitle)}</Typography>
</CardContent>
<AssignmentList
loading={loading}
items={warehouses}
itemsChoices={warehousesChoices}
addItem={addWarehouse}
removeItem={removeWarehouse}
searchItems={searchWarehouses}
reorderItem={reorderWarehouses}
fetchMoreItems={fetchMoreWarehouses}
totalCount={totalCount}
dataTestId="warehouse"

View file

@ -0,0 +1,10 @@
import { defineMessages } from "react-intl";
export const messages = defineMessages({
subtitle: {
id: "v2+u4c",
defaultMessage:
"Assign and sort warehouses that will be used in this channel (warehouses can be assigned in multiple channels).",
description: "card subtitle",
},
});

View file

@ -1,19 +0,0 @@
import { makeStyles } from "@saleor/macaw-ui";
const useStyles = makeStyles(
theme => ({
container: {
padding: theme.spacing(1, 0),
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
root: {
paddingRight: theme.spacing(1),
},
}),
{ name: "Warehouses" },
);
export default useStyles;

View file

@ -1,4 +1,5 @@
import {
AllocationStrategyEnum,
ChannelDetailsFragment,
ChannelErrorCode,
ChannelErrorFragment,
@ -29,6 +30,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
{
__typename: "Channel",
@ -43,6 +60,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
{
__typename: "Channel",
@ -57,6 +90,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
{
__typename: "Channel",
@ -71,6 +120,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
{
__typename: "Channel",
@ -85,6 +150,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
{
__typename: "Channel",
@ -99,6 +180,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
{
__typename: "Channel",
@ -113,6 +210,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
},
];
@ -129,6 +242,22 @@ export const channel: ChannelDetailsFragment = {
country: "Poland",
__typename: "CountryDisplay",
},
stockSettings: {
__typename: "StockSettings",
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_HIGH_STOCK,
},
warehouses: [
{
__typename: "Warehouse",
id: "WH1",
name: "Warehouse 1",
},
{
__typename: "Warehouse",
id: "WH2",
name: "Warehouse 2",
},
],
};
type ProductChannelsWithPricing = ProductFragment["channelListings"][0] & {

View file

@ -61,3 +61,16 @@ export const channelDeactivateMutation = gql`
}
}
`;
export const ChannelReorderWarehousesMutation = gql`
mutation ChannelReorderWarehouses($channelId: ID!, $moves: [ReorderInput!]!) {
channelReorderWarehouses(channelId: $channelId, moves: $moves) {
channel {
...ChannelDetails
}
errors {
...ChannelError
}
}
}
`;

View file

@ -1,3 +1,4 @@
import ChannelAllocationStrategy from "@saleor/channels/components/ChannelAllocationStrategy";
import ShippingZones from "@saleor/channels/components/ShippingZones";
import Warehouses from "@saleor/channels/components/Warehouses";
import { channelsListUrl } from "@saleor/channels/urls";
@ -7,12 +8,14 @@ import Grid from "@saleor/components/Grid";
import Savebar from "@saleor/components/Savebar";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import {
AllocationStrategyEnum,
ChannelDetailsFragment,
ChannelErrorFragment,
CountryCode,
CountryFragment,
SearchShippingZonesQuery,
SearchWarehousesQuery,
StockSettingsInput,
} from "@saleor/graphql";
import { SearchData } from "@saleor/hooks/makeTopLevelSearch";
import { getParsedSearchData } from "@saleor/hooks/makeTopLevelSearch/utils";
@ -20,10 +23,6 @@ import { SubmitPromise } from "@saleor/hooks/useForm";
import useNavigator from "@saleor/hooks/useNavigator";
import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
import {
getById,
getByUnmatchingId,
} from "@saleor/orders/components/OrderReturnPage/utils";
import { FetchMoreProps, RelayToFlat } from "@saleor/types";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { mapCountriesToChoices } from "@saleor/utils/maps";
@ -31,8 +30,14 @@ import React, { useState } from "react";
import { ChannelForm, FormData } from "../../components/ChannelForm";
import { ChannelStatus } from "../../components/ChannelStatus/ChannelStatus";
import {
createShippingZoneAddHandler,
createShippingZoneRemoveHandler,
createWarehouseAddHandler,
createWarehouseRemoveHandler,
createWarehouseReorderHandler,
} from "./handlers";
import { ChannelShippingZones, ChannelWarehouses } from "./types";
import { getUpdatedIdsWithNewId, getUpdatedIdsWithoutNewId } from "./utils";
export interface ChannelDetailsPageProps<TErrors> {
channel?: ChannelDetailsFragment;
@ -87,16 +92,14 @@ const ChannelDetailsPage = function<TErrors>({
setSelectedCountryDisplayName,
] = useStateFromProps(channel?.defaultCountry.country || "");
const [shippingZonesToDisplay, setShippingZonesToDisplay] = useStateFromProps<
ChannelShippingZones
>(channelShippingZones);
const [warehousesToDisplay, setWarehousesToDisplay] = useStateFromProps<
ChannelWarehouses
>(channelWarehouses);
const countryChoices = mapCountriesToChoices(countries || []);
const { defaultCountry, ...formData } = channel || {};
const { defaultCountry, stockSettings, ...formData } =
channel || ({} as ChannelDetailsFragment);
const initialStockSettings: StockSettingsInput = {
allocationStrategy: AllocationStrategyEnum.PRIORITIZE_SORTING_ORDER,
...stockSettings,
};
const initialData: FormData = {
currencyCode: "",
name: "",
@ -107,15 +110,22 @@ const ChannelDetailsPage = function<TErrors>({
warehousesIdsToRemove: [],
defaultCountry: (defaultCountry?.code || "") as CountryCode,
...formData,
...initialStockSettings,
shippingZonesToDisplay: channelShippingZones,
warehousesToDisplay: channelWarehouses,
};
const getFilteredShippingZonesChoices = (): RelayToFlat<SearchShippingZonesQuery["search"]> =>
const getFilteredShippingZonesChoices = (
shippingZonesToDisplay: ChannelShippingZones,
): RelayToFlat<SearchShippingZonesQuery["search"]> =>
getParsedSearchData({ data: searchShippingZonesData }).filter(
({ id: searchedZoneId }) =>
!shippingZonesToDisplay.some(({ id }) => id === searchedZoneId),
);
const getFilteredWarehousesChoices = (): RelayToFlat<SearchWarehousesQuery["search"]> =>
const getFilteredWarehousesChoices = (
warehousesToDisplay: ChannelWarehouses,
): RelayToFlat<SearchWarehousesQuery["search"]> =>
getParsedSearchData({ data: searchWarehousesData }).filter(
({ id: searchedWarehouseId }) =>
!warehousesToDisplay.some(({ id }) => id === searchedWarehouseId),
@ -151,91 +161,30 @@ const ChannelDetailsPage = function<TErrors>({
countryChoices,
);
const addShippingZone = (zoneId: string) => {
triggerChange();
set({
...data,
shippingZonesIdsToRemove: getUpdatedIdsWithoutNewId(
data.shippingZonesIdsToRemove,
zoneId,
),
shippingZonesIdsToAdd: getUpdatedIdsWithNewId(
data.shippingZonesIdsToAdd,
zoneId,
),
});
setShippingZonesToDisplay([
...shippingZonesToDisplay,
getParsedSearchData({ data: searchShippingZonesData }).find(
getById(zoneId),
),
]);
};
const removeShippingZone = (zoneId: string) => {
triggerChange();
set({
...data,
shippingZonesIdsToAdd: getUpdatedIdsWithoutNewId(
data.shippingZonesIdsToAdd,
zoneId,
),
shippingZonesIdsToRemove: getUpdatedIdsWithNewId(
data.shippingZonesIdsToRemove,
zoneId,
),
});
setShippingZonesToDisplay(
shippingZonesToDisplay.filter(getByUnmatchingId(zoneId)),
const addShippingZone = createShippingZoneAddHandler(
data,
searchShippingZonesData,
set,
triggerChange,
);
};
const addWarehouse = (warehouseId: string) => {
triggerChange();
set({
...data,
warehousesIdsToRemove: getUpdatedIdsWithoutNewId(
data.warehousesIdsToRemove,
warehouseId,
),
warehousesIdsToAdd: getUpdatedIdsWithNewId(
data.warehousesIdsToAdd,
warehouseId,
),
});
setWarehousesToDisplay([
...warehousesToDisplay,
getParsedSearchData({ data: searchWarehousesData }).find(
getById(warehouseId),
),
]);
};
const removeWarehouse = (warehouseId: string) => {
triggerChange();
set({
...data,
warehousesIdsToAdd: getUpdatedIdsWithoutNewId(
data.warehousesIdsToAdd,
warehouseId,
),
warehousesIdsToRemove: getUpdatedIdsWithNewId(
data.warehousesIdsToRemove,
warehouseId,
),
});
setWarehousesToDisplay(
warehousesToDisplay.filter(getByUnmatchingId(warehouseId)),
const removeShippingZone = createShippingZoneRemoveHandler(
data,
set,
triggerChange,
);
};
const addWarehouse = createWarehouseAddHandler(
data,
searchWarehousesData,
set,
triggerChange,
);
const removeWarehouse = createWarehouseRemoveHandler(
data,
set,
triggerChange,
);
const reorderWarehouse = createWarehouseReorderHandler(data, set);
return (
<>
@ -266,23 +215,36 @@ const ChannelDetailsPage = function<TErrors>({
</>
)}
<ShippingZones
shippingZonesChoices={getFilteredShippingZonesChoices()}
shippingZones={shippingZonesToDisplay}
shippingZonesChoices={getFilteredShippingZonesChoices(
data.shippingZonesToDisplay,
)}
shippingZones={data.shippingZonesToDisplay}
addShippingZone={addShippingZone}
removeShippingZone={removeShippingZone}
searchShippingZones={searchShippingZones}
fetchMoreShippingZones={fetchMoreShippingZones}
totalCount={allShippingZonesCount}
loading={disabled}
/>
<CardSpacer />
<Warehouses
warehousesChoices={getFilteredWarehousesChoices()}
warehouses={warehousesToDisplay}
warehousesChoices={getFilteredWarehousesChoices(
data.warehousesToDisplay,
)}
warehouses={data.warehousesToDisplay}
addWarehouse={addWarehouse}
removeWarehouse={removeWarehouse}
searchWarehouses={searchWarehouses}
fetchMoreWarehouses={fetchMoreWarehouses}
totalCount={allWarehousesCount}
reorderWarehouses={reorderWarehouse}
loading={disabled}
/>
<CardSpacer />
<ChannelAllocationStrategy
data={data}
disabled={disabled}
onChange={change}
/>
</div>
</Grid>

View file

@ -0,0 +1,138 @@
import { FormData } from "@saleor/channels/components/ChannelForm";
import { SearchData } from "@saleor/hooks/makeTopLevelSearch";
import { getParsedSearchData } from "@saleor/hooks/makeTopLevelSearch/utils";
import {
getById,
getByUnmatchingId,
} from "@saleor/orders/components/OrderReturnPage/utils";
import { ReorderAction, ReorderEvent } from "@saleor/types";
import { move } from "@saleor/utils/lists";
import { getUpdatedIdsWithNewId, getUpdatedIdsWithoutNewId } from "./utils";
export function createShippingZoneAddHandler(
data: FormData,
searchShippingZonesData: SearchData,
set: (data: Partial<FormData>) => void,
triggerChange: () => void,
) {
return (zoneId: string) => {
triggerChange();
set({
...data,
shippingZonesIdsToRemove: getUpdatedIdsWithoutNewId(
data.shippingZonesIdsToRemove,
zoneId,
),
shippingZonesIdsToAdd: getUpdatedIdsWithNewId(
data.shippingZonesIdsToAdd,
zoneId,
),
shippingZonesToDisplay: [
...data.shippingZonesToDisplay,
getParsedSearchData({ data: searchShippingZonesData }).find(
getById(zoneId),
),
],
});
};
}
export function createShippingZoneRemoveHandler(
data: FormData,
set: (data: Partial<FormData>) => void,
triggerChange: () => void,
) {
return (zoneId: string) => {
triggerChange();
set({
...data,
shippingZonesIdsToAdd: getUpdatedIdsWithoutNewId(
data.shippingZonesIdsToAdd,
zoneId,
),
shippingZonesIdsToRemove: getUpdatedIdsWithNewId(
data.shippingZonesIdsToRemove,
zoneId,
),
shippingZonesToDisplay: data.shippingZonesToDisplay.filter(
getByUnmatchingId(zoneId),
),
});
};
}
export function createWarehouseAddHandler(
data: FormData,
searchWarehousesData: SearchData,
set: (data: Partial<FormData>) => void,
triggerChange: () => void,
) {
return (warehouseId: string) => {
triggerChange();
set({
...data,
warehousesIdsToRemove: getUpdatedIdsWithoutNewId(
data.warehousesIdsToRemove,
warehouseId,
),
warehousesIdsToAdd: getUpdatedIdsWithNewId(
data.warehousesIdsToAdd,
warehouseId,
),
warehousesToDisplay: [
...data.warehousesToDisplay,
getParsedSearchData({ data: searchWarehousesData }).find(
getById(warehouseId),
),
],
});
};
}
export function createWarehouseRemoveHandler(
data: FormData,
set: (data: Partial<FormData>) => void,
triggerChange: () => void,
) {
return (warehouseId: string) => {
triggerChange();
set({
...data,
warehousesIdsToAdd: getUpdatedIdsWithoutNewId(
data.warehousesIdsToAdd,
warehouseId,
),
warehousesIdsToRemove: getUpdatedIdsWithNewId(
data.warehousesIdsToRemove,
warehouseId,
),
warehousesToDisplay: data.warehousesToDisplay.filter(
getByUnmatchingId(warehouseId),
),
});
};
}
export function createWarehouseReorderHandler(
data: FormData,
set: (data: Partial<FormData>) => void,
): ReorderAction {
return ({ oldIndex, newIndex }: ReorderEvent) => {
const updatedWarehousesToDisplay = move(
data.warehousesToDisplay[oldIndex],
data.warehousesToDisplay,
(a, b) => a.id === b.id,
newIndex,
);
set({
...data,
warehousesToDisplay: updatedWarehousesToDisplay,
});
};
}

View file

@ -1,7 +1,4 @@
import {
ChannelShippingZonesQuery,
ChannelWarehousesQuery,
} from "@saleor/graphql";
import { ChannelShippingZonesQuery, WarehouseFragment } from "@saleor/graphql";
import { RelayToFlat } from "@saleor/types";
export type ChannelShippingZones = RelayToFlat<
@ -10,8 +7,6 @@ export type ChannelShippingZones = RelayToFlat<
export type ChannelShippingZone = ChannelShippingZones[0];
export type ChannelWarehouses = RelayToFlat<
ChannelWarehousesQuery["warehouses"]
>;
export type ChannelWarehouses = WarehouseFragment[];
export type ChannelWarehouse = ChannelWarehouses[0];

View file

@ -6,7 +6,9 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import {
ChannelCreateMutation,
ChannelErrorFragment,
useChannelCreateMutation,
useChannelReorderWarehousesMutation,
useShippingZonesCountQuery,
useWarehousesCountQuery,
} from "@saleor/graphql";
@ -19,12 +21,14 @@ import { sectionNames } from "@saleor/intl";
import { extractMutationErrors } from "@saleor/misc";
import useShippingZonesSearch from "@saleor/searches/useShippingZonesSearch";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import getChannelsErrorMessage from "@saleor/utils/errors/channels";
import currencyCodes from "currency-codes";
import React from "react";
import { useIntl } from "react-intl";
import ChannelDetailsPage from "../../pages/ChannelDetailsPage";
import { channelPath, channelsListUrl } from "../../urls";
import { calculateItemsOrderMoves } from "../ChannelDetails/handlers";
export const ChannelCreateView = ({}) => {
const navigate = useNavigator();
@ -32,39 +36,75 @@ export const ChannelCreateView = ({}) => {
const intl = useIntl();
const shop = useShop();
const [createChannel, createChannelOpts] = useChannelCreateMutation({
onCompleted: ({
channelCreate: { errors, channel },
}: ChannelCreateMutation) => {
notify(getDefaultNotifierSuccessErrorData(errors, intl));
const handleError = (error: ChannelErrorFragment) => {
notify({
status: "error",
text: getChannelsErrorMessage(error, intl),
});
};
if (!errors.length) {
navigate(channelPath(channel.id));
}
const [createChannel, createChannelOpts] = useChannelCreateMutation({
onCompleted: ({ channelCreate: { errors } }: ChannelCreateMutation) => {
notify(getDefaultNotifierSuccessErrorData(errors, intl));
},
});
const handleSubmit = ({
const [reorderChannelWarehouses] = useChannelReorderWarehousesMutation({
onCompleted: data => {
const errors = data.channelReorderWarehouses.errors;
if (errors.length) {
errors.forEach(error => handleError(error));
}
navigate(channelPath(data.channelReorderWarehouses.channel?.id));
},
});
const handleSubmit = async ({
shippingZonesIdsToAdd,
shippingZonesIdsToRemove,
warehousesIdsToAdd,
warehousesIdsToRemove,
warehousesToDisplay,
shippingZonesToDisplay,
currencyCode,
allocationStrategy,
...rest
}: FormData) =>
extractMutationErrors(
createChannel({
}: FormData) => {
const createChannelMutation = createChannel({
variables: {
input: {
...rest,
currencyCode: currencyCode.toUpperCase(),
addShippingZones: shippingZonesIdsToAdd,
addWarehouses: warehousesIdsToAdd,
stockSettings: {
allocationStrategy,
},
},
}),
},
});
const result = await createChannelMutation;
const errors = await extractMutationErrors(createChannelMutation);
if (!errors?.length) {
const moves = calculateItemsOrderMoves(
result.data?.channelCreate.channel?.warehouses,
warehousesToDisplay,
);
await reorderChannelWarehouses({
variables: {
channelId: result.data?.channelCreate.channel?.id,
moves,
},
});
}
return errors;
};
const {
data: shippingZonesCountData,
loading: shippingZonesCountLoading,

View file

@ -14,10 +14,10 @@ import {
useChannelDeactivateMutation,
useChannelDeleteMutation,
useChannelQuery,
useChannelReorderWarehousesMutation,
useChannelShippingZonesQuery,
useChannelsQuery,
useChannelUpdateMutation,
useChannelWarehousesQuery,
useShippingZonesCountQuery,
useWarehousesCountQuery,
} from "@saleor/graphql";
@ -32,6 +32,7 @@ import useShippingZonesSearch from "@saleor/searches/useShippingZonesSearch";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import getChannelsErrorMessage from "@saleor/utils/errors/channels";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import { mapEdgesToItems } from "@saleor/utils/maps";
import React from "react";
import { useIntl } from "react-intl";
@ -42,6 +43,7 @@ import {
ChannelUrlDialog,
ChannelUrlQueryParams,
} from "../../urls";
import { calculateItemsOrderMoves } from "./handlers";
interface ChannelDetailsProps {
id: string;
@ -102,17 +104,30 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
},
});
const handleSubmit = ({
const [
reorderChannelWarehouses,
reorderChannelWarehousesOpts,
] = useChannelReorderWarehousesMutation({
onCompleted: data => {
const errors = data.channelReorderWarehouses.errors;
if (errors.length) {
errors.forEach(error => handleError(error));
}
},
});
const handleSubmit = async ({
name,
slug,
shippingZonesIdsToRemove,
shippingZonesIdsToAdd,
warehousesIdsToRemove,
warehousesIdsToAdd,
warehousesToDisplay,
defaultCountry,
}: FormData) =>
extractMutationErrors(
updateChannel({
allocationStrategy,
}: FormData) => {
const updateChannelMutation = updateChannel({
variables: {
id: data?.channel.id,
input: {
@ -123,11 +138,33 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
removeShippingZones: shippingZonesIdsToRemove,
addWarehouses: warehousesIdsToAdd,
removeWarehouses: warehousesIdsToRemove,
stockSettings: {
allocationStrategy,
},
},
}),
},
});
const result = await updateChannelMutation;
const errors = await extractMutationErrors(updateChannelMutation);
if (!errors?.length) {
const moves = calculateItemsOrderMoves(
result.data?.channelUpdate.channel?.warehouses,
warehousesToDisplay,
);
await reorderChannelWarehouses({
variables: {
channelId: id,
moves,
},
});
}
return errors;
};
const onDeleteCompleted = (data: ChannelDeleteMutation) => {
const errors = data.channelDelete.errors;
if (errors.length === 0) {
@ -194,17 +231,6 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
loading: warehousesCountLoading,
} = useWarehousesCountQuery();
const {
data: channelWarehousesData,
loading: channelsWarehousesLoading,
} = useChannelWarehousesQuery({
variables: {
filter: {
channels: [id],
},
},
});
const {
loadMore: fetchMoreWarehouses,
search: searchWarehouses,
@ -213,6 +239,11 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
variables: DEFAULT_INITIAL_SEARCH_DATA,
});
const channelWarehouses = data?.channel?.warehouses || [];
const channelShippingZones = mapEdgesToItems(
channelShippingZonesData?.shippingZones,
);
return (
<>
<WindowTitle
@ -228,9 +259,7 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
</Backlink>
<PageHeader title={data?.channel?.name} />
<ChannelDetailsPage
channelShippingZones={channelShippingZonesData?.shippingZones?.edges?.map(
({ node }) => node,
)}
channelShippingZones={channelShippingZones}
allShippingZonesCount={
shippingZonesCountData?.shippingZones?.totalCount
}
@ -240,9 +269,7 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
searchShippingZonesResult,
fetchMoreShippingZones,
)}
channelWarehouses={channelWarehousesData?.warehouses?.edges?.map(
({ node }) => node,
)}
channelWarehouses={channelWarehouses}
allWarehousesCount={warehousesCountData?.warehouses?.totalCount}
searchWarehouses={searchWarehouses}
searchWarehousesData={searchWarehousesResult.data}
@ -253,11 +280,11 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
channel={data?.channel}
disabled={
updateChannelOpts.loading ||
reorderChannelWarehousesOpts.loading ||
loading ||
shippingZonesCountLoading ||
warehousesCountLoading ||
channelsShippingZonesLoading ||
channelsWarehousesLoading
channelsShippingZonesLoading
}
disabledStatus={
activateChannelOpts.loading || deactivateChannelOpts.loading

View file

@ -0,0 +1,44 @@
import { ReorderInput } from "@saleor/graphql";
import { Node } from "@saleor/types";
import { move } from "@saleor/utils/lists";
export function calculateItemsOrderMoves<T extends Node>(
itemsInputOrder: T[],
itemsOutputOrder: T[],
): ReorderInput[] {
const itemsInputOrderIds = itemsInputOrder.map(item => item.id);
const itemsOutputOrderIds = itemsOutputOrder.map(item => item.id);
let itemsIntermediateOrderIds = itemsInputOrderIds;
const itemsOrderMoves = itemsOutputOrderIds.reduce(
(moves, itemId, newIndex) => {
const oldIndex = itemsIntermediateOrderIds.indexOf(itemId);
const sortOrder = newIndex - oldIndex;
if (sortOrder === 0) {
return moves;
}
const newMoves = [
...moves,
{
id: itemId,
sortOrder,
},
];
itemsIntermediateOrderIds = move(
itemsIntermediateOrderIds[oldIndex],
itemsIntermediateOrderIds,
(a, b) => a === b,
newIndex,
);
return newMoves;
},
[] as ReorderInput[],
);
return itemsOrderMoves;
}

View file

@ -19,6 +19,9 @@ export const channelFragment = gql`
code
country
}
stockSettings {
allocationStrategy
}
}
`;
@ -26,5 +29,8 @@ export const channelDetailsFragment = gql`
fragment ChannelDetails on Channel {
...Channel
hasOrders
warehouses {
...Warehouse
}
}
`;

View file

@ -185,14 +185,27 @@ export const ChannelFragmentDoc = gql`
code
country
}
stockSettings {
allocationStrategy
}
}
`;
export const WarehouseFragmentDoc = gql`
fragment Warehouse on Warehouse {
id
name
}
`;
export const ChannelDetailsFragmentDoc = gql`
fragment ChannelDetails on Channel {
...Channel
hasOrders
warehouses {
...Warehouse
}
}
${ChannelFragmentDoc}`;
${ChannelFragmentDoc}
${WarehouseFragmentDoc}`;
export const CollectionFragmentDoc = gql`
fragment Collection on Collection {
id
@ -1203,12 +1216,6 @@ export const OrderEventFragmentDoc = gql`
}
}
`;
export const WarehouseFragmentDoc = gql`
fragment Warehouse on Warehouse {
id
name
}
`;
export const StockFragmentDoc = gql`
fragment Stock on Stock {
id
@ -4387,6 +4394,46 @@ export function useChannelDeactivateMutation(baseOptions?: ApolloReactHooks.Muta
export type ChannelDeactivateMutationHookResult = ReturnType<typeof useChannelDeactivateMutation>;
export type ChannelDeactivateMutationResult = Apollo.MutationResult<Types.ChannelDeactivateMutation>;
export type ChannelDeactivateMutationOptions = Apollo.BaseMutationOptions<Types.ChannelDeactivateMutation, Types.ChannelDeactivateMutationVariables>;
export const ChannelReorderWarehousesDocument = gql`
mutation ChannelReorderWarehouses($channelId: ID!, $moves: [ReorderInput!]!) {
channelReorderWarehouses(channelId: $channelId, moves: $moves) {
channel {
...ChannelDetails
}
errors {
...ChannelError
}
}
}
${ChannelDetailsFragmentDoc}
${ChannelErrorFragmentDoc}`;
export type ChannelReorderWarehousesMutationFn = Apollo.MutationFunction<Types.ChannelReorderWarehousesMutation, Types.ChannelReorderWarehousesMutationVariables>;
/**
* __useChannelReorderWarehousesMutation__
*
* To run a mutation, you first call `useChannelReorderWarehousesMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useChannelReorderWarehousesMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [channelReorderWarehousesMutation, { data, loading, error }] = useChannelReorderWarehousesMutation({
* variables: {
* channelId: // value for 'channelId'
* moves: // value for 'moves'
* },
* });
*/
export function useChannelReorderWarehousesMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.ChannelReorderWarehousesMutation, Types.ChannelReorderWarehousesMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useMutation<Types.ChannelReorderWarehousesMutation, Types.ChannelReorderWarehousesMutationVariables>(ChannelReorderWarehousesDocument, options);
}
export type ChannelReorderWarehousesMutationHookResult = ReturnType<typeof useChannelReorderWarehousesMutation>;
export type ChannelReorderWarehousesMutationResult = Apollo.MutationResult<Types.ChannelReorderWarehousesMutation>;
export type ChannelReorderWarehousesMutationOptions = Apollo.BaseMutationOptions<Types.ChannelReorderWarehousesMutation, Types.ChannelReorderWarehousesMutationVariables>;
export const BaseChannelsDocument = gql`
query BaseChannels {
channels {
@ -16487,46 +16534,6 @@ export function useWarehouseDetailsLazyQuery(baseOptions?: ApolloReactHooks.Lazy
export type WarehouseDetailsQueryHookResult = ReturnType<typeof useWarehouseDetailsQuery>;
export type WarehouseDetailsLazyQueryHookResult = ReturnType<typeof useWarehouseDetailsLazyQuery>;
export type WarehouseDetailsQueryResult = Apollo.QueryResult<Types.WarehouseDetailsQuery, Types.WarehouseDetailsQueryVariables>;
export const ChannelWarehousesDocument = gql`
query ChannelWarehouses($filter: WarehouseFilterInput) {
warehouses(filter: $filter, first: 100) {
edges {
node {
id
name
}
}
}
}
`;
/**
* __useChannelWarehousesQuery__
*
* To run a query within a React component, call `useChannelWarehousesQuery` and pass it any options that fit your needs.
* When your component renders, `useChannelWarehousesQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useChannelWarehousesQuery({
* variables: {
* filter: // value for 'filter'
* },
* });
*/
export function useChannelWarehousesQuery(baseOptions?: ApolloReactHooks.QueryHookOptions<Types.ChannelWarehousesQuery, Types.ChannelWarehousesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useQuery<Types.ChannelWarehousesQuery, Types.ChannelWarehousesQueryVariables>(ChannelWarehousesDocument, options);
}
export function useChannelWarehousesLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.ChannelWarehousesQuery, Types.ChannelWarehousesQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useLazyQuery<Types.ChannelWarehousesQuery, Types.ChannelWarehousesQueryVariables>(ChannelWarehousesDocument, options);
}
export type ChannelWarehousesQueryHookResult = ReturnType<typeof useChannelWarehousesQuery>;
export type ChannelWarehousesLazyQueryHookResult = ReturnType<typeof useChannelWarehousesLazyQuery>;
export type ChannelWarehousesQueryResult = Apollo.QueryResult<Types.ChannelWarehousesQuery, Types.ChannelWarehousesQueryVariables>;
export const WarehousesCountDocument = gql`
query WarehousesCount {
warehouses {

File diff suppressed because one or more lines are too long

View file

@ -156,6 +156,21 @@ export enum AddressTypeEnum {
SHIPPING = 'SHIPPING'
}
/**
* Determine the allocation strategy for the channel.
*
* PRIORITIZE_SORTING_ORDER - the allocation is prioritized by the warehouses' sort
* order within the channel
*
* PRIORITIZE_HIGH_STOCK - the allocation is prioritized by the highest available
* quantity in stocks
*
*/
export enum AllocationStrategyEnum {
PRIORITIZE_SORTING_ORDER = 'PRIORITIZE_SORTING_ORDER',
PRIORITIZE_HIGH_STOCK = 'PRIORITIZE_HIGH_STOCK'
}
/** An enumeration. */
export enum AppErrorCode {
FORBIDDEN = 'FORBIDDEN',
@ -606,6 +621,14 @@ export type CategorySortingInput = {
export type ChannelCreateInput = {
/** isActive flag. */
isActive?: InputMaybe<Scalars['Boolean']>;
/**
* The channel stock settings.
*
* Added in Saleor 3.7.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
stockSettings?: InputMaybe<StockSettingsInput>;
/** List of shipping zones to assign to the channel. */
addShippingZones?: InputMaybe<Array<Scalars['ID']>>;
/**
@ -653,6 +676,14 @@ export enum ChannelErrorCode {
export type ChannelUpdateInput = {
/** isActive flag. */
isActive?: InputMaybe<Scalars['Boolean']>;
/**
* The channel stock settings.
*
* Added in Saleor 3.7.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
stockSettings?: InputMaybe<StockSettingsInput>;
/** List of shipping zones to assign to the channel. */
addShippingZones?: InputMaybe<Array<Scalars['ID']>>;
/**
@ -3031,6 +3062,12 @@ export type OrderFulfillInput = {
notifyCustomer?: InputMaybe<Scalars['Boolean']>;
/** If true, then allow proceed fulfillment when stock is exceeded. */
allowStockToBeExceeded?: InputMaybe<Scalars['Boolean']>;
/**
* Fulfillment tracking number.
*
* Added in Saleor 3.6.
*/
trackingNumber?: InputMaybe<Scalars['String']>;
};
export type OrderFulfillLineInput = {
@ -3963,6 +4000,8 @@ export type ProductVariantBulkCreateInput = {
attributes: Array<BulkAttributeValueInput>;
/** Stock keeping unit. */
sku?: InputMaybe<Scalars['String']>;
/** Variant name. */
name?: InputMaybe<Scalars['String']>;
/** Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. */
trackInventory?: InputMaybe<Scalars['Boolean']>;
/** Weight of the Product Variant. */
@ -4011,6 +4050,8 @@ export type ProductVariantCreateInput = {
attributes: Array<AttributeValueInput>;
/** Stock keeping unit. */
sku?: InputMaybe<Scalars['String']>;
/** Variant name. */
name?: InputMaybe<Scalars['String']>;
/** Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. */
trackInventory?: InputMaybe<Scalars['Boolean']>;
/** Weight of the Product Variant. */
@ -4050,6 +4091,8 @@ export type ProductVariantInput = {
attributes?: InputMaybe<Array<AttributeValueInput>>;
/** Stock keeping unit. */
sku?: InputMaybe<Scalars['String']>;
/** Variant name. */
name?: InputMaybe<Scalars['String']>;
/** Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. */
trackInventory?: InputMaybe<Scalars['Boolean']>;
/** Weight of the Product Variant. */
@ -4493,6 +4536,11 @@ export type StockInput = {
quantity: Scalars['Int'];
};
export type StockSettingsInput = {
/** Allocation strategy options. Strategy defines the preference of warehouses for allocations and reservations. */
allocationStrategy: AllocationStrategyEnum;
};
/** Enum representing the type of a payment storage in a gateway. */
export enum StorePaymentMethodEnum {
/** On session storage type. The payment is stored only to be reused when the customer is present in the checkout flow. */
@ -4965,7 +5013,11 @@ export type WebhookCreateInput = {
app?: InputMaybe<Scalars['ID']>;
/** Determine if webhook will be set active or not. */
isActive?: InputMaybe<Scalars['Boolean']>;
/** The secret key used to create a hash signature with each payload. */
/**
* The secret key used to create a hash signature with each payload.
*
* DEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.
*/
secretKey?: InputMaybe<Scalars['String']>;
/**
* Subscription query used to define a webhook payload.
@ -5562,7 +5614,11 @@ export type WebhookUpdateInput = {
app?: InputMaybe<Scalars['ID']>;
/** Determine if webhook will be set active or not. */
isActive?: InputMaybe<Scalars['Boolean']>;
/** Use to create a hash signature with each payload. */
/**
* Use to create a hash signature with each payload.
*
* DEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.
*/
secretKey?: InputMaybe<Scalars['String']>;
/**
* Subscription query used to define a webhook payload.
@ -5867,7 +5923,7 @@ export type ChannelCreateMutationVariables = Exact<{
}>;
export type ChannelCreateMutation = { __typename: 'Mutation', channelCreate: { __typename: 'ChannelCreate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelCreateMutation = { __typename: 'Mutation', channelCreate: { __typename: 'ChannelCreate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelUpdateMutationVariables = Exact<{
id: Scalars['ID'];
@ -5875,7 +5931,7 @@ export type ChannelUpdateMutationVariables = Exact<{
}>;
export type ChannelUpdateMutation = { __typename: 'Mutation', channelUpdate: { __typename: 'ChannelUpdate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelUpdateMutation = { __typename: 'Mutation', channelUpdate: { __typename: 'ChannelUpdate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelDeleteMutationVariables = Exact<{
id: Scalars['ID'];
@ -5890,31 +5946,39 @@ export type ChannelActivateMutationVariables = Exact<{
}>;
export type ChannelActivateMutation = { __typename: 'Mutation', channelActivate: { __typename: 'ChannelActivate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelActivateMutation = { __typename: 'Mutation', channelActivate: { __typename: 'ChannelActivate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelDeactivateMutationVariables = Exact<{
id: Scalars['ID'];
}>;
export type ChannelDeactivateMutation = { __typename: 'Mutation', channelDeactivate: { __typename: 'ChannelDeactivate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelDeactivateMutation = { __typename: 'Mutation', channelDeactivate: { __typename: 'ChannelDeactivate', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type ChannelReorderWarehousesMutationVariables = Exact<{
channelId: Scalars['ID'];
moves: Array<ReorderInput> | ReorderInput;
}>;
export type ChannelReorderWarehousesMutation = { __typename: 'Mutation', channelReorderWarehouses: { __typename: 'ChannelReorderWarehouses', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } } | null, errors: Array<{ __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null }> } | null };
export type BaseChannelsQueryVariables = Exact<{ [key: string]: never; }>;
export type BaseChannelsQuery = { __typename: 'Query', channels: Array<{ __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } }> | null };
export type BaseChannelsQuery = { __typename: 'Query', channels: Array<{ __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } }> | null };
export type ChannelsQueryVariables = Exact<{ [key: string]: never; }>;
export type ChannelsQuery = { __typename: 'Query', channels: Array<{ __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } }> | null };
export type ChannelsQuery = { __typename: 'Query', channels: Array<{ __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } }> | null };
export type ChannelQueryVariables = Exact<{
id: Scalars['ID'];
}>;
export type ChannelQuery = { __typename: 'Query', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } } | null };
export type ChannelQuery = { __typename: 'Query', channel: { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } } | null };
export type CollectionUpdateMutationVariables = Exact<{
id: Scalars['ID'];
@ -6082,7 +6146,7 @@ export type SetCustomerDefaultAddressMutationVariables = Exact<{
}>;
export type SetCustomerDefaultAddressMutation = { __typename: 'Mutation', addressSetDefault: { __typename: 'AddressSetDefault', errors: Array<{ __typename: 'AccountError', code: AccountErrorCode, field: string | null, addressType: AddressTypeEnum | null, message: string | null }>, user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }> | null, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null } | null };
export type SetCustomerDefaultAddressMutation = { __typename: 'Mutation', addressSetDefault: { __typename: 'AddressSetDefault', errors: Array<{ __typename: 'AccountError', code: AccountErrorCode, field: string | null, addressType: AddressTypeEnum | null, message: string | null }>, user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }>, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null } | null };
export type CreateCustomerAddressMutationVariables = Exact<{
id: Scalars['ID'];
@ -6090,7 +6154,7 @@ export type CreateCustomerAddressMutationVariables = Exact<{
}>;
export type CreateCustomerAddressMutation = { __typename: 'Mutation', addressCreate: { __typename: 'AddressCreate', errors: Array<{ __typename: 'AccountError', code: AccountErrorCode, field: string | null, addressType: AddressTypeEnum | null, message: string | null }>, address: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }> | null, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null } | null };
export type CreateCustomerAddressMutation = { __typename: 'Mutation', addressCreate: { __typename: 'AddressCreate', errors: Array<{ __typename: 'AccountError', code: AccountErrorCode, field: string | null, addressType: AddressTypeEnum | null, message: string | null }>, address: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }>, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null } | null };
export type UpdateCustomerAddressMutationVariables = Exact<{
id: Scalars['ID'];
@ -6105,7 +6169,7 @@ export type RemoveCustomerAddressMutationVariables = Exact<{
}>;
export type RemoveCustomerAddressMutation = { __typename: 'Mutation', addressDelete: { __typename: 'AddressDelete', errors: Array<{ __typename: 'AccountError', code: AccountErrorCode, field: string | null, addressType: AddressTypeEnum | null, message: string | null }>, user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }> | null, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null } | null };
export type RemoveCustomerAddressMutation = { __typename: 'Mutation', addressDelete: { __typename: 'AddressDelete', errors: Array<{ __typename: 'AccountError', code: AccountErrorCode, field: string | null, addressType: AddressTypeEnum | null, message: string | null }>, user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }>, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null } | null };
export type BulkRemoveCustomersMutationVariables = Exact<{
ids: Array<Scalars['ID']> | Scalars['ID'];
@ -6140,7 +6204,7 @@ export type CustomerAddressesQueryVariables = Exact<{
}>;
export type CustomerAddressesQuery = { __typename: 'Query', user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }> | null, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null };
export type CustomerAddressesQuery = { __typename: 'Query', user: { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }>, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null } | null };
export type CustomerCreateDataQueryVariables = Exact<{ [key: string]: never; }>;
@ -6357,9 +6421,9 @@ export type CategoryDetailsFragment = { __typename: 'Category', id: string, name
export type ChannelErrorFragment = { __typename: 'ChannelError', code: ChannelErrorCode, field: string | null, message: string | null };
export type ChannelFragment = { __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } };
export type ChannelFragment = { __typename: 'Channel', id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } };
export type ChannelDetailsFragment = { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string } };
export type ChannelDetailsFragment = { __typename: 'Channel', hasOrders: boolean, id: string, isActive: boolean, name: string, slug: string, currencyCode: string, warehouses: Array<{ __typename: 'Warehouse', id: string, name: string }>, defaultCountry: { __typename: 'CountryDisplay', code: string, country: string }, stockSettings: { __typename: 'StockSettings', allocationStrategy: AllocationStrategyEnum } };
export type CollectionFragment = { __typename: 'Collection', id: string, name: string, channelListings: Array<{ __typename: 'CollectionChannelListing', isPublished: boolean, publicationDate: any | null, channel: { __typename: 'Channel', id: string, name: string } }> | null };
@ -6371,7 +6435,7 @@ export type CustomerFragment = { __typename: 'User', id: string, email: string,
export type CustomerDetailsFragment = { __typename: 'User', dateJoined: any, lastLogin: any | null, note: string | null, isActive: boolean, id: string, email: string, firstName: string, lastName: string, defaultShippingAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, defaultBillingAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, privateMetadata: Array<{ __typename: 'MetadataItem', key: string, value: string }> };
export type CustomerAddressesFragment = { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }> | null, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null };
export type CustomerAddressesFragment = { __typename: 'User', id: string, email: string, firstName: string, lastName: string, addresses: Array<{ __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }>, defaultBillingAddress: { __typename: 'Address', id: string } | null, defaultShippingAddress: { __typename: 'Address', id: string } | null };
export type SaleFragment = { __typename: 'Sale', id: string, name: string, type: SaleType, startDate: any, endDate: any | null, channelListings: Array<{ __typename: 'SaleChannelListing', id: string, discountValue: number, currency: string, channel: { __typename: 'Channel', id: string, name: string, currencyCode: string } }> | null, metadata: Array<{ __typename: 'MetadataItem', key: string, value: string }>, privateMetadata: Array<{ __typename: 'MetadataItem', key: string, value: string }> };
@ -8616,13 +8680,6 @@ export type WarehouseDetailsQueryVariables = Exact<{
export type WarehouseDetailsQuery = { __typename: 'Query', warehouse: { __typename: 'Warehouse', isPrivate: boolean, clickAndCollectOption: WarehouseClickAndCollectOptionEnum, id: string, name: string, address: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } }, shippingZones: { __typename: 'ShippingZoneCountableConnection', edges: Array<{ __typename: 'ShippingZoneCountableEdge', node: { __typename: 'ShippingZone', id: string, name: string } }> } } | null };
export type ChannelWarehousesQueryVariables = Exact<{
filter?: InputMaybe<WarehouseFilterInput>;
}>;
export type ChannelWarehousesQuery = { __typename: 'Query', warehouses: { __typename: 'WarehouseCountableConnection', edges: Array<{ __typename: 'WarehouseCountableEdge', node: { __typename: 'Warehouse', id: string, name: string } }> } | null };
export type WarehousesCountQueryVariables = Exact<{ [key: string]: never; }>;

File diff suppressed because it is too large Load diff

View file

@ -37,20 +37,6 @@ export const warehouseDetails = gql`
}
`;
// first: 100 - to be removed when we implement pagintion in ui for this query
export const channelWarehouses = gql`
query ChannelWarehouses($filter: WarehouseFilterInput) {
warehouses(filter: $filter, first: 100) {
edges {
node {
id
name
}
}
}
}
`;
export const warehousesCount = gql`
query WarehousesCount {
warehouses {