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, "enumValues": null,
"possibleTypes": 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", "kind": "OBJECT",
"name": "App", "name": "App",
@ -12182,6 +12205,22 @@
}, },
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "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, "inputFields": null,
@ -12355,6 +12394,18 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "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", "name": "addShippingZones",
"description": "List of shipping zones to assign to the channel.", "description": "List of shipping zones to assign to the channel.",
@ -12943,6 +12994,53 @@
], ],
"possibleTypes": null "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", "kind": "OBJECT",
"name": "ChannelStatusChanged", "name": "ChannelStatusChanged",
@ -13109,6 +13207,18 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "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", "name": "addShippingZones",
"description": "List of shipping zones to assign to the channel.", "description": "List of shipping zones to assign to the channel.",
@ -51670,6 +51780,59 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "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", "name": "attributeCreate",
"description": "Creates an attribute.", "description": "Creates an attribute.",
@ -59493,6 +59656,18 @@
"defaultValue": "false", "defaultValue": "false",
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "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, "interfaces": null,
@ -76932,6 +77107,18 @@
"isDeprecated": false, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "name",
"description": "Variant name.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "trackInventory", "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.", "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, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "name",
"description": "Variant name.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "trackInventory", "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.", "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, "isDeprecated": false,
"deprecationReason": null "deprecationReason": null
}, },
{
"name": "name",
"description": "Variant name.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{ {
"name": "trackInventory", "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.", "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, "enumValues": null,
"possibleTypes": 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", "kind": "ENUM",
"name": "StorePaymentMethodEnum", "name": "StorePaymentMethodEnum",
@ -96905,15 +97170,19 @@
"description": "List of all user's addresses.", "description": "List of all user's addresses.",
"args": [], "args": [],
"type": { "type": {
"kind": "LIST", "kind": "NON_NULL",
"name": null, "name": null,
"ofType": { "ofType": {
"kind": "NON_NULL", "kind": "LIST",
"name": null, "name": null,
"ofType": { "ofType": {
"kind": "OBJECT", "kind": "NON_NULL",
"name": "Address", "name": null,
"ofType": null "ofType": {
"kind": "OBJECT",
"name": "Address",
"ofType": null
}
} }
} }
}, },
@ -102864,15 +103133,15 @@
}, },
{ {
"name": "secretKey", "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": [], "args": [],
"type": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
"ofType": null "ofType": null
}, },
"isDeprecated": false, "isDeprecated": true,
"deprecationReason": null "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", "name": "subscriptionQuery",
@ -103085,7 +103354,7 @@
}, },
{ {
"name": "secretKey", "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": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",
@ -105465,7 +105734,7 @@
}, },
{ {
"name": "secretKey", "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": { "type": {
"kind": "SCALAR", "kind": "SCALAR",
"name": "String", "name": "String",

View file

@ -166,6 +166,10 @@
"context": "header, allocated product quantity", "context": "header, allocated product quantity",
"string": "Allocated" "string": "Allocated"
}, },
"/DzBc6": {
"context": "section description",
"string": "Strategy defines the preference of warehouses for stock allocations and reservations."
},
"/JENWS": { "/JENWS": {
"string": "Reduced Tax Rates" "string": "Reduced Tax Rates"
}, },
@ -735,6 +739,10 @@
"context": "notification", "context": "notification",
"string": "Removed pages" "string": "Removed pages"
}, },
"423QsF": {
"context": "option title",
"string": "Prioritize warehouses with highest stock"
},
"43AOvZ": { "43AOvZ": {
"context": "alert group message", "context": "alert group message",
"string": "You will not be able to finalize this draft because:" "string": "You will not be able to finalize this draft because:"
@ -2104,6 +2112,10 @@
"context": "selected customer gift card is sent to subtitle", "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." "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": { "FSinkL": {
"context": "variant stock status", "context": "variant stock status",
"string": "Available inventory at:" "string": "Available inventory at:"
@ -2112,6 +2124,10 @@
"context": "ExitFormPrompt title", "context": "ExitFormPrompt title",
"string": "You have unsaved changes" "string": "You have unsaved changes"
}, },
"FYfoiF": {
"context": "section name",
"string": "Allocation strategy"
},
"Fbr4Vp": { "Fbr4Vp": {
"context": "dialog header", "context": "dialog header",
"string": "Permissions" "string": "Permissions"
@ -2207,6 +2223,10 @@
"context": "tab name", "context": "tab name",
"string": "All Collections" "string": "All Collections"
}, },
"G5NKx6": {
"context": "tooltip",
"string": "Checkout reservation time threshold is enabled in settings."
},
"G7mu0y": { "G7mu0y": {
"string": "The GraphQL API is beta quality. It is not fully optimized and some mutations or queries may be missing." "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": { "HMD+ib": {
"string": "Last order" "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": { "HP6m+q": {
"string": "Attributes and Product Types" "string": "Attributes and Product Types"
}, },
@ -2576,10 +2600,6 @@
"context": "change warehouse dialog description", "context": "change warehouse dialog description",
"string": "Choose warehouse from which you want to fulfill {productName}" "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": { "IoCMjg": {
"context": "no collections", "context": "no collections",
"string": "No collections found" "string": "No collections found"
@ -4679,6 +4699,10 @@
"context": "imperial unit system", "context": "imperial unit system",
"string": "Imperial" "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": { "YicEbK": {
"string": "Search Atrtibuttes" "string": "Search Atrtibuttes"
}, },
@ -5750,6 +5774,10 @@
"context": "voucher country range", "context": "voucher country range",
"string": "Countries" "string": "Countries"
}, },
"icb1fc": {
"context": "tooltip",
"string": "Stock allocations occur when:"
},
"icz/jb": { "icz/jb": {
"context": "customer", "context": "customer",
"string": "Join Date" "string": "Join Date"
@ -6616,6 +6644,10 @@
"context": "key-value field input", "context": "key-value field input",
"string": "Key" "string": "Key"
}, },
"q5Lfp4": {
"context": "tooltip",
"string": "Order contains products that have \"Track inventory\" enabled."
},
"q8ep2I": { "q8ep2I": {
"context": "dialog header", "context": "dialog header",
"string": "Delete Customers" "string": "Delete Customers"
@ -7253,6 +7285,10 @@
"v1pNHW": { "v1pNHW": {
"string": "Attribute Class" "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+": { "v3WWK+": {
"string": "Status is invalid" "string": "Status is invalid"
}, },

View file

@ -411,6 +411,21 @@ type Allocation implements Node {
warehouse: Warehouse! 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.""" """Represents app data."""
type App implements Node & ObjectWithMetadata { type App implements Node & ObjectWithMetadata {
id: ID! 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. Note: this API is currently in Feature Preview and can be subject to changes at later point.
""" """
availableShippingMethodsPerCountry(countries: [CountryCode!]): [ShippingMethodsPerCountry!] 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 flag."""
isActive: Boolean 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.""" """List of shipping zones to assign to the channel."""
addShippingZones: [ID!] addShippingZones: [ID!]
@ -2708,6 +2743,21 @@ enum ChannelErrorCode {
DUPLICATED_INPUT_ITEM 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. Event sent when channel status has changed.
@ -2747,6 +2797,15 @@ input ChannelUpdateInput {
"""isActive flag.""" """isActive flag."""
isActive: Boolean 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.""" """List of shipping zones to assign to the channel."""
addShippingZones: [ID!] addShippingZones: [ID!]
@ -11485,6 +11544,23 @@ type Mutation {
id: ID! id: ID!
): ChannelDeactivate ): 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.""" """Creates an attribute."""
attributeCreate( attributeCreate(
"""Fields required to create an attribute.""" """Fields required to create an attribute."""
@ -13182,6 +13258,13 @@ input OrderFulfillInput {
"""If true, then allow proceed fulfillment when stock is exceeded.""" """If true, then allow proceed fulfillment when stock is exceeded."""
allowStockToBeExceeded: Boolean = false allowStockToBeExceeded: Boolean = false
"""
Fulfillment tracking number.
Added in Saleor 3.6.
"""
trackingNumber: String
} }
input OrderFulfillLineInput { input OrderFulfillLineInput {
@ -17016,6 +17099,9 @@ input ProductVariantBulkCreateInput {
"""Stock keeping unit.""" """Stock keeping unit."""
sku: String 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. 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.""" """Stock keeping unit."""
sku: String 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. 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.""" """Stock keeping unit."""
sku: String 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. 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! 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 representing the type of a payment storage in a gateway."""
enum StorePaymentMethodEnum { enum StorePaymentMethodEnum {
""" """
@ -21753,7 +21866,7 @@ type User implements Node & ObjectWithMetadata {
isActive: Boolean! isActive: Boolean!
"""List of all user's addresses.""" """List of all user's addresses."""
addresses: [Address!] addresses: [Address!]!
"""Returns the last open checkout of this user.""" """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.") 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.""" """Informs if webhook is activated."""
isActive: Boolean! isActive: Boolean!
""" """Used to create a hash signature for each payload."""
Used to create a hash signature with 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.")
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 define payloads for specific events.""" """Used to define payloads for specific events."""
subscriptionQuery: String subscriptionQuery: String
@ -23029,7 +23138,11 @@ input WebhookCreateInput {
"""Determine if webhook will be set active or not.""" """Determine if webhook will be set active or not."""
isActive: Boolean 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 secretKey: String
""" """
@ -23917,7 +24030,11 @@ input WebhookUpdateInput {
"""Determine if webhook will be set active or not.""" """Determine if webhook will be set active or not."""
isActive: Boolean 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 secretKey: String
""" """

View file

@ -1,10 +1,13 @@
import { Accordion, Divider, Typography } from "@material-ui/core"; import { Accordion, Divider, Typography } from "@material-ui/core";
import Skeleton from "@saleor/components/Skeleton";
import { ReorderEvent } from "@saleor/types";
import React from "react"; import React from "react";
import { defineMessages, useIntl } from "react-intl"; import { defineMessages, useIntl } from "react-intl";
import AssignmentListFooter from "./AssignmentListFooter"; import AssignmentListFooter from "./AssignmentListFooter";
import AssignmentListHeader from "./AssignmentListHeader"; import AssignmentListHeader from "./AssignmentListHeader";
import Item from "./Item"; import Item from "./Item";
import SortableContainer from "./SortableContainer";
import { useExpanderStyles, useStyles } from "./styles"; import { useExpanderStyles, useStyles } from "./styles";
import { AssignmentListProps } from "./types"; import { AssignmentListProps } from "./types";
@ -17,33 +20,75 @@ const messages = defineMessages({
}); });
const AssignmentList: React.FC<AssignmentListProps> = props => { 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 intl = useIntl();
const classes = useStyles(); const classes = useStyles();
const expanderClasses = useExpanderStyles(); 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; const hasMoreItemsToBeSelected = totalCount !== items.length;
return ( return (
<Accordion classes={expanderClasses}> <Accordion classes={expanderClasses}>
<AssignmentListHeader assignCount={items.length} itemsName={itemsName} /> <AssignmentListHeader
assignCount={items.length}
itemsName={itemsName}
loading={loading}
/>
<Divider /> <Divider />
{items.map(item => ( {loading ? (
<Item key={item.id} item={item} onDelete={removeItem} /> <Skeleton className={classes.skeleton} />
))}
{hasMoreItemsToBeSelected ? (
<AssignmentListFooter {...props} />
) : ( ) : (
<Typography <>
color="textSecondary" <SortableContainer
variant="subtitle1" axis="xy"
className={classes.infoMessage} lockAxis="xy"
> useDragHandle
{intl.formatMessage(messages.allSelectedMessage, { onSortStart={handleSortStart}
itemsName: itemsName.toLowerCase(), onSortEnd={handleSortEnd}
})} >
</Typography> <div>
{items.map((item, itemIndex) => (
<Item
key={itemIndex}
index={itemIndex}
item={item}
onDelete={removeItem}
sortable={!!reorderItem}
/>
))}
</div>
</SortableContainer>
{hasMoreItemsToBeSelected ? (
<AssignmentListFooter {...props} />
) : (
<Typography
color="textSecondary"
variant="subtitle1"
className={classes.infoMessage}
>
{intl.formatMessage(messages.allSelectedMessage, {
itemsName: itemsName.toLowerCase(),
})}
</Typography>
)}
</>
)} )}
</Accordion> </Accordion>
); );

View file

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

View file

@ -1,28 +1,41 @@
import { Divider, Typography } from "@material-ui/core"; import { Divider, Typography } from "@material-ui/core";
import DeletableItem from "@saleor/components/DeletableItem"; import DeletableItem from "@saleor/components/DeletableItem";
import React from "react"; import React from "react";
import { SortableElement, SortableElementProps } from "react-sortable-hoc";
import SortableHandle from "./SortableHandle";
import { useStyles } from "./styles"; import { useStyles } from "./styles";
import { AssignItem } from "./types"; import { AssignItem } from "./types";
interface ItemProps { interface ItemProps extends SortableElementProps {
item: AssignItem; item: AssignItem;
sortable?: boolean;
onDelete: (id: string) => void; onDelete: (id: string) => void;
} }
const Item: React.FC<ItemProps> = ({ item, onDelete }) => { const Item = SortableElement(
const { id, name } = item; ({ item, sortable = false, onDelete }: ItemProps) => {
const classes = useStyles(); const { id, name } = item;
const classes = useStyles();
return ( return (
<> <>
<div className={classes.container}> <div className={classes.container}>
<Typography>{name}</Typography> <div className={classes.containerContent}>
<DeletableItem id={id} onDelete={onDelete} /> {sortable && (
</div> <SortableHandle
<Divider /> className={classes.sortableHandle}
</> data-test-id="button-drag-handle"
); />
}; )}
<Typography>{name}</Typography>
</div>
<DeletableItem id={id} onDelete={onDelete} />
</div>
<Divider />
</>
);
},
);
export default Item; 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", flexDirection: "row",
alignItems: "center", alignItems: "center",
}, },
skeleton: {
width: "100%",
marginRight: theme.spacing(4),
},
// empty expanded needed for mui to use root styles // empty expanded needed for mui to use root styles
expanded: {}, expanded: {},
root: { root: {
@ -61,6 +65,17 @@ export const useStyles = makeStyles(
flexDirection: "row", flexDirection: "row",
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center", alignItems: "center",
background: theme.palette.background.paper,
},
containerContent: {
display: "flex",
overflow: "auto",
},
sortableHandle: {
marginRight: theme.spacing(1),
},
grabbing: {
cursor: "grabbing",
}, },
root: { root: {
paddingRight: theme.spacing(1), paddingRight: theme.spacing(1),
@ -68,6 +83,9 @@ export const useStyles = makeStyles(
infoMessage: { infoMessage: {
padding: theme.spacing(3), padding: theme.spacing(3),
}, },
skeleton: {
margin: theme.spacing(4, 0),
},
}), }),
{ name: "AssignmentList" }, { name: "AssignmentList" },
); );

View file

@ -1,4 +1,4 @@
import { FetchMoreProps } from "@saleor/types"; import { FetchMoreProps, ReorderAction } from "@saleor/types";
export interface AssignItem { export interface AssignItem {
id: string; id: string;
@ -13,7 +13,9 @@ export interface AssignmentListProps {
totalCount: number; totalCount: number;
inputName: string; inputName: string;
dataTestId: string; dataTestId: string;
loading: boolean;
addItem: (id: string) => void; addItem: (id: string) => void;
removeItem: (id: string) => void; removeItem: (id: string) => void;
reorderItem?: ReorderAction;
searchItems: (searchPhrase: string) => void; 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 { countries } from "@saleor/fixtures";
import { CountryCode } from "@saleor/graphql"; import { AllocationStrategyEnum, CountryCode } from "@saleor/graphql";
import Decorator from "@saleor/storybook/Decorator"; import Decorator from "@saleor/storybook/Decorator";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
@ -17,6 +17,31 @@ const props: ChannelFormProps = {
name: "Test", name: "Test",
slug: "test", slug: "test",
defaultCountry: CountryCode.PL, 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, disabled: false,
errors: [], errors: [],

View file

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

View file

@ -31,6 +31,7 @@ const baseProps: ShippingZonesProps = {
shippingZones: [], shippingZones: [],
shippingZonesChoices: shippingZones as ChannelShippingZones, shippingZonesChoices: shippingZones as ChannelShippingZones,
totalCount: 10, totalCount: 10,
loading: false,
}; };
storiesOf("Shipping zones", module) storiesOf("Shipping zones", module)
@ -41,4 +42,5 @@ storiesOf("Shipping zones", module)
{...baseProps} {...baseProps}
shippingZones={shippingZones as ChannelShippingZones} 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 { sectionNames } from "@saleor/intl";
import { FetchMoreProps, RelayToFlat } from "@saleor/types"; import { FetchMoreProps, RelayToFlat } from "@saleor/types";
import React from "react"; import React from "react";
import { defineMessages, useIntl } from "react-intl"; import { useIntl } from "react-intl";
import AssignmentList from "../AssignmentList"; import AssignmentList from "../AssignmentList";
import { messages } from "./messages";
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",
},
});
export interface ShippingZonesProps { export interface ShippingZonesProps {
addShippingZone: (id: string) => void; addShippingZone: (id: string) => void;
removeShippingZone: (id: string) => void; removeShippingZone: (id: string) => void;
searchShippingZones: (searchPhrase: string) => void; searchShippingZones: (searchPhrase: string) => void;
loading: boolean;
totalCount: number; totalCount: number;
fetchMoreShippingZones: FetchMoreProps; fetchMoreShippingZones: FetchMoreProps;
shippingZones: ChannelShippingZones; shippingZones: ChannelShippingZones;
@ -33,6 +26,7 @@ const ShippingZones: React.FC<ShippingZonesProps> = props => {
addShippingZone, addShippingZone,
removeShippingZone, removeShippingZone,
searchShippingZones, searchShippingZones,
loading,
totalCount, totalCount,
fetchMoreShippingZones, fetchMoreShippingZones,
shippingZones, shippingZones,
@ -48,6 +42,7 @@ const ShippingZones: React.FC<ShippingZonesProps> = props => {
<Typography>{intl.formatMessage(messages.subtitle)}</Typography> <Typography>{intl.formatMessage(messages.subtitle)}</Typography>
</CardContent> </CardContent>
<AssignmentList <AssignmentList
loading={loading}
items={shippingZones} items={shippingZones}
itemsChoices={shippingZonesChoices} itemsChoices={shippingZonesChoices}
addItem={addShippingZone} 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, onFetchMore: () => undefined,
totalCount: 0, totalCount: 0,
}, },
reorderWarehouses: () => undefined,
warehouses: [], warehouses: [],
warehousesChoices: warehouses as ChannelWarehouses, warehousesChoices: warehouses as ChannelWarehouses,
totalCount: 10, totalCount: 10,
loading: false,
}; };
storiesOf("Warehouses", module) storiesOf("Warehouses", module)
@ -38,4 +40,5 @@ storiesOf("Warehouses", module)
.add("with no options selected", () => <Warehouses {...baseProps} />) .add("with no options selected", () => <Warehouses {...baseProps} />)
.add("with options selected", () => ( .add("with options selected", () => (
<Warehouses {...baseProps} warehouses={warehouses as ChannelWarehouses} /> <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 CardTitle from "@saleor/components/CardTitle";
import { SearchWarehousesQuery } from "@saleor/graphql"; import { SearchWarehousesQuery } from "@saleor/graphql";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { FetchMoreProps, RelayToFlat } from "@saleor/types"; import { FetchMoreProps, RelayToFlat, ReorderAction } from "@saleor/types";
import React from "react"; import React from "react";
import { defineMessages, useIntl } from "react-intl"; import { useIntl } from "react-intl";
import AssignmentList from "../AssignmentList"; import AssignmentList from "../AssignmentList";
import { messages } from "./messages";
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",
},
});
export interface WarehousesProps { export interface WarehousesProps {
addWarehouse: (id: string) => void; addWarehouse: (id: string) => void;
removeWarehouse: (id: string) => void; removeWarehouse: (id: string) => void;
searchWarehouses: (searchPhrase: string) => void; searchWarehouses: (searchPhrase: string) => void;
reorderWarehouses: ReorderAction;
loading: boolean;
totalCount: number; totalCount: number;
fetchMoreWarehouses: FetchMoreProps; fetchMoreWarehouses: FetchMoreProps;
warehouses: ChannelWarehouses; warehouses: ChannelWarehouses;
@ -33,6 +27,8 @@ const Warehouses: React.FC<WarehousesProps> = props => {
addWarehouse, addWarehouse,
removeWarehouse, removeWarehouse,
searchWarehouses, searchWarehouses,
reorderWarehouses,
loading,
totalCount, totalCount,
fetchMoreWarehouses, fetchMoreWarehouses,
warehouses, warehouses,
@ -48,11 +44,13 @@ const Warehouses: React.FC<WarehousesProps> = props => {
<Typography>{intl.formatMessage(messages.subtitle)}</Typography> <Typography>{intl.formatMessage(messages.subtitle)}</Typography>
</CardContent> </CardContent>
<AssignmentList <AssignmentList
loading={loading}
items={warehouses} items={warehouses}
itemsChoices={warehousesChoices} itemsChoices={warehousesChoices}
addItem={addWarehouse} addItem={addWarehouse}
removeItem={removeWarehouse} removeItem={removeWarehouse}
searchItems={searchWarehouses} searchItems={searchWarehouses}
reorderItem={reorderWarehouses}
fetchMoreItems={fetchMoreWarehouses} fetchMoreItems={fetchMoreWarehouses}
totalCount={totalCount} totalCount={totalCount}
dataTestId="warehouse" 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 { import {
AllocationStrategyEnum,
ChannelDetailsFragment, ChannelDetailsFragment,
ChannelErrorCode, ChannelErrorCode,
ChannelErrorFragment, ChannelErrorFragment,
@ -29,6 +30,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", __typename: "Channel",
@ -43,6 +60,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", __typename: "Channel",
@ -57,6 +90,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", __typename: "Channel",
@ -71,6 +120,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", __typename: "Channel",
@ -85,6 +150,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", __typename: "Channel",
@ -99,6 +180,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", __typename: "Channel",
@ -113,6 +210,22 @@ export const channelsList: ChannelDetailsFragment[] = [
country: "Poland", country: "Poland",
__typename: "CountryDisplay", __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", country: "Poland",
__typename: "CountryDisplay", __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] & { 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 ShippingZones from "@saleor/channels/components/ShippingZones";
import Warehouses from "@saleor/channels/components/Warehouses"; import Warehouses from "@saleor/channels/components/Warehouses";
import { channelsListUrl } from "@saleor/channels/urls"; import { channelsListUrl } from "@saleor/channels/urls";
@ -7,12 +8,14 @@ import Grid from "@saleor/components/Grid";
import Savebar from "@saleor/components/Savebar"; import Savebar from "@saleor/components/Savebar";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import { import {
AllocationStrategyEnum,
ChannelDetailsFragment, ChannelDetailsFragment,
ChannelErrorFragment, ChannelErrorFragment,
CountryCode, CountryCode,
CountryFragment, CountryFragment,
SearchShippingZonesQuery, SearchShippingZonesQuery,
SearchWarehousesQuery, SearchWarehousesQuery,
StockSettingsInput,
} from "@saleor/graphql"; } from "@saleor/graphql";
import { SearchData } from "@saleor/hooks/makeTopLevelSearch"; import { SearchData } from "@saleor/hooks/makeTopLevelSearch";
import { getParsedSearchData } from "@saleor/hooks/makeTopLevelSearch/utils"; import { getParsedSearchData } from "@saleor/hooks/makeTopLevelSearch/utils";
@ -20,10 +23,6 @@ import { SubmitPromise } from "@saleor/hooks/useForm";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui"; import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
import {
getById,
getByUnmatchingId,
} from "@saleor/orders/components/OrderReturnPage/utils";
import { FetchMoreProps, RelayToFlat } from "@saleor/types"; import { FetchMoreProps, RelayToFlat } from "@saleor/types";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { mapCountriesToChoices } from "@saleor/utils/maps"; import { mapCountriesToChoices } from "@saleor/utils/maps";
@ -31,8 +30,14 @@ import React, { useState } from "react";
import { ChannelForm, FormData } from "../../components/ChannelForm"; import { ChannelForm, FormData } from "../../components/ChannelForm";
import { ChannelStatus } from "../../components/ChannelStatus/ChannelStatus"; import { ChannelStatus } from "../../components/ChannelStatus/ChannelStatus";
import {
createShippingZoneAddHandler,
createShippingZoneRemoveHandler,
createWarehouseAddHandler,
createWarehouseRemoveHandler,
createWarehouseReorderHandler,
} from "./handlers";
import { ChannelShippingZones, ChannelWarehouses } from "./types"; import { ChannelShippingZones, ChannelWarehouses } from "./types";
import { getUpdatedIdsWithNewId, getUpdatedIdsWithoutNewId } from "./utils";
export interface ChannelDetailsPageProps<TErrors> { export interface ChannelDetailsPageProps<TErrors> {
channel?: ChannelDetailsFragment; channel?: ChannelDetailsFragment;
@ -87,16 +92,14 @@ const ChannelDetailsPage = function<TErrors>({
setSelectedCountryDisplayName, setSelectedCountryDisplayName,
] = useStateFromProps(channel?.defaultCountry.country || ""); ] = useStateFromProps(channel?.defaultCountry.country || "");
const [shippingZonesToDisplay, setShippingZonesToDisplay] = useStateFromProps<
ChannelShippingZones
>(channelShippingZones);
const [warehousesToDisplay, setWarehousesToDisplay] = useStateFromProps<
ChannelWarehouses
>(channelWarehouses);
const countryChoices = mapCountriesToChoices(countries || []); 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 = { const initialData: FormData = {
currencyCode: "", currencyCode: "",
name: "", name: "",
@ -107,15 +110,22 @@ const ChannelDetailsPage = function<TErrors>({
warehousesIdsToRemove: [], warehousesIdsToRemove: [],
defaultCountry: (defaultCountry?.code || "") as CountryCode, defaultCountry: (defaultCountry?.code || "") as CountryCode,
...formData, ...formData,
...initialStockSettings,
shippingZonesToDisplay: channelShippingZones,
warehousesToDisplay: channelWarehouses,
}; };
const getFilteredShippingZonesChoices = (): RelayToFlat<SearchShippingZonesQuery["search"]> => const getFilteredShippingZonesChoices = (
shippingZonesToDisplay: ChannelShippingZones,
): RelayToFlat<SearchShippingZonesQuery["search"]> =>
getParsedSearchData({ data: searchShippingZonesData }).filter( getParsedSearchData({ data: searchShippingZonesData }).filter(
({ id: searchedZoneId }) => ({ id: searchedZoneId }) =>
!shippingZonesToDisplay.some(({ id }) => id === searchedZoneId), !shippingZonesToDisplay.some(({ id }) => id === searchedZoneId),
); );
const getFilteredWarehousesChoices = (): RelayToFlat<SearchWarehousesQuery["search"]> => const getFilteredWarehousesChoices = (
warehousesToDisplay: ChannelWarehouses,
): RelayToFlat<SearchWarehousesQuery["search"]> =>
getParsedSearchData({ data: searchWarehousesData }).filter( getParsedSearchData({ data: searchWarehousesData }).filter(
({ id: searchedWarehouseId }) => ({ id: searchedWarehouseId }) =>
!warehousesToDisplay.some(({ id }) => id === searchedWarehouseId), !warehousesToDisplay.some(({ id }) => id === searchedWarehouseId),
@ -151,91 +161,30 @@ const ChannelDetailsPage = function<TErrors>({
countryChoices, countryChoices,
); );
const addShippingZone = (zoneId: string) => { const addShippingZone = createShippingZoneAddHandler(
triggerChange(); data,
searchShippingZonesData,
set,
triggerChange,
);
const removeShippingZone = createShippingZoneRemoveHandler(
data,
set,
triggerChange,
);
set({ const addWarehouse = createWarehouseAddHandler(
...data, data,
shippingZonesIdsToRemove: getUpdatedIdsWithoutNewId( searchWarehousesData,
data.shippingZonesIdsToRemove, set,
zoneId, triggerChange,
), );
shippingZonesIdsToAdd: getUpdatedIdsWithNewId( const removeWarehouse = createWarehouseRemoveHandler(
data.shippingZonesIdsToAdd, data,
zoneId, set,
), triggerChange,
}); );
const reorderWarehouse = createWarehouseReorderHandler(data, set);
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 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)),
);
};
return ( return (
<> <>
@ -266,23 +215,36 @@ const ChannelDetailsPage = function<TErrors>({
</> </>
)} )}
<ShippingZones <ShippingZones
shippingZonesChoices={getFilteredShippingZonesChoices()} shippingZonesChoices={getFilteredShippingZonesChoices(
shippingZones={shippingZonesToDisplay} data.shippingZonesToDisplay,
)}
shippingZones={data.shippingZonesToDisplay}
addShippingZone={addShippingZone} addShippingZone={addShippingZone}
removeShippingZone={removeShippingZone} removeShippingZone={removeShippingZone}
searchShippingZones={searchShippingZones} searchShippingZones={searchShippingZones}
fetchMoreShippingZones={fetchMoreShippingZones} fetchMoreShippingZones={fetchMoreShippingZones}
totalCount={allShippingZonesCount} totalCount={allShippingZonesCount}
loading={disabled}
/> />
<CardSpacer /> <CardSpacer />
<Warehouses <Warehouses
warehousesChoices={getFilteredWarehousesChoices()} warehousesChoices={getFilteredWarehousesChoices(
warehouses={warehousesToDisplay} data.warehousesToDisplay,
)}
warehouses={data.warehousesToDisplay}
addWarehouse={addWarehouse} addWarehouse={addWarehouse}
removeWarehouse={removeWarehouse} removeWarehouse={removeWarehouse}
searchWarehouses={searchWarehouses} searchWarehouses={searchWarehouses}
fetchMoreWarehouses={fetchMoreWarehouses} fetchMoreWarehouses={fetchMoreWarehouses}
totalCount={allWarehousesCount} totalCount={allWarehousesCount}
reorderWarehouses={reorderWarehouse}
loading={disabled}
/>
<CardSpacer />
<ChannelAllocationStrategy
data={data}
disabled={disabled}
onChange={change}
/> />
</div> </div>
</Grid> </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 { import { ChannelShippingZonesQuery, WarehouseFragment } from "@saleor/graphql";
ChannelShippingZonesQuery,
ChannelWarehousesQuery,
} from "@saleor/graphql";
import { RelayToFlat } from "@saleor/types"; import { RelayToFlat } from "@saleor/types";
export type ChannelShippingZones = RelayToFlat< export type ChannelShippingZones = RelayToFlat<
@ -10,8 +7,6 @@ export type ChannelShippingZones = RelayToFlat<
export type ChannelShippingZone = ChannelShippingZones[0]; export type ChannelShippingZone = ChannelShippingZones[0];
export type ChannelWarehouses = RelayToFlat< export type ChannelWarehouses = WarehouseFragment[];
ChannelWarehousesQuery["warehouses"]
>;
export type ChannelWarehouse = ChannelWarehouses[0]; 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 { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import { import {
ChannelCreateMutation, ChannelCreateMutation,
ChannelErrorFragment,
useChannelCreateMutation, useChannelCreateMutation,
useChannelReorderWarehousesMutation,
useShippingZonesCountQuery, useShippingZonesCountQuery,
useWarehousesCountQuery, useWarehousesCountQuery,
} from "@saleor/graphql"; } from "@saleor/graphql";
@ -19,12 +21,14 @@ import { sectionNames } from "@saleor/intl";
import { extractMutationErrors } from "@saleor/misc"; import { extractMutationErrors } from "@saleor/misc";
import useShippingZonesSearch from "@saleor/searches/useShippingZonesSearch"; import useShippingZonesSearch from "@saleor/searches/useShippingZonesSearch";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch"; import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import getChannelsErrorMessage from "@saleor/utils/errors/channels";
import currencyCodes from "currency-codes"; import currencyCodes from "currency-codes";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import ChannelDetailsPage from "../../pages/ChannelDetailsPage"; import ChannelDetailsPage from "../../pages/ChannelDetailsPage";
import { channelPath, channelsListUrl } from "../../urls"; import { channelPath, channelsListUrl } from "../../urls";
import { calculateItemsOrderMoves } from "../ChannelDetails/handlers";
export const ChannelCreateView = ({}) => { export const ChannelCreateView = ({}) => {
const navigate = useNavigator(); const navigate = useNavigator();
@ -32,38 +36,74 @@ export const ChannelCreateView = ({}) => {
const intl = useIntl(); const intl = useIntl();
const shop = useShop(); const shop = useShop();
const [createChannel, createChannelOpts] = useChannelCreateMutation({ const handleError = (error: ChannelErrorFragment) => {
onCompleted: ({ notify({
channelCreate: { errors, channel }, status: "error",
}: ChannelCreateMutation) => { text: getChannelsErrorMessage(error, intl),
notify(getDefaultNotifierSuccessErrorData(errors, intl)); });
};
if (!errors.length) { const [createChannel, createChannelOpts] = useChannelCreateMutation({
navigate(channelPath(channel.id)); 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, shippingZonesIdsToAdd,
shippingZonesIdsToRemove, shippingZonesIdsToRemove,
warehousesIdsToAdd, warehousesIdsToAdd,
warehousesIdsToRemove, warehousesIdsToRemove,
warehousesToDisplay,
shippingZonesToDisplay,
currencyCode, currencyCode,
allocationStrategy,
...rest ...rest
}: FormData) => }: FormData) => {
extractMutationErrors( const createChannelMutation = createChannel({
createChannel({ variables: {
variables: { input: {
input: { ...rest,
...rest, currencyCode: currencyCode.toUpperCase(),
currencyCode: currencyCode.toUpperCase(), addShippingZones: shippingZonesIdsToAdd,
addShippingZones: shippingZonesIdsToAdd, addWarehouses: warehousesIdsToAdd,
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 { const {
data: shippingZonesCountData, data: shippingZonesCountData,

View file

@ -14,10 +14,10 @@ import {
useChannelDeactivateMutation, useChannelDeactivateMutation,
useChannelDeleteMutation, useChannelDeleteMutation,
useChannelQuery, useChannelQuery,
useChannelReorderWarehousesMutation,
useChannelShippingZonesQuery, useChannelShippingZonesQuery,
useChannelsQuery, useChannelsQuery,
useChannelUpdateMutation, useChannelUpdateMutation,
useChannelWarehousesQuery,
useShippingZonesCountQuery, useShippingZonesCountQuery,
useWarehousesCountQuery, useWarehousesCountQuery,
} from "@saleor/graphql"; } from "@saleor/graphql";
@ -32,6 +32,7 @@ import useShippingZonesSearch from "@saleor/searches/useShippingZonesSearch";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch"; import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import getChannelsErrorMessage from "@saleor/utils/errors/channels"; import getChannelsErrorMessage from "@saleor/utils/errors/channels";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import { mapEdgesToItems } from "@saleor/utils/maps";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
@ -42,6 +43,7 @@ import {
ChannelUrlDialog, ChannelUrlDialog,
ChannelUrlQueryParams, ChannelUrlQueryParams,
} from "../../urls"; } from "../../urls";
import { calculateItemsOrderMoves } from "./handlers";
interface ChannelDetailsProps { interface ChannelDetailsProps {
id: string; id: string;
@ -102,31 +104,66 @@ 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, name,
slug, slug,
shippingZonesIdsToRemove, shippingZonesIdsToRemove,
shippingZonesIdsToAdd, shippingZonesIdsToAdd,
warehousesIdsToRemove, warehousesIdsToRemove,
warehousesIdsToAdd, warehousesIdsToAdd,
warehousesToDisplay,
defaultCountry, defaultCountry,
}: FormData) => allocationStrategy,
extractMutationErrors( }: FormData) => {
updateChannel({ const updateChannelMutation = updateChannel({
variables: { variables: {
id: data?.channel.id, id: data?.channel.id,
input: { input: {
name, name,
slug, slug,
defaultCountry, defaultCountry,
addShippingZones: shippingZonesIdsToAdd, addShippingZones: shippingZonesIdsToAdd,
removeShippingZones: shippingZonesIdsToRemove, removeShippingZones: shippingZonesIdsToRemove,
addWarehouses: warehousesIdsToAdd, addWarehouses: warehousesIdsToAdd,
removeWarehouses: warehousesIdsToRemove, 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 onDeleteCompleted = (data: ChannelDeleteMutation) => {
const errors = data.channelDelete.errors; const errors = data.channelDelete.errors;
@ -194,17 +231,6 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
loading: warehousesCountLoading, loading: warehousesCountLoading,
} = useWarehousesCountQuery(); } = useWarehousesCountQuery();
const {
data: channelWarehousesData,
loading: channelsWarehousesLoading,
} = useChannelWarehousesQuery({
variables: {
filter: {
channels: [id],
},
},
});
const { const {
loadMore: fetchMoreWarehouses, loadMore: fetchMoreWarehouses,
search: searchWarehouses, search: searchWarehouses,
@ -213,6 +239,11 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
variables: DEFAULT_INITIAL_SEARCH_DATA, variables: DEFAULT_INITIAL_SEARCH_DATA,
}); });
const channelWarehouses = data?.channel?.warehouses || [];
const channelShippingZones = mapEdgesToItems(
channelShippingZonesData?.shippingZones,
);
return ( return (
<> <>
<WindowTitle <WindowTitle
@ -228,9 +259,7 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
</Backlink> </Backlink>
<PageHeader title={data?.channel?.name} /> <PageHeader title={data?.channel?.name} />
<ChannelDetailsPage <ChannelDetailsPage
channelShippingZones={channelShippingZonesData?.shippingZones?.edges?.map( channelShippingZones={channelShippingZones}
({ node }) => node,
)}
allShippingZonesCount={ allShippingZonesCount={
shippingZonesCountData?.shippingZones?.totalCount shippingZonesCountData?.shippingZones?.totalCount
} }
@ -240,9 +269,7 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
searchShippingZonesResult, searchShippingZonesResult,
fetchMoreShippingZones, fetchMoreShippingZones,
)} )}
channelWarehouses={channelWarehousesData?.warehouses?.edges?.map( channelWarehouses={channelWarehouses}
({ node }) => node,
)}
allWarehousesCount={warehousesCountData?.warehouses?.totalCount} allWarehousesCount={warehousesCountData?.warehouses?.totalCount}
searchWarehouses={searchWarehouses} searchWarehouses={searchWarehouses}
searchWarehousesData={searchWarehousesResult.data} searchWarehousesData={searchWarehousesResult.data}
@ -253,11 +280,11 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
channel={data?.channel} channel={data?.channel}
disabled={ disabled={
updateChannelOpts.loading || updateChannelOpts.loading ||
reorderChannelWarehousesOpts.loading ||
loading || loading ||
shippingZonesCountLoading || shippingZonesCountLoading ||
warehousesCountLoading || warehousesCountLoading ||
channelsShippingZonesLoading || channelsShippingZonesLoading
channelsWarehousesLoading
} }
disabledStatus={ disabledStatus={
activateChannelOpts.loading || deactivateChannelOpts.loading 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 code
country country
} }
stockSettings {
allocationStrategy
}
} }
`; `;
@ -26,5 +29,8 @@ export const channelDetailsFragment = gql`
fragment ChannelDetails on Channel { fragment ChannelDetails on Channel {
...Channel ...Channel
hasOrders hasOrders
warehouses {
...Warehouse
}
} }
`; `;

View file

@ -185,14 +185,27 @@ export const ChannelFragmentDoc = gql`
code code
country country
} }
stockSettings {
allocationStrategy
}
}
`;
export const WarehouseFragmentDoc = gql`
fragment Warehouse on Warehouse {
id
name
} }
`; `;
export const ChannelDetailsFragmentDoc = gql` export const ChannelDetailsFragmentDoc = gql`
fragment ChannelDetails on Channel { fragment ChannelDetails on Channel {
...Channel ...Channel
hasOrders hasOrders
warehouses {
...Warehouse
}
} }
${ChannelFragmentDoc}`; ${ChannelFragmentDoc}
${WarehouseFragmentDoc}`;
export const CollectionFragmentDoc = gql` export const CollectionFragmentDoc = gql`
fragment Collection on Collection { fragment Collection on Collection {
id id
@ -1203,12 +1216,6 @@ export const OrderEventFragmentDoc = gql`
} }
} }
`; `;
export const WarehouseFragmentDoc = gql`
fragment Warehouse on Warehouse {
id
name
}
`;
export const StockFragmentDoc = gql` export const StockFragmentDoc = gql`
fragment Stock on Stock { fragment Stock on Stock {
id id
@ -4387,6 +4394,46 @@ export function useChannelDeactivateMutation(baseOptions?: ApolloReactHooks.Muta
export type ChannelDeactivateMutationHookResult = ReturnType<typeof useChannelDeactivateMutation>; export type ChannelDeactivateMutationHookResult = ReturnType<typeof useChannelDeactivateMutation>;
export type ChannelDeactivateMutationResult = Apollo.MutationResult<Types.ChannelDeactivateMutation>; export type ChannelDeactivateMutationResult = Apollo.MutationResult<Types.ChannelDeactivateMutation>;
export type ChannelDeactivateMutationOptions = Apollo.BaseMutationOptions<Types.ChannelDeactivateMutation, Types.ChannelDeactivateMutationVariables>; 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` export const BaseChannelsDocument = gql`
query BaseChannels { query BaseChannels {
channels { channels {
@ -16487,46 +16534,6 @@ export function useWarehouseDetailsLazyQuery(baseOptions?: ApolloReactHooks.Lazy
export type WarehouseDetailsQueryHookResult = ReturnType<typeof useWarehouseDetailsQuery>; export type WarehouseDetailsQueryHookResult = ReturnType<typeof useWarehouseDetailsQuery>;
export type WarehouseDetailsLazyQueryHookResult = ReturnType<typeof useWarehouseDetailsLazyQuery>; export type WarehouseDetailsLazyQueryHookResult = ReturnType<typeof useWarehouseDetailsLazyQuery>;
export type WarehouseDetailsQueryResult = Apollo.QueryResult<Types.WarehouseDetailsQuery, Types.WarehouseDetailsQueryVariables>; 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` export const WarehousesCountDocument = gql`
query WarehousesCount { query WarehousesCount {
warehouses { warehouses {

File diff suppressed because one or more lines are too long

View file

@ -156,6 +156,21 @@ export enum AddressTypeEnum {
SHIPPING = 'SHIPPING' 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. */ /** An enumeration. */
export enum AppErrorCode { export enum AppErrorCode {
FORBIDDEN = 'FORBIDDEN', FORBIDDEN = 'FORBIDDEN',
@ -606,6 +621,14 @@ export type CategorySortingInput = {
export type ChannelCreateInput = { export type ChannelCreateInput = {
/** isActive flag. */ /** isActive flag. */
isActive?: InputMaybe<Scalars['Boolean']>; 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. */ /** List of shipping zones to assign to the channel. */
addShippingZones?: InputMaybe<Array<Scalars['ID']>>; addShippingZones?: InputMaybe<Array<Scalars['ID']>>;
/** /**
@ -653,6 +676,14 @@ export enum ChannelErrorCode {
export type ChannelUpdateInput = { export type ChannelUpdateInput = {
/** isActive flag. */ /** isActive flag. */
isActive?: InputMaybe<Scalars['Boolean']>; 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. */ /** List of shipping zones to assign to the channel. */
addShippingZones?: InputMaybe<Array<Scalars['ID']>>; addShippingZones?: InputMaybe<Array<Scalars['ID']>>;
/** /**
@ -3031,6 +3062,12 @@ export type OrderFulfillInput = {
notifyCustomer?: InputMaybe<Scalars['Boolean']>; notifyCustomer?: InputMaybe<Scalars['Boolean']>;
/** If true, then allow proceed fulfillment when stock is exceeded. */ /** If true, then allow proceed fulfillment when stock is exceeded. */
allowStockToBeExceeded?: InputMaybe<Scalars['Boolean']>; allowStockToBeExceeded?: InputMaybe<Scalars['Boolean']>;
/**
* Fulfillment tracking number.
*
* Added in Saleor 3.6.
*/
trackingNumber?: InputMaybe<Scalars['String']>;
}; };
export type OrderFulfillLineInput = { export type OrderFulfillLineInput = {
@ -3963,6 +4000,8 @@ export type ProductVariantBulkCreateInput = {
attributes: Array<BulkAttributeValueInput>; attributes: Array<BulkAttributeValueInput>;
/** Stock keeping unit. */ /** Stock keeping unit. */
sku?: InputMaybe<Scalars['String']>; 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. */ /** 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']>; trackInventory?: InputMaybe<Scalars['Boolean']>;
/** Weight of the Product Variant. */ /** Weight of the Product Variant. */
@ -4011,6 +4050,8 @@ export type ProductVariantCreateInput = {
attributes: Array<AttributeValueInput>; attributes: Array<AttributeValueInput>;
/** Stock keeping unit. */ /** Stock keeping unit. */
sku?: InputMaybe<Scalars['String']>; 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. */ /** 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']>; trackInventory?: InputMaybe<Scalars['Boolean']>;
/** Weight of the Product Variant. */ /** Weight of the Product Variant. */
@ -4050,6 +4091,8 @@ export type ProductVariantInput = {
attributes?: InputMaybe<Array<AttributeValueInput>>; attributes?: InputMaybe<Array<AttributeValueInput>>;
/** Stock keeping unit. */ /** Stock keeping unit. */
sku?: InputMaybe<Scalars['String']>; 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. */ /** 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']>; trackInventory?: InputMaybe<Scalars['Boolean']>;
/** Weight of the Product Variant. */ /** Weight of the Product Variant. */
@ -4493,6 +4536,11 @@ export type StockInput = {
quantity: Scalars['Int']; 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. */ /** Enum representing the type of a payment storage in a gateway. */
export enum StorePaymentMethodEnum { export enum StorePaymentMethodEnum {
/** On session storage type. The payment is stored only to be reused when the customer is present in the checkout flow. */ /** 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']>; app?: InputMaybe<Scalars['ID']>;
/** Determine if webhook will be set active or not. */ /** Determine if webhook will be set active or not. */
isActive?: InputMaybe<Scalars['Boolean']>; 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']>; secretKey?: InputMaybe<Scalars['String']>;
/** /**
* Subscription query used to define a webhook payload. * Subscription query used to define a webhook payload.
@ -5562,7 +5614,11 @@ export type WebhookUpdateInput = {
app?: InputMaybe<Scalars['ID']>; app?: InputMaybe<Scalars['ID']>;
/** Determine if webhook will be set active or not. */ /** Determine if webhook will be set active or not. */
isActive?: InputMaybe<Scalars['Boolean']>; 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']>; secretKey?: InputMaybe<Scalars['String']>;
/** /**
* Subscription query used to define a webhook payload. * 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<{ export type ChannelUpdateMutationVariables = Exact<{
id: Scalars['ID']; 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<{ export type ChannelDeleteMutationVariables = Exact<{
id: Scalars['ID']; 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<{ export type ChannelDeactivateMutationVariables = Exact<{
id: Scalars['ID']; 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 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 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<{ export type ChannelQueryVariables = Exact<{
id: Scalars['ID']; 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<{ export type CollectionUpdateMutationVariables = Exact<{
id: Scalars['ID']; 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<{ export type CreateCustomerAddressMutationVariables = Exact<{
id: Scalars['ID']; 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<{ export type UpdateCustomerAddressMutationVariables = Exact<{
id: Scalars['ID']; 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<{ export type BulkRemoveCustomersMutationVariables = Exact<{
ids: Array<Scalars['ID']> | Scalars['ID']; 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; }>; 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 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 }; 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 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 }> }; 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 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; }>; 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` export const warehousesCount = gql`
query WarehousesCount { query WarehousesCount {
warehouses { warehouses {