Add assign warehouse section in channel page (#2127)
* Add assign warehouse section in channel page * Update data-test-ids on channel page * Update channel page form details * Update shipping zones and warehouses cards in chaannel page * Assigning warehouses by channel in product and variant pages (#2135) * Assigning warehouses by channel in product and variant pages * Disable warehouse assignment when no channel on variant page * Update products stocks section messages
This commit is contained in:
parent
eb58e2c8ed
commit
f1ffb5093f
46 changed files with 4263 additions and 1560 deletions
|
@ -9,7 +9,10 @@ export const ADD_CHANNEL_FORM_SELECTORS = {
|
||||||
slugValidationMessage: "[data-test-id='slug-text-input-helper-text']",
|
slugValidationMessage: "[data-test-id='slug-text-input-helper-text']",
|
||||||
currencyAutocompleteDropdown:
|
currencyAutocompleteDropdown:
|
||||||
"[data-test-id='single-autocomplete-select-option'][data-test-type='custom']",
|
"[data-test-id='single-autocomplete-select-option'][data-test-type='custom']",
|
||||||
addShippingZoneButton: '[data-test-id="add-shipping-zone-button"]',
|
addShippingZoneButton: '[data-test-id="shipping-add-button"]',
|
||||||
|
addWarehouseButton: '[data-test-id="warehouse-add-button"]',
|
||||||
shippingAutocompleteSelect: "[data-test-id='shipping-auto-complete-select']",
|
shippingAutocompleteSelect: "[data-test-id='shipping-auto-complete-select']",
|
||||||
countryAutocompleteInput: '[data-test-id="country-select-input"]'
|
warehouseAutocompleteSelect:
|
||||||
|
"[data-test-id='warehouse-auto-complete-select']",
|
||||||
|
countryAutocompleteInput: '[data-test-id="country-select-input"]',
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,10 +27,6 @@
|
||||||
"context": "order shipping method name",
|
"context": "order shipping method name",
|
||||||
"string": "Shipping"
|
"string": "Shipping"
|
||||||
},
|
},
|
||||||
"+G9l7u": {
|
|
||||||
"context": "all selected zones card message",
|
|
||||||
"string": "All available shipping zones have been selected"
|
|
||||||
},
|
|
||||||
"+HuipK": {
|
"+HuipK": {
|
||||||
"context": "variant sku",
|
"context": "variant sku",
|
||||||
"string": "SKU {sku}"
|
"string": "SKU {sku}"
|
||||||
|
@ -170,6 +166,10 @@
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Add Tracking Code"
|
"string": "Add Tracking Code"
|
||||||
},
|
},
|
||||||
|
"/C//FB": {
|
||||||
|
"context": "header, allocated product quantity",
|
||||||
|
"string": "Allocated"
|
||||||
|
},
|
||||||
"/JENWS": {
|
"/JENWS": {
|
||||||
"string": "Reduced Tax Rates"
|
"string": "Reduced Tax Rates"
|
||||||
},
|
},
|
||||||
|
@ -224,6 +224,10 @@
|
||||||
"/glQgs": {
|
"/glQgs": {
|
||||||
"string": "No channels found"
|
"string": "No channels found"
|
||||||
},
|
},
|
||||||
|
"/iijFq": {
|
||||||
|
"context": "input label",
|
||||||
|
"string": "Global threshold"
|
||||||
|
},
|
||||||
"/kWzY1": {
|
"/kWzY1": {
|
||||||
"string": "Are you sure you want to delete this address from users address book?"
|
"string": "Are you sure you want to delete this address from users address book?"
|
||||||
},
|
},
|
||||||
|
@ -601,9 +605,6 @@
|
||||||
"context": "payment status",
|
"context": "payment status",
|
||||||
"string": "Fully paid"
|
"string": "Fully paid"
|
||||||
},
|
},
|
||||||
"2qJc9y": {
|
|
||||||
"string": "CANCEL END DATE"
|
|
||||||
},
|
|
||||||
"2r4cTE": {
|
"2r4cTE": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Enable Dark Mode"
|
"string": "Enable Dark Mode"
|
||||||
|
@ -1126,9 +1127,6 @@
|
||||||
"context": "attribute value deleted",
|
"context": "attribute value deleted",
|
||||||
"string": "Value deleted"
|
"string": "Value deleted"
|
||||||
},
|
},
|
||||||
"7Ii5ZQ": {
|
|
||||||
"string": "SETUP END DATE"
|
|
||||||
},
|
|
||||||
"7JAAul": {
|
"7JAAul": {
|
||||||
"context": "product field",
|
"context": "product field",
|
||||||
"string": "Export Product Weight"
|
"string": "Export Product Weight"
|
||||||
|
@ -1206,10 +1204,6 @@
|
||||||
"context": "info text",
|
"context": "info text",
|
||||||
"string": "This rate will apply to all orders"
|
"string": "This rate will apply to all orders"
|
||||||
},
|
},
|
||||||
"7wkGxW": {
|
|
||||||
"context": "app has been installed",
|
|
||||||
"string": "{unitsLeft} units left"
|
|
||||||
},
|
|
||||||
"7yKZvp": {
|
"7yKZvp": {
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "User Status"
|
"string": "User Status"
|
||||||
|
@ -1226,10 +1220,6 @@
|
||||||
"context": "navigator placeholder",
|
"context": "navigator placeholder",
|
||||||
"string": "Order Number"
|
"string": "Order Number"
|
||||||
},
|
},
|
||||||
"8CbACQ": {
|
|
||||||
"context": "add shipping zone title",
|
|
||||||
"string": "Add Shipping Zones"
|
|
||||||
},
|
|
||||||
"8EGagh": {
|
"8EGagh": {
|
||||||
"context": "search box label",
|
"context": "search box label",
|
||||||
"string": "Filter Countries"
|
"string": "Filter Countries"
|
||||||
|
@ -1331,6 +1321,10 @@
|
||||||
"context": "option",
|
"context": "option",
|
||||||
"string": "Create single variant"
|
"string": "Create single variant"
|
||||||
},
|
},
|
||||||
|
"9IWg/f": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "SETUP END DATE"
|
||||||
|
},
|
||||||
"9OtpHt": {
|
"9OtpHt": {
|
||||||
"string": "Order line deleted"
|
"string": "Order line deleted"
|
||||||
},
|
},
|
||||||
|
@ -1462,10 +1456,6 @@
|
||||||
"context": "order refund subtitle",
|
"context": "order refund subtitle",
|
||||||
"string": "Refunded items can't be fulfilled"
|
"string": "Refunded items can't be fulfilled"
|
||||||
},
|
},
|
||||||
"ANRRpG": {
|
|
||||||
"context": "card title",
|
|
||||||
"string": "Shipping Zones"
|
|
||||||
},
|
|
||||||
"AOI4LW": {
|
"AOI4LW": {
|
||||||
"context": "navigator placeholder",
|
"context": "navigator placeholder",
|
||||||
"string": "Search in Catalog"
|
"string": "Search in Catalog"
|
||||||
|
@ -1710,10 +1700,6 @@
|
||||||
"context": "dialog content",
|
"context": "dialog content",
|
||||||
"string": "{counter,plural,one{Are you sure you want to delete this shipping zone?} other{Are you sure you want to delete {displayQuantity} shipping zones?}}"
|
"string": "{counter,plural,one{Are you sure you want to delete this shipping zone?} other{Are you sure you want to delete {displayQuantity} shipping zones?}}"
|
||||||
},
|
},
|
||||||
"CEavJt": {
|
|
||||||
"context": "section header",
|
|
||||||
"string": "Unlimited"
|
|
||||||
},
|
|
||||||
"CG+awx": {
|
"CG+awx": {
|
||||||
"context": "dialog content",
|
"context": "dialog content",
|
||||||
"string": "Which address would you like to use as shipping address for selected customer:"
|
"string": "Which address would you like to use as shipping address for selected customer:"
|
||||||
|
@ -2033,6 +2019,10 @@
|
||||||
"ErNH3D": {
|
"ErNH3D": {
|
||||||
"string": "Define where this attribute should be used in Saleor system"
|
"string": "Define where this attribute should be used in Saleor system"
|
||||||
},
|
},
|
||||||
|
"ErvPaM": {
|
||||||
|
"context": "header",
|
||||||
|
"string": "Warehouse Name"
|
||||||
|
},
|
||||||
"EsZH44": {
|
"EsZH44": {
|
||||||
"context": "VariantDetailsChannelsAvailabilityCard item subtitle hidden",
|
"context": "VariantDetailsChannelsAvailabilityCard item subtitle hidden",
|
||||||
"string": "Hidden"
|
"string": "Hidden"
|
||||||
|
@ -2041,6 +2031,10 @@
|
||||||
"context": "header",
|
"context": "header",
|
||||||
"string": "{pluginName} Details"
|
"string": "{pluginName} Details"
|
||||||
},
|
},
|
||||||
|
"EuOXmr": {
|
||||||
|
"context": "add items title",
|
||||||
|
"string": "Add {itemsName}"
|
||||||
|
},
|
||||||
"Ev6SEF": {
|
"Ev6SEF": {
|
||||||
"string": "New Password"
|
"string": "New Password"
|
||||||
},
|
},
|
||||||
|
@ -2428,6 +2422,10 @@
|
||||||
"context": "number of variants",
|
"context": "number of variants",
|
||||||
"string": "Variants ({quantity})"
|
"string": "Variants ({quantity})"
|
||||||
},
|
},
|
||||||
|
"HYC6cH": {
|
||||||
|
"context": "input description",
|
||||||
|
"string": "Threshold that cannot be exceeded even if per channel thresholds are still available"
|
||||||
|
},
|
||||||
"HYHLsB": {
|
"HYHLsB": {
|
||||||
"context": "product field",
|
"context": "product field",
|
||||||
"string": "Export Variant ID"
|
"string": "Export Variant ID"
|
||||||
|
@ -2585,6 +2583,10 @@
|
||||||
"context": "header",
|
"context": "header",
|
||||||
"string": "Edit Media"
|
"string": "Edit Media"
|
||||||
},
|
},
|
||||||
|
"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"
|
||||||
|
@ -2748,6 +2750,10 @@
|
||||||
"context": "section header",
|
"context": "section header",
|
||||||
"string": "Organize Product"
|
"string": "Organize Product"
|
||||||
},
|
},
|
||||||
|
"JkO0jp": {
|
||||||
|
"context": "input description",
|
||||||
|
"string": "{unitsLeft} units left"
|
||||||
|
},
|
||||||
"JnzDrI": {
|
"JnzDrI": {
|
||||||
"context": "discount type",
|
"context": "discount type",
|
||||||
"string": "Fixed Amount"
|
"string": "Fixed Amount"
|
||||||
|
@ -2779,10 +2785,6 @@
|
||||||
"context": "select product informations to be exported",
|
"context": "select product informations to be exported",
|
||||||
"string": "Information exported:"
|
"string": "Information exported:"
|
||||||
},
|
},
|
||||||
"JyQEHU": {
|
|
||||||
"context": "tabel column header",
|
|
||||||
"string": "Channels"
|
|
||||||
},
|
|
||||||
"JyQoES": {
|
"JyQoES": {
|
||||||
"context": "delete attribute value",
|
"context": "delete attribute value",
|
||||||
"string": "Are you sure you want to delete \"{name}\" value?"
|
"string": "Are you sure you want to delete \"{name}\" value?"
|
||||||
|
@ -2847,10 +2849,6 @@
|
||||||
"context": "product available for purchase date",
|
"context": "product available for purchase date",
|
||||||
"string": "will become available on {date}"
|
"string": "will become available on {date}"
|
||||||
},
|
},
|
||||||
"KTAg0f": {
|
|
||||||
"context": "tabel column header",
|
|
||||||
"string": "Warehouse Name"
|
|
||||||
},
|
|
||||||
"KXkdMH": {
|
"KXkdMH": {
|
||||||
"context": "order discount removed title",
|
"context": "order discount removed title",
|
||||||
"string": "Order discount was removed by"
|
"string": "Order discount was removed by"
|
||||||
|
@ -3202,9 +3200,6 @@
|
||||||
"context": "gift card bulk create success dialog content",
|
"context": "gift card bulk create success dialog content",
|
||||||
"string": "We have issued all of your requested gift cards. You can download the list of new gift cards using the button below."
|
"string": "We have issued all of your requested gift cards. You can download the list of new gift cards using the button below."
|
||||||
},
|
},
|
||||||
"NcY4ph": {
|
|
||||||
"string": "Threshold that cannot be exceeded even if per channel thresholds are still available"
|
|
||||||
},
|
|
||||||
"Nfh9QM": {
|
"Nfh9QM": {
|
||||||
"context": "checkbox gift cards label description",
|
"context": "checkbox gift cards label description",
|
||||||
"string": "when activated non-shippable gift cards will be automatically set as fulfilled and sent to customer"
|
"string": "when activated non-shippable gift cards will be automatically set as fulfilled and sent to customer"
|
||||||
|
@ -3699,9 +3694,6 @@
|
||||||
"context": "use attribute in filtering",
|
"context": "use attribute in filtering",
|
||||||
"string": "Use in Filtering"
|
"string": "Use in Filtering"
|
||||||
},
|
},
|
||||||
"RJ5QxE": {
|
|
||||||
"string": "Global threshold"
|
|
||||||
},
|
|
||||||
"RLBLPQ": {
|
"RLBLPQ": {
|
||||||
"context": "no warehouses info",
|
"context": "no warehouses info",
|
||||||
"string": "There are no warehouses set up for your store. To add stock quantity to the product please <a>configure a warehouse</a>"
|
"string": "There are no warehouses set up for your store. To add stock quantity to the product please <a>configure a warehouse</a>"
|
||||||
|
@ -3833,6 +3825,10 @@
|
||||||
"SKFr04": {
|
"SKFr04": {
|
||||||
"string": "Attribute not found."
|
"string": "Attribute not found."
|
||||||
},
|
},
|
||||||
|
"SM+yG0": {
|
||||||
|
"context": "input label",
|
||||||
|
"string": "SKU (Stock Keeping Unit)"
|
||||||
|
},
|
||||||
"SMakqb": {
|
"SMakqb": {
|
||||||
"context": "customer contact section, header",
|
"context": "customer contact section, header",
|
||||||
"string": "Contact Information"
|
"string": "Contact Information"
|
||||||
|
@ -4208,6 +4204,10 @@
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Edit Shipping Method"
|
"string": "Edit Shipping Method"
|
||||||
},
|
},
|
||||||
|
"V1MytH": {
|
||||||
|
"context": "shipping zones section name",
|
||||||
|
"string": "Shipping Zones"
|
||||||
|
},
|
||||||
"V1mqpZ": {
|
"V1mqpZ": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Create Permission Group"
|
"string": "Create Permission Group"
|
||||||
|
@ -4466,6 +4466,10 @@
|
||||||
"context": "gift card bulk create success dialog title",
|
"context": "gift card bulk create success dialog title",
|
||||||
"string": "Bulk Issue Gift Cards"
|
"string": "Bulk Issue Gift Cards"
|
||||||
},
|
},
|
||||||
|
"Wyl25+": {
|
||||||
|
"context": "product inventory, checkbox description",
|
||||||
|
"string": "Active inventory tracking will automatically calculate changes of stock"
|
||||||
|
},
|
||||||
"WzA5Ll": {
|
"WzA5Ll": {
|
||||||
"string": "Cannot remove user from last group"
|
"string": "Cannot remove user from last group"
|
||||||
},
|
},
|
||||||
|
@ -5395,9 +5399,6 @@
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Choose file"
|
"string": "Choose file"
|
||||||
},
|
},
|
||||||
"ekXood": {
|
|
||||||
"string": "Unlimited"
|
|
||||||
},
|
|
||||||
"erC44f": {
|
"erC44f": {
|
||||||
"context": "filters error messages dependencies missing",
|
"context": "filters error messages dependencies missing",
|
||||||
"string": "Filter requires other filters: {dependencies}"
|
"string": "Filter requires other filters: {dependencies}"
|
||||||
|
@ -5550,10 +5551,6 @@
|
||||||
"g/BrOt": {
|
"g/BrOt": {
|
||||||
"string": "Url has invalid format"
|
"string": "Url has invalid format"
|
||||||
},
|
},
|
||||||
"g/FRtd": {
|
|
||||||
"context": "table column header, allocated product quantity",
|
|
||||||
"string": "Allocated"
|
|
||||||
},
|
|
||||||
"g1WQlC": {
|
"g1WQlC": {
|
||||||
"context": "page title",
|
"context": "page title",
|
||||||
"string": "Summary"
|
"string": "Summary"
|
||||||
|
@ -5612,10 +5609,6 @@
|
||||||
"context": "plugin filters error messages channels",
|
"context": "plugin filters error messages channels",
|
||||||
"string": "No channels selected"
|
"string": "No channels selected"
|
||||||
},
|
},
|
||||||
"ge/xFX": {
|
|
||||||
"context": "table column header",
|
|
||||||
"string": "Quantity"
|
|
||||||
},
|
|
||||||
"ghGLbJ": {
|
"ghGLbJ": {
|
||||||
"context": "OrderPayment click&collect shipping method",
|
"context": "OrderPayment click&collect shipping method",
|
||||||
"string": "click&collect"
|
"string": "click&collect"
|
||||||
|
@ -5643,10 +5636,6 @@
|
||||||
"context": "page header",
|
"context": "page header",
|
||||||
"string": "Create Page"
|
"string": "Create Page"
|
||||||
},
|
},
|
||||||
"gtKcPf": {
|
|
||||||
"context": "title",
|
|
||||||
"string": "{zonesCount} / {totalCount} shipping zones"
|
|
||||||
},
|
|
||||||
"gvOzOl": {
|
"gvOzOl": {
|
||||||
"string": "Page Title"
|
"string": "Page Title"
|
||||||
},
|
},
|
||||||
|
@ -5890,9 +5879,6 @@
|
||||||
"context": "attribute values",
|
"context": "attribute values",
|
||||||
"string": "Values"
|
"string": "Values"
|
||||||
},
|
},
|
||||||
"jABdx1": {
|
|
||||||
"string": "Active inventory tracking will automatically calculate changes of stock"
|
|
||||||
},
|
|
||||||
"jBu2yj": {
|
"jBu2yj": {
|
||||||
"context": "acre-inch unit",
|
"context": "acre-inch unit",
|
||||||
"string": "acre-inch"
|
"string": "acre-inch"
|
||||||
|
@ -7174,10 +7160,18 @@
|
||||||
"context": "Header row stock label",
|
"context": "Header row stock label",
|
||||||
"string": "Stock"
|
"string": "Stock"
|
||||||
},
|
},
|
||||||
|
"taS/08": {
|
||||||
|
"context": "variant stocks section subtitle",
|
||||||
|
"string": "Assign this variant to a channel in the product channel manager to define warehouses allocation"
|
||||||
|
},
|
||||||
"taX/V3": {
|
"taX/V3": {
|
||||||
"context": "order total amount",
|
"context": "order total amount",
|
||||||
"string": "Total"
|
"string": "Total"
|
||||||
},
|
},
|
||||||
|
"tlGXkh": {
|
||||||
|
"context": "input description",
|
||||||
|
"string": "Unlimited"
|
||||||
|
},
|
||||||
"toDL5R": {
|
"toDL5R": {
|
||||||
"context": "order status",
|
"context": "order status",
|
||||||
"string": "Draft"
|
"string": "Draft"
|
||||||
|
@ -7247,6 +7241,10 @@
|
||||||
"context": "app has been removed",
|
"context": "app has been removed",
|
||||||
"string": "App successfully removed"
|
"string": "App successfully removed"
|
||||||
},
|
},
|
||||||
|
"uKlrEk": {
|
||||||
|
"context": "all selected items message",
|
||||||
|
"string": "All available {itemsName} have been selected"
|
||||||
|
},
|
||||||
"uMpv1v": {
|
"uMpv1v": {
|
||||||
"string": "Fulfillment successfully cancelled"
|
"string": "Fulfillment successfully cancelled"
|
||||||
},
|
},
|
||||||
|
@ -7364,6 +7362,10 @@
|
||||||
"v3WWK+": {
|
"v3WWK+": {
|
||||||
"string": "Status is invalid"
|
"string": "Status is invalid"
|
||||||
},
|
},
|
||||||
|
"v9ILn/": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "CANCEL END DATE"
|
||||||
|
},
|
||||||
"vC8vyb": {
|
"vC8vyb": {
|
||||||
"context": "enabled status option label",
|
"context": "enabled status option label",
|
||||||
"string": "Enabled"
|
"string": "Enabled"
|
||||||
|
@ -7628,9 +7630,6 @@
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Assign Variant"
|
"string": "Assign Variant"
|
||||||
},
|
},
|
||||||
"xB7BTp": {
|
|
||||||
"string": "SKU (Stock Keeping Unit)"
|
|
||||||
},
|
|
||||||
"xHj9Qe": {
|
"xHj9Qe": {
|
||||||
"context": "gift card settings header",
|
"context": "gift card settings header",
|
||||||
"string": "Gift Cards Settings"
|
"string": "Gift Cards Settings"
|
||||||
|
|
257
schema.graphql
257
schema.graphql
|
@ -493,7 +493,7 @@ type App implements Node & ObjectWithMetadata {
|
||||||
"""Description of the data privacy defined for this app."""
|
"""Description of the data privacy defined for this app."""
|
||||||
dataPrivacy: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `dataPrivacyUrl` instead.")
|
dataPrivacy: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `dataPrivacyUrl` instead.")
|
||||||
|
|
||||||
"""Url to details about the privacy policy on the app owner page."""
|
"""URL to details about the privacy policy on the app owner page."""
|
||||||
dataPrivacyUrl: String
|
dataPrivacyUrl: String
|
||||||
|
|
||||||
"""Homepage of the app."""
|
"""Homepage of the app."""
|
||||||
|
@ -502,14 +502,14 @@ type App implements Node & ObjectWithMetadata {
|
||||||
"""Support page for the app."""
|
"""Support page for the app."""
|
||||||
supportUrl: String
|
supportUrl: String
|
||||||
|
|
||||||
"""Url to iframe with the configuration for the app."""
|
"""URL to iframe with the configuration for the app."""
|
||||||
configurationUrl: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `appUrl` instead.")
|
configurationUrl: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `appUrl` instead.")
|
||||||
|
|
||||||
"""Url to iframe with the app."""
|
"""URL to iframe with the app."""
|
||||||
appUrl: String
|
appUrl: String
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Url to manifest used during app's installation.
|
URL to manifest used during app's installation.
|
||||||
|
|
||||||
Added in Saleor 3.5.
|
Added in Saleor 3.5.
|
||||||
"""
|
"""
|
||||||
|
@ -1711,6 +1711,29 @@ input AttributeValueCreateInput {
|
||||||
name: String!
|
name: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AttributeValueCreated implements Event {
|
||||||
|
"""Time of the event."""
|
||||||
|
issuedAt: DateTime
|
||||||
|
|
||||||
|
"""Saleor version that triggered the event."""
|
||||||
|
version: String
|
||||||
|
|
||||||
|
"""The user or application that triggered the event."""
|
||||||
|
issuingPrincipal: IssuingPrincipal
|
||||||
|
|
||||||
|
"""The application receiving the webhook."""
|
||||||
|
recipient: App
|
||||||
|
|
||||||
|
"""
|
||||||
|
The attribute value the event relates to.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
attributeValue: AttributeValue
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Deletes a value of an attribute.
|
Deletes a value of an attribute.
|
||||||
|
|
||||||
|
@ -1724,6 +1747,29 @@ type AttributeValueDelete {
|
||||||
attributeValue: AttributeValue
|
attributeValue: AttributeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AttributeValueDeleted implements Event {
|
||||||
|
"""Time of the event."""
|
||||||
|
issuedAt: DateTime
|
||||||
|
|
||||||
|
"""Saleor version that triggered the event."""
|
||||||
|
version: String
|
||||||
|
|
||||||
|
"""The user or application that triggered the event."""
|
||||||
|
issuingPrincipal: IssuingPrincipal
|
||||||
|
|
||||||
|
"""The application receiving the webhook."""
|
||||||
|
recipient: App
|
||||||
|
|
||||||
|
"""
|
||||||
|
The attribute value the event relates to.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
attributeValue: AttributeValue
|
||||||
|
}
|
||||||
|
|
||||||
input AttributeValueFilterInput {
|
input AttributeValueFilterInput {
|
||||||
search: String
|
search: String
|
||||||
ids: [ID!]
|
ids: [ID!]
|
||||||
|
@ -1871,6 +1917,29 @@ input AttributeValueUpdateInput {
|
||||||
name: String
|
name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AttributeValueUpdated implements Event {
|
||||||
|
"""Time of the event."""
|
||||||
|
issuedAt: DateTime
|
||||||
|
|
||||||
|
"""Saleor version that triggered the event."""
|
||||||
|
version: String
|
||||||
|
|
||||||
|
"""The user or application that triggered the event."""
|
||||||
|
issuingPrincipal: IssuingPrincipal
|
||||||
|
|
||||||
|
"""The application receiving the webhook."""
|
||||||
|
recipient: App
|
||||||
|
|
||||||
|
"""
|
||||||
|
The attribute value the event relates to.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
attributeValue: AttributeValue
|
||||||
|
}
|
||||||
|
|
||||||
input BulkAttributeValueInput {
|
input BulkAttributeValueInput {
|
||||||
"""ID of the selected attribute."""
|
"""ID of the selected attribute."""
|
||||||
id: ID
|
id: ID
|
||||||
|
@ -2373,6 +2442,15 @@ type Channel implements Node {
|
||||||
Added in Saleor 3.1.
|
Added in Saleor 3.1.
|
||||||
"""
|
"""
|
||||||
defaultCountry: CountryDisplay!
|
defaultCountry: CountryDisplay!
|
||||||
|
|
||||||
|
"""
|
||||||
|
List of warehouses assigned to this channel.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
warehouses: [Warehouse!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -2402,6 +2480,18 @@ input ChannelCreateInput {
|
||||||
"""isActive flag."""
|
"""isActive flag."""
|
||||||
isActive: Boolean
|
isActive: Boolean
|
||||||
|
|
||||||
|
"""List of shipping zones to assign to the channel."""
|
||||||
|
addShippingZones: [ID!]
|
||||||
|
|
||||||
|
"""
|
||||||
|
List of warehouses to assign to the channel.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
addWarehouses: [ID!]
|
||||||
|
|
||||||
"""Name of the channel."""
|
"""Name of the channel."""
|
||||||
name: String!
|
name: String!
|
||||||
|
|
||||||
|
@ -2415,11 +2505,10 @@ input ChannelCreateInput {
|
||||||
Default country for the channel. Default country can be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided.
|
Default country for the channel. Default country can be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided.
|
||||||
|
|
||||||
Added in Saleor 3.1.
|
Added in Saleor 3.1.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
"""
|
"""
|
||||||
defaultCountry: CountryCode!
|
defaultCountry: CountryCode!
|
||||||
|
|
||||||
"""List of shipping zones to assign to the channel."""
|
|
||||||
addShippingZones: [ID!]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelCreated implements Event {
|
type ChannelCreated implements Event {
|
||||||
|
@ -2510,6 +2599,9 @@ type ChannelError {
|
||||||
|
|
||||||
"""List of shipping zone IDs which causes the error."""
|
"""List of shipping zone IDs which causes the error."""
|
||||||
shippingZones: [ID!]
|
shippingZones: [ID!]
|
||||||
|
|
||||||
|
"""List of warehouses IDs which causes the error."""
|
||||||
|
warehouses: [ID!]
|
||||||
}
|
}
|
||||||
|
|
||||||
"""An enumeration."""
|
"""An enumeration."""
|
||||||
|
@ -2563,6 +2655,18 @@ input ChannelUpdateInput {
|
||||||
"""isActive flag."""
|
"""isActive flag."""
|
||||||
isActive: Boolean
|
isActive: Boolean
|
||||||
|
|
||||||
|
"""List of shipping zones to assign to the channel."""
|
||||||
|
addShippingZones: [ID!]
|
||||||
|
|
||||||
|
"""
|
||||||
|
List of warehouses to assign to the channel.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
addWarehouses: [ID!]
|
||||||
|
|
||||||
"""Name of the channel."""
|
"""Name of the channel."""
|
||||||
name: String
|
name: String
|
||||||
|
|
||||||
|
@ -2576,11 +2680,17 @@ input ChannelUpdateInput {
|
||||||
"""
|
"""
|
||||||
defaultCountry: CountryCode
|
defaultCountry: CountryCode
|
||||||
|
|
||||||
"""List of shipping zones to assign to the channel."""
|
|
||||||
addShippingZones: [ID!]
|
|
||||||
|
|
||||||
"""List of shipping zones to unassign from the channel."""
|
"""List of shipping zones to unassign from the channel."""
|
||||||
removeShippingZones: [ID!]
|
removeShippingZones: [ID!]
|
||||||
|
|
||||||
|
"""
|
||||||
|
List of warehouses to unassign from the channel.
|
||||||
|
|
||||||
|
Added in Saleor 3.5.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
removeWarehouses: [ID!]
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelUpdated implements Event {
|
type ChannelUpdated implements Event {
|
||||||
|
@ -2972,8 +3082,54 @@ type CheckoutLanguageCodeUpdate {
|
||||||
}
|
}
|
||||||
|
|
||||||
"""Represents an item in the checkout."""
|
"""Represents an item in the checkout."""
|
||||||
type CheckoutLine implements Node {
|
type CheckoutLine implements Node & ObjectWithMetadata {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
|
"""List of private metadata items. Requires staff permissions to access."""
|
||||||
|
privateMetadata: [MetadataItem!]!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A single key from private metadata. Requires staff permissions to access.
|
||||||
|
|
||||||
|
Tip: Use GraphQL aliases to fetch multiple keys.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
privateMetafield(key: String!): String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
privateMetafields(keys: [String!]): Metadata
|
||||||
|
|
||||||
|
"""List of public metadata items. Can be accessed without permissions."""
|
||||||
|
metadata: [MetadataItem!]!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A single key from public metadata.
|
||||||
|
|
||||||
|
Tip: Use GraphQL aliases to fetch multiple keys.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
metafield(key: String!): String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Public metadata. Use `keys` to control which fields you want to include. The default is to include everything.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
metafields(keys: [String!]): Metadata
|
||||||
variant: ProductVariant!
|
variant: ProductVariant!
|
||||||
quantity: Int!
|
quantity: Int!
|
||||||
|
|
||||||
|
@ -7520,7 +7676,7 @@ type Manifest {
|
||||||
permissions: [Permission!]
|
permissions: [Permission!]
|
||||||
appUrl: String
|
appUrl: String
|
||||||
|
|
||||||
"""Url to iframe with the configuration for the app."""
|
"""URL to iframe with the configuration for the app."""
|
||||||
configurationUrl: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `appUrl` instead.")
|
configurationUrl: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `appUrl` instead.")
|
||||||
tokenTargetUrl: String
|
tokenTargetUrl: String
|
||||||
|
|
||||||
|
@ -12818,8 +12974,54 @@ type OrderFullyPaid implements Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
"""Represents order line of particular order."""
|
"""Represents order line of particular order."""
|
||||||
type OrderLine implements Node {
|
type OrderLine implements Node & ObjectWithMetadata {
|
||||||
id: ID!
|
id: ID!
|
||||||
|
|
||||||
|
"""List of private metadata items. Requires staff permissions to access."""
|
||||||
|
privateMetadata: [MetadataItem!]!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A single key from private metadata. Requires staff permissions to access.
|
||||||
|
|
||||||
|
Tip: Use GraphQL aliases to fetch multiple keys.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
privateMetafield(key: String!): String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
privateMetafields(keys: [String!]): Metadata
|
||||||
|
|
||||||
|
"""List of public metadata items. Can be accessed without permissions."""
|
||||||
|
metadata: [MetadataItem!]!
|
||||||
|
|
||||||
|
"""
|
||||||
|
A single key from public metadata.
|
||||||
|
|
||||||
|
Tip: Use GraphQL aliases to fetch multiple keys.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
metafield(key: String!): String
|
||||||
|
|
||||||
|
"""
|
||||||
|
Public metadata. Use `keys` to control which fields you want to include. The default is to include everything.
|
||||||
|
|
||||||
|
Added in Saleor 3.3.
|
||||||
|
|
||||||
|
Note: this API is currently in Feature Preview and can be subject to changes at later point.
|
||||||
|
"""
|
||||||
|
metafields(keys: [String!]): Metadata
|
||||||
productName: String!
|
productName: String!
|
||||||
variantName: String!
|
variantName: String!
|
||||||
productSku: String
|
productSku: String
|
||||||
|
@ -21946,6 +22148,7 @@ input WarehouseFilterInput {
|
||||||
search: String
|
search: String
|
||||||
ids: [ID!]
|
ids: [ID!]
|
||||||
isPrivate: Boolean
|
isPrivate: Boolean
|
||||||
|
channels: [ID!]
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -22247,6 +22450,15 @@ enum WebhookEventTypeAsyncEnum {
|
||||||
"""An attribute is deleted."""
|
"""An attribute is deleted."""
|
||||||
ATTRIBUTE_DELETED
|
ATTRIBUTE_DELETED
|
||||||
|
|
||||||
|
"""A new attribute value is created."""
|
||||||
|
ATTRIBUTE_VALUE_CREATED
|
||||||
|
|
||||||
|
"""An attribute value is updated."""
|
||||||
|
ATTRIBUTE_VALUE_UPDATED
|
||||||
|
|
||||||
|
"""An attribute value is deleted."""
|
||||||
|
ATTRIBUTE_VALUE_DELETED
|
||||||
|
|
||||||
"""A new category created."""
|
"""A new category created."""
|
||||||
CATEGORY_CREATED
|
CATEGORY_CREATED
|
||||||
|
|
||||||
|
@ -22341,6 +22553,9 @@ enum WebhookEventTypeAsyncEnum {
|
||||||
"""A customer account is updated."""
|
"""A customer account is updated."""
|
||||||
CUSTOMER_UPDATED
|
CUSTOMER_UPDATED
|
||||||
|
|
||||||
|
"""A customer account is deleted."""
|
||||||
|
CUSTOMER_DELETED
|
||||||
|
|
||||||
"""A new collection is created."""
|
"""A new collection is created."""
|
||||||
COLLECTION_CREATED
|
COLLECTION_CREATED
|
||||||
|
|
||||||
|
@ -22488,6 +22703,15 @@ enum WebhookEventTypeEnum {
|
||||||
"""An attribute is deleted."""
|
"""An attribute is deleted."""
|
||||||
ATTRIBUTE_DELETED
|
ATTRIBUTE_DELETED
|
||||||
|
|
||||||
|
"""A new attribute value is created."""
|
||||||
|
ATTRIBUTE_VALUE_CREATED
|
||||||
|
|
||||||
|
"""An attribute value is updated."""
|
||||||
|
ATTRIBUTE_VALUE_UPDATED
|
||||||
|
|
||||||
|
"""An attribute value is deleted."""
|
||||||
|
ATTRIBUTE_VALUE_DELETED
|
||||||
|
|
||||||
"""A new category created."""
|
"""A new category created."""
|
||||||
CATEGORY_CREATED
|
CATEGORY_CREATED
|
||||||
|
|
||||||
|
@ -22582,6 +22806,9 @@ enum WebhookEventTypeEnum {
|
||||||
"""A customer account is updated."""
|
"""A customer account is updated."""
|
||||||
CUSTOMER_UPDATED
|
CUSTOMER_UPDATED
|
||||||
|
|
||||||
|
"""A customer account is deleted."""
|
||||||
|
CUSTOMER_DELETED
|
||||||
|
|
||||||
"""A new collection is created."""
|
"""A new collection is created."""
|
||||||
COLLECTION_CREATED
|
COLLECTION_CREATED
|
||||||
|
|
||||||
|
@ -22730,6 +22957,9 @@ enum WebhookSampleEventTypeEnum {
|
||||||
ATTRIBUTE_CREATED
|
ATTRIBUTE_CREATED
|
||||||
ATTRIBUTE_UPDATED
|
ATTRIBUTE_UPDATED
|
||||||
ATTRIBUTE_DELETED
|
ATTRIBUTE_DELETED
|
||||||
|
ATTRIBUTE_VALUE_CREATED
|
||||||
|
ATTRIBUTE_VALUE_UPDATED
|
||||||
|
ATTRIBUTE_VALUE_DELETED
|
||||||
CATEGORY_CREATED
|
CATEGORY_CREATED
|
||||||
CATEGORY_UPDATED
|
CATEGORY_UPDATED
|
||||||
CATEGORY_DELETED
|
CATEGORY_DELETED
|
||||||
|
@ -22764,6 +22994,7 @@ enum WebhookSampleEventTypeEnum {
|
||||||
INVOICE_SENT
|
INVOICE_SENT
|
||||||
CUSTOMER_CREATED
|
CUSTOMER_CREATED
|
||||||
CUSTOMER_UPDATED
|
CUSTOMER_UPDATED
|
||||||
|
CUSTOMER_DELETED
|
||||||
COLLECTION_CREATED
|
COLLECTION_CREATED
|
||||||
COLLECTION_UPDATED
|
COLLECTION_UPDATED
|
||||||
COLLECTION_DELETED
|
COLLECTION_DELETED
|
||||||
|
|
60
src/channels/components/AssignmentList/AssignmentList.tsx
Normal file
60
src/channels/components/AssignmentList/AssignmentList.tsx
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import { Accordion, Divider, Typography } from "@material-ui/core";
|
||||||
|
import React from "react";
|
||||||
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import AssignmentListFooter from "./AssignmentListFooter";
|
||||||
|
import AssignmentListHeader from "./AssignmentListHeader";
|
||||||
|
import Item from "./Item";
|
||||||
|
import { useExpanderStyles, useStyles } from "./styles";
|
||||||
|
import { AssignmentListProps } from "./types";
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
allSelectedMessage: {
|
||||||
|
id: "uKlrEk",
|
||||||
|
defaultMessage: "All available {itemsName} have been selected",
|
||||||
|
description: "all selected items message",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const AssignmentList: React.FC<AssignmentListProps> = props => {
|
||||||
|
const {
|
||||||
|
items,
|
||||||
|
itemsName,
|
||||||
|
fetchMoreItems: { totalCount },
|
||||||
|
removeItem,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles();
|
||||||
|
const expanderClasses = useExpanderStyles();
|
||||||
|
|
||||||
|
const hasMoreItemsToBeSelected = totalCount !== items.length;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion classes={expanderClasses}>
|
||||||
|
<AssignmentListHeader
|
||||||
|
assignCount={items.length}
|
||||||
|
totalCount={totalCount}
|
||||||
|
itemsName={itemsName}
|
||||||
|
/>
|
||||||
|
<Divider />
|
||||||
|
{items.map(item => (
|
||||||
|
<Item key={item.id} item={item} onDelete={removeItem} />
|
||||||
|
))}
|
||||||
|
{hasMoreItemsToBeSelected ? (
|
||||||
|
<AssignmentListFooter {...props} />
|
||||||
|
) : (
|
||||||
|
<Typography
|
||||||
|
color="textSecondary"
|
||||||
|
variant="subtitle1"
|
||||||
|
className={classes.infoMessage}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.allSelectedMessage, {
|
||||||
|
itemsName: itemsName.toLowerCase(),
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default AssignmentList;
|
|
@ -1,82 +1,87 @@
|
||||||
import { ClickAwayListener } from "@material-ui/core";
|
import { ClickAwayListener } from "@material-ui/core";
|
||||||
import { ChannelShippingZones } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
|
||||||
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
import SingleAutocompleteSelectField from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import CardAddItemsFooter from "@saleor/products/components/ProductStocks/CardAddItemsFooter";
|
import CardAddItemsFooter from "@saleor/products/components/ProductStocks/CardAddItemsFooter";
|
||||||
import { mapNodeToChoice } from "@saleor/utils/maps";
|
import { mapNodeToChoice } from "@saleor/utils/maps";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { defineMessages } from "react-intl";
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
import useStyles from "./styles";
|
import { useStyles } from "./styles";
|
||||||
import { ShippingZonesProps } from "./types";
|
import { AssignItem, AssignmentListProps } from "./types";
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
addZoneTitle: {
|
addItemTitle: {
|
||||||
id: "8CbACQ",
|
id: "EuOXmr",
|
||||||
defaultMessage: "Add Shipping Zones",
|
defaultMessage: "Add {itemsName}",
|
||||||
description: "add shipping zone title",
|
description: "add items title",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
type ShippingZonesCardListFooterProps = ShippingZonesProps;
|
type AssignmentListFooterProps = AssignmentListProps;
|
||||||
|
|
||||||
const ShippingZonesCardListFooter: React.FC<ShippingZonesCardListFooterProps> = ({
|
const AssignmentListFooter: React.FC<AssignmentListFooterProps> = ({
|
||||||
shippingZonesChoices,
|
items,
|
||||||
searchShippingZones,
|
itemsChoices,
|
||||||
fetchMoreShippingZones,
|
itemsName,
|
||||||
addShippingZone,
|
inputName,
|
||||||
shippingZones,
|
dataTestId,
|
||||||
|
addItem,
|
||||||
|
searchItems,
|
||||||
|
fetchMoreItems,
|
||||||
}) => {
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const [isChoicesSelectShown, setIsChoicesSelectShown] = useState(false);
|
const [isChoicesSelectShown, setIsChoicesSelectShown] = useState(false);
|
||||||
const shippingZonesRef = useRef<ChannelShippingZones>(shippingZones);
|
const itemsRef = useRef<AssignItem[]>(items);
|
||||||
|
|
||||||
// select holds value and displays it so it needs remounting
|
// select holds value and displays it so it needs remounting
|
||||||
// to display empty input after adding new zone
|
// to display empty input after adding new zone
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (shippingZones.length > shippingZonesRef.current.length) {
|
if (items.length > itemsRef.current.length) {
|
||||||
setIsChoicesSelectShown(true);
|
setIsChoicesSelectShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
shippingZonesRef.current = shippingZones;
|
itemsRef.current = items;
|
||||||
}, [shippingZones]);
|
}, [items]);
|
||||||
|
|
||||||
const handleChoice = ({ target }) => {
|
const handleChoice = ({ target }) => {
|
||||||
setIsChoicesSelectShown(false);
|
setIsChoicesSelectShown(false);
|
||||||
addShippingZone(target.value);
|
addItem(target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFooterClickAway = () => {
|
const handleFooterClickAway = () => {
|
||||||
setIsChoicesSelectShown(false);
|
setIsChoicesSelectShown(false);
|
||||||
searchShippingZones("");
|
searchItems("");
|
||||||
};
|
};
|
||||||
|
|
||||||
return isChoicesSelectShown ? (
|
return isChoicesSelectShown ? (
|
||||||
<ClickAwayListener onClickAway={handleFooterClickAway}>
|
<ClickAwayListener onClickAway={handleFooterClickAway}>
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
data-test-id="shipping-auto-complete-select"
|
data-test-id={`${dataTestId}-auto-complete-select`}
|
||||||
value=""
|
value=""
|
||||||
displayValue=""
|
displayValue=""
|
||||||
nakedInput
|
nakedInput
|
||||||
name="shippingZone"
|
name={inputName}
|
||||||
choices={mapNodeToChoice(shippingZonesChoices)}
|
choices={mapNodeToChoice(itemsChoices)}
|
||||||
fetchChoices={searchShippingZones}
|
fetchChoices={searchItems}
|
||||||
onChange={handleChoice}
|
onChange={handleChoice}
|
||||||
{...fetchMoreShippingZones}
|
{...fetchMoreItems}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</ClickAwayListener>
|
</ClickAwayListener>
|
||||||
) : (
|
) : (
|
||||||
<CardAddItemsFooter
|
<CardAddItemsFooter
|
||||||
onAdd={() => setIsChoicesSelectShown(true)}
|
onAdd={() => setIsChoicesSelectShown(true)}
|
||||||
title={messages.addZoneTitle}
|
title={intl.formatMessage(messages.addItemTitle, {
|
||||||
|
itemsName,
|
||||||
|
})}
|
||||||
testIds={{
|
testIds={{
|
||||||
link: "add-shipping-zone-link",
|
link: `${dataTestId}-add-link`,
|
||||||
button: "add-shipping-zone-button",
|
button: `${dataTestId}-add-button`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShippingZonesCardListFooter;
|
export default AssignmentListFooter;
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { AccordionSummary, Typography } from "@material-ui/core";
|
||||||
|
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
||||||
|
import IconChevronDown from "@saleor/icons/ChevronDown";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { useHeaderStyles } from "./styles";
|
||||||
|
|
||||||
|
interface AssignmentListHeaderProps {
|
||||||
|
assignCount: number;
|
||||||
|
totalCount: number;
|
||||||
|
itemsName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AssignmentListHeader: React.FC<AssignmentListHeaderProps> = ({
|
||||||
|
assignCount,
|
||||||
|
totalCount,
|
||||||
|
itemsName,
|
||||||
|
}) => {
|
||||||
|
const classes = useHeaderStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.container}>
|
||||||
|
<AccordionSummary expandIcon={<IconChevronDown />} classes={classes}>
|
||||||
|
<Typography variant="subtitle2" color="textSecondary">
|
||||||
|
{`${assignCount} / ${totalCount} ${itemsName.toLowerCase()}`}
|
||||||
|
</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<HorizontalSpacer spacing={1.5} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AssignmentListHeader;
|
|
@ -1,21 +1,18 @@
|
||||||
import { Divider, Typography } from "@material-ui/core";
|
import { Divider, Typography } from "@material-ui/core";
|
||||||
import { ChannelShippingZone } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
|
||||||
import DeletableItem from "@saleor/components/DeletableItem";
|
import DeletableItem from "@saleor/components/DeletableItem";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import useStyles from "./styles";
|
import { useStyles } from "./styles";
|
||||||
|
import { AssignItem } from "./types";
|
||||||
|
|
||||||
interface ShippingZoneItemProps {
|
interface ItemProps {
|
||||||
zone: ChannelShippingZone;
|
item: AssignItem;
|
||||||
onDelete: (id: string) => void;
|
onDelete: (id: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ShippingZoneItem: React.FC<ShippingZoneItemProps> = ({
|
const Item: React.FC<ItemProps> = ({ item, onDelete }) => {
|
||||||
zone,
|
const { id, name } = item;
|
||||||
onDelete,
|
const classes = useStyles();
|
||||||
}) => {
|
|
||||||
const { id, name } = zone;
|
|
||||||
const classes = useStyles({});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -28,4 +25,4 @@ const ShippingZoneItem: React.FC<ShippingZoneItemProps> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ShippingZoneItem;
|
export default Item;
|
2
src/channels/components/AssignmentList/index.tsx
Normal file
2
src/channels/components/AssignmentList/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./AssignmentList";
|
||||||
|
export { default } from "./AssignmentList";
|
73
src/channels/components/AssignmentList/styles.ts
Normal file
73
src/channels/components/AssignmentList/styles.ts
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useExpanderStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
expanded: {},
|
||||||
|
root: {
|
||||||
|
boxShadow: "none",
|
||||||
|
padding: theme.spacing(1, 4),
|
||||||
|
|
||||||
|
"&:before": {
|
||||||
|
content: "none",
|
||||||
|
},
|
||||||
|
|
||||||
|
"&$expanded": {
|
||||||
|
margin: 0,
|
||||||
|
border: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ name: "Expander" },
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useHeaderStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
container: {
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
// empty expanded needed for mui to use root styles
|
||||||
|
expanded: {},
|
||||||
|
root: {
|
||||||
|
width: "100%",
|
||||||
|
border: "none",
|
||||||
|
marginRight: theme.spacing(1),
|
||||||
|
padding: 0,
|
||||||
|
paddingBottom: theme.spacing(2),
|
||||||
|
minHeight: 0,
|
||||||
|
|
||||||
|
"&$expanded": {
|
||||||
|
minHeight: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
margin: 0,
|
||||||
|
|
||||||
|
"&$expanded": {
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ name: "AssignmentListHeader" },
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
container: {
|
||||||
|
padding: theme.spacing(1, 0),
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
paddingRight: theme.spacing(1),
|
||||||
|
},
|
||||||
|
infoMessage: {
|
||||||
|
padding: theme.spacing(3),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ name: "AssignmentList" },
|
||||||
|
);
|
18
src/channels/components/AssignmentList/types.ts
Normal file
18
src/channels/components/AssignmentList/types.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { FetchMoreProps } from "@saleor/types";
|
||||||
|
|
||||||
|
export interface AssignItem {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AssignmentListProps {
|
||||||
|
items: AssignItem[];
|
||||||
|
itemsChoices: AssignItem[];
|
||||||
|
itemsName: string;
|
||||||
|
fetchMoreItems: FetchMoreProps;
|
||||||
|
inputName: string;
|
||||||
|
dataTestId: string;
|
||||||
|
addItem: (id: string) => void;
|
||||||
|
removeItem: (id: string) => void;
|
||||||
|
searchItems: (searchPhrase: string) => void;
|
||||||
|
}
|
|
@ -12,6 +12,8 @@ const props: ChannelFormProps = {
|
||||||
currencyCode: "euro",
|
currencyCode: "euro",
|
||||||
shippingZonesIdsToAdd: [],
|
shippingZonesIdsToAdd: [],
|
||||||
shippingZonesIdsToRemove: [],
|
shippingZonesIdsToRemove: [],
|
||||||
|
warehousesIdsToAdd: [],
|
||||||
|
warehousesIdsToRemove: [],
|
||||||
name: "Test",
|
name: "Test",
|
||||||
slug: "test",
|
slug: "test",
|
||||||
defaultCountry: CountryCode.PL,
|
defaultCountry: CountryCode.PL,
|
||||||
|
|
|
@ -29,6 +29,8 @@ export interface FormData {
|
||||||
slug: string;
|
slug: string;
|
||||||
shippingZonesIdsToAdd: string[];
|
shippingZonesIdsToAdd: string[];
|
||||||
shippingZonesIdsToRemove: string[];
|
shippingZonesIdsToRemove: string[];
|
||||||
|
warehousesIdsToAdd: string[];
|
||||||
|
warehousesIdsToRemove: string[];
|
||||||
defaultCountry: CountryCode;
|
defaultCountry: CountryCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import CommonDecorator from "@saleor/storybook/Decorator";
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import ShippingZonesCard from "./ShippingZonesCard";
|
import ShippingZones from "./ShippingZones";
|
||||||
|
|
||||||
const shippingZones = [
|
const shippingZones = [
|
||||||
{
|
{
|
||||||
|
@ -32,11 +32,11 @@ const baseProps = {
|
||||||
shippingZonesChoices: shippingZones as ChannelShippingZones,
|
shippingZonesChoices: shippingZones as ChannelShippingZones,
|
||||||
};
|
};
|
||||||
|
|
||||||
storiesOf("Shipping zones card", module)
|
storiesOf("Shipping zones", module)
|
||||||
.addDecorator(CommonDecorator)
|
.addDecorator(CommonDecorator)
|
||||||
.add("with no options selected", () => <ShippingZonesCard {...baseProps} />)
|
.add("with no options selected", () => <ShippingZones {...baseProps} />)
|
||||||
.add("with options selected", () => (
|
.add("with options selected", () => (
|
||||||
<ShippingZonesCard
|
<ShippingZones
|
||||||
{...baseProps}
|
{...baseProps}
|
||||||
shippingZones={shippingZones as ChannelShippingZones}
|
shippingZones={shippingZones as ChannelShippingZones}
|
||||||
/>
|
/>
|
63
src/channels/components/ShippingZones/ShippingZones.tsx
Normal file
63
src/channels/components/ShippingZones/ShippingZones.tsx
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import { Card, CardContent, Typography } from "@material-ui/core";
|
||||||
|
import { ChannelShippingZones } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import { SearchShippingZonesQuery } from "@saleor/graphql";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import { FetchMoreProps, RelayToFlat } from "@saleor/types";
|
||||||
|
import React from "react";
|
||||||
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import AssignmentList from "../AssignmentList";
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
subtitle: {
|
||||||
|
id: "Ic7Wln",
|
||||||
|
defaultMessage:
|
||||||
|
"Select shipping zones that will be supplied via this channel. You can assign shipping zones to multiple channels.",
|
||||||
|
description: "card subtitle",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
interface ShippingZonesProps {
|
||||||
|
addShippingZone: (id: string) => void;
|
||||||
|
removeShippingZone: (id: string) => void;
|
||||||
|
searchShippingZones: (searchPhrase: string) => void;
|
||||||
|
fetchMoreShippingZones: FetchMoreProps;
|
||||||
|
shippingZones: ChannelShippingZones;
|
||||||
|
shippingZonesChoices: RelayToFlat<SearchShippingZonesQuery["search"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShippingZones: React.FC<ShippingZonesProps> = props => {
|
||||||
|
const {
|
||||||
|
addShippingZone,
|
||||||
|
removeShippingZone,
|
||||||
|
searchShippingZones,
|
||||||
|
fetchMoreShippingZones,
|
||||||
|
shippingZones,
|
||||||
|
shippingZonesChoices,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle title={intl.formatMessage(sectionNames.shippingZones)} />
|
||||||
|
<CardContent>
|
||||||
|
<Typography>{intl.formatMessage(messages.subtitle)}</Typography>
|
||||||
|
</CardContent>
|
||||||
|
<AssignmentList
|
||||||
|
items={shippingZones}
|
||||||
|
itemsChoices={shippingZonesChoices}
|
||||||
|
addItem={addShippingZone}
|
||||||
|
removeItem={removeShippingZone}
|
||||||
|
searchItems={searchShippingZones}
|
||||||
|
fetchMoreItems={fetchMoreShippingZones}
|
||||||
|
dataTestId="shipping"
|
||||||
|
inputName="shippingZone"
|
||||||
|
itemsName={intl.formatMessage(sectionNames.shippingZones)}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShippingZones;
|
2
src/channels/components/ShippingZones/index.tsx
Normal file
2
src/channels/components/ShippingZones/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./ShippingZones";
|
||||||
|
export { default } from "./ShippingZones";
|
|
@ -1,25 +1,5 @@
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
import { makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
export const useExpanderStyles = makeStyles(
|
|
||||||
theme => ({
|
|
||||||
expanded: {},
|
|
||||||
root: {
|
|
||||||
boxShadow: "none",
|
|
||||||
padding: theme.spacing(1, 4),
|
|
||||||
|
|
||||||
"&:before": {
|
|
||||||
content: "none",
|
|
||||||
},
|
|
||||||
|
|
||||||
"&$expanded": {
|
|
||||||
margin: 0,
|
|
||||||
border: "none",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{ name: "Expander" },
|
|
||||||
);
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
container: {
|
container: {
|
||||||
|
@ -33,7 +13,7 @@ const useStyles = makeStyles(
|
||||||
paddingRight: theme.spacing(1),
|
paddingRight: theme.spacing(1),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{ name: "ShippingZonesCard" },
|
{ name: "ShippingZones" },
|
||||||
);
|
);
|
||||||
|
|
||||||
export default useStyles;
|
export default useStyles;
|
|
@ -1,93 +0,0 @@
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
Card,
|
|
||||||
CardContent,
|
|
||||||
Divider,
|
|
||||||
makeStyles,
|
|
||||||
Typography,
|
|
||||||
} from "@material-ui/core";
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
|
||||||
import React from "react";
|
|
||||||
import { defineMessages, useIntl } from "react-intl";
|
|
||||||
|
|
||||||
import ShippingZoneItem from "./ShippingZoneItem";
|
|
||||||
import ShippingZonesCardListFooter from "./ShippingZonesCardListFooter";
|
|
||||||
import ShippingZonesListHeader from "./ShippingZonesListHeader";
|
|
||||||
import { useExpanderStyles } from "./styles";
|
|
||||||
import { ShippingZonesProps } from "./types";
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
title: {
|
|
||||||
id: "ANRRpG",
|
|
||||||
defaultMessage: "Shipping Zones",
|
|
||||||
description: "card title",
|
|
||||||
},
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
allSelectedMessage: {
|
|
||||||
id: "+G9l7u",
|
|
||||||
defaultMessage: "All available shipping zones have been selected",
|
|
||||||
description: "all selected zones card message",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
|
||||||
theme => ({
|
|
||||||
infoMessage: {
|
|
||||||
padding: theme.spacing(3),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{ name: "ShippingZonesCard" },
|
|
||||||
);
|
|
||||||
|
|
||||||
type ShippingZonesCardProps = ShippingZonesProps;
|
|
||||||
|
|
||||||
const ShippingZonesCard: React.FC<ShippingZonesCardProps> = props => {
|
|
||||||
const {
|
|
||||||
shippingZones,
|
|
||||||
removeShippingZone,
|
|
||||||
fetchMoreShippingZones: { totalCount },
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const expanderClasses = useExpanderStyles({});
|
|
||||||
const classes = useStyles();
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
const hasMoreZonesToBeSelected = totalCount !== shippingZones.length;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<CardTitle title={intl.formatMessage(messages.title)} />
|
|
||||||
<CardContent>
|
|
||||||
<Typography>{intl.formatMessage(messages.subtitle)}</Typography>
|
|
||||||
</CardContent>
|
|
||||||
<Accordion classes={expanderClasses}>
|
|
||||||
<ShippingZonesListHeader
|
|
||||||
shippingZones={shippingZones}
|
|
||||||
totalCount={totalCount}
|
|
||||||
/>
|
|
||||||
<Divider />
|
|
||||||
{shippingZones.map(zone => (
|
|
||||||
<ShippingZoneItem zone={zone} onDelete={removeShippingZone} />
|
|
||||||
))}
|
|
||||||
{hasMoreZonesToBeSelected ? (
|
|
||||||
<ShippingZonesCardListFooter {...props} />
|
|
||||||
) : (
|
|
||||||
<Typography
|
|
||||||
color="textSecondary"
|
|
||||||
variant="subtitle1"
|
|
||||||
className={classes.infoMessage}
|
|
||||||
>
|
|
||||||
{intl.formatMessage(messages.allSelectedMessage)}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Accordion>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ShippingZonesCard;
|
|
|
@ -1,77 +0,0 @@
|
||||||
import { AccordionSummary, Typography } from "@material-ui/core";
|
|
||||||
import HorizontalSpacer from "@saleor/apps/components/HorizontalSpacer";
|
|
||||||
import { ChannelShippingZones } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
|
||||||
import IconChevronDown from "@saleor/icons/ChevronDown";
|
|
||||||
import { makeStyles } from "@saleor/macaw-ui";
|
|
||||||
import React from "react";
|
|
||||||
import { defineMessages, useIntl } from "react-intl";
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
|
||||||
theme => ({
|
|
||||||
container: {
|
|
||||||
width: "100%",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
},
|
|
||||||
// empty expanded needed for mui to use root styles
|
|
||||||
expanded: {},
|
|
||||||
root: {
|
|
||||||
width: "100%",
|
|
||||||
border: "none",
|
|
||||||
marginRight: theme.spacing(1),
|
|
||||||
padding: 0,
|
|
||||||
paddingBottom: theme.spacing(2),
|
|
||||||
minHeight: 0,
|
|
||||||
|
|
||||||
"&$expanded": {
|
|
||||||
minHeight: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
margin: 0,
|
|
||||||
|
|
||||||
"&$expanded": {
|
|
||||||
margin: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{ name: "ShippingZonesListHeader" },
|
|
||||||
);
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
title: {
|
|
||||||
id: "gtKcPf",
|
|
||||||
defaultMessage: "{zonesCount} / {totalCount} shipping zones",
|
|
||||||
description: "title",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
interface ShippingZonesListHeaderProps {
|
|
||||||
shippingZones: ChannelShippingZones;
|
|
||||||
totalCount: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ShippingZonesListHeader: React.FC<ShippingZonesListHeaderProps> = ({
|
|
||||||
shippingZones,
|
|
||||||
totalCount,
|
|
||||||
}) => {
|
|
||||||
const classes = useStyles({});
|
|
||||||
const intl = useIntl();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes.container}>
|
|
||||||
<AccordionSummary expandIcon={<IconChevronDown />} classes={classes}>
|
|
||||||
<Typography variant="subtitle2" color="textSecondary">
|
|
||||||
{intl.formatMessage(messages.title, {
|
|
||||||
zonesCount: shippingZones.length,
|
|
||||||
totalCount,
|
|
||||||
})}
|
|
||||||
</Typography>
|
|
||||||
</AccordionSummary>
|
|
||||||
<HorizontalSpacer spacing={1.5} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ShippingZonesListHeader;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export * from "./ShippingZonesCard";
|
|
||||||
export { default } from "./ShippingZonesCard";
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { ChannelShippingZones } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
|
||||||
import { SearchShippingZonesQuery } from "@saleor/graphql";
|
|
||||||
import { FetchMoreProps, RelayToFlat } from "@saleor/types";
|
|
||||||
|
|
||||||
export interface ShippingZonesProps {
|
|
||||||
addShippingZone: (id: string) => void;
|
|
||||||
removeShippingZone: (id: string) => void;
|
|
||||||
searchShippingZones: (searchPhrase: string) => void;
|
|
||||||
fetchMoreShippingZones: FetchMoreProps;
|
|
||||||
shippingZones: ChannelShippingZones;
|
|
||||||
shippingZonesChoices: RelayToFlat<SearchShippingZonesQuery["search"]>;
|
|
||||||
}
|
|
40
src/channels/components/Warehouses/Warehouses.stories.tsx
Normal file
40
src/channels/components/Warehouses/Warehouses.stories.tsx
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { ChannelWarehouses } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
||||||
|
import CommonDecorator from "@saleor/storybook/Decorator";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Warehouses from "./Warehouses";
|
||||||
|
|
||||||
|
const warehouses = [
|
||||||
|
{
|
||||||
|
__typename: "Warehouse",
|
||||||
|
id: "2",
|
||||||
|
name: "Fancy warehouse",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "Warehouse",
|
||||||
|
id: "3",
|
||||||
|
name: "Nice warehouse",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const baseProps = {
|
||||||
|
addWarehouse: () => undefined,
|
||||||
|
removeWarehouse: () => undefined,
|
||||||
|
searchWarehouses: () => undefined,
|
||||||
|
fetchMoreWarehouses: {
|
||||||
|
loading: false,
|
||||||
|
hasMore: false,
|
||||||
|
onFetchMore: () => undefined,
|
||||||
|
totalCount: 0,
|
||||||
|
},
|
||||||
|
warehouses: [],
|
||||||
|
warehousesChoices: warehouses as ChannelWarehouses,
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Warehouses", module)
|
||||||
|
.addDecorator(CommonDecorator)
|
||||||
|
.add("with no options selected", () => <Warehouses {...baseProps} />)
|
||||||
|
.add("with options selected", () => (
|
||||||
|
<Warehouses {...baseProps} warehouses={warehouses as ChannelWarehouses} />
|
||||||
|
));
|
62
src/channels/components/Warehouses/Warehouses.tsx
Normal file
62
src/channels/components/Warehouses/Warehouses.tsx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import { Card, CardContent, Typography } from "@material-ui/core";
|
||||||
|
import { ChannelWarehouses } from "@saleor/channels/pages/ChannelDetailsPage/types";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import { SearchWarehousesQuery } from "@saleor/graphql";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import { FetchMoreProps, RelayToFlat } from "@saleor/types";
|
||||||
|
import React from "react";
|
||||||
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import AssignmentList from "../AssignmentList";
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
subtitle: {
|
||||||
|
id: "ImTelT",
|
||||||
|
defaultMessage:
|
||||||
|
"Select warehouses that will be used in this channel. You can assign warehouses to multiple channels.",
|
||||||
|
description: "card subtitle",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
interface WarehousesProps {
|
||||||
|
addWarehouse: (id: string) => void;
|
||||||
|
removeWarehouse: (id: string) => void;
|
||||||
|
searchWarehouses: (searchPhrase: string) => void;
|
||||||
|
fetchMoreWarehouses: FetchMoreProps;
|
||||||
|
warehouses: ChannelWarehouses;
|
||||||
|
warehousesChoices: RelayToFlat<SearchWarehousesQuery["search"]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Warehouses: React.FC<WarehousesProps> = props => {
|
||||||
|
const {
|
||||||
|
addWarehouse,
|
||||||
|
removeWarehouse,
|
||||||
|
searchWarehouses,
|
||||||
|
fetchMoreWarehouses,
|
||||||
|
warehouses,
|
||||||
|
warehousesChoices,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle title={intl.formatMessage(sectionNames.warehouses)} />
|
||||||
|
<CardContent>
|
||||||
|
<Typography>{intl.formatMessage(messages.subtitle)}</Typography>
|
||||||
|
</CardContent>
|
||||||
|
<AssignmentList
|
||||||
|
items={warehouses}
|
||||||
|
itemsChoices={warehousesChoices}
|
||||||
|
addItem={addWarehouse}
|
||||||
|
removeItem={removeWarehouse}
|
||||||
|
searchItems={searchWarehouses}
|
||||||
|
fetchMoreItems={fetchMoreWarehouses}
|
||||||
|
dataTestId="warehouse"
|
||||||
|
inputName="warehouse"
|
||||||
|
itemsName={intl.formatMessage(sectionNames.warehouses)}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default Warehouses;
|
2
src/channels/components/Warehouses/index.tsx
Normal file
2
src/channels/components/Warehouses/index.tsx
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./Warehouses";
|
||||||
|
export { default } from "./Warehouses";
|
19
src/channels/components/Warehouses/styles.ts
Normal file
19
src/channels/components/Warehouses/styles.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
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;
|
|
@ -22,6 +22,8 @@ const props: ChannelDetailsPageProps<ChannelErrorFragment[]> = {
|
||||||
updateChannelStatus: () => undefined,
|
updateChannelStatus: () => undefined,
|
||||||
searchShippingZones: () => undefined,
|
searchShippingZones: () => undefined,
|
||||||
searchShippingZonesData: undefined,
|
searchShippingZonesData: undefined,
|
||||||
|
searchWarehouses: () => undefined,
|
||||||
|
searchWarehousesData: undefined,
|
||||||
countries: countries.map(({ name, code }) => ({
|
countries: countries.map(({ name, code }) => ({
|
||||||
code,
|
code,
|
||||||
country: name,
|
country: name,
|
||||||
|
@ -45,6 +47,24 @@ const props: ChannelDetailsPageProps<ChannelErrorFragment[]> = {
|
||||||
onFetchMore: () => undefined,
|
onFetchMore: () => undefined,
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
},
|
},
|
||||||
|
channelWarehouses: [
|
||||||
|
{
|
||||||
|
__typename: "Warehouse",
|
||||||
|
id: "warehouse-1",
|
||||||
|
name: "Warehouse 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: "Warehouse",
|
||||||
|
id: "warehouse-2",
|
||||||
|
name: "Warehouse 2",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fetchMoreWarehouses: {
|
||||||
|
loading: false,
|
||||||
|
hasMore: false,
|
||||||
|
onFetchMore: () => undefined,
|
||||||
|
totalCount: 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
storiesOf("Views / Channels / Channel details", module)
|
storiesOf("Views / Channels / Channel details", module)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import ShippingZonesCard from "@saleor/channels/components/ShippingZonesCard/ShippingZonesCard";
|
import ShippingZones from "@saleor/channels/components/ShippingZones";
|
||||||
|
import Warehouses from "@saleor/channels/components/Warehouses";
|
||||||
import { channelsListUrl } from "@saleor/channels/urls";
|
import { channelsListUrl } from "@saleor/channels/urls";
|
||||||
import CardSpacer from "@saleor/components/CardSpacer";
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
import Form from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
|
@ -11,6 +12,7 @@ import {
|
||||||
CountryCode,
|
CountryCode,
|
||||||
CountryFragment,
|
CountryFragment,
|
||||||
SearchShippingZonesQuery,
|
SearchShippingZonesQuery,
|
||||||
|
SearchWarehousesQuery,
|
||||||
} 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";
|
||||||
|
@ -29,7 +31,7 @@ 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 { ChannelShippingZones } from "./types";
|
import { ChannelShippingZones, ChannelWarehouses } from "./types";
|
||||||
import { getUpdatedIdsWithNewId, getUpdatedIdsWithoutNewId } from "./utils";
|
import { getUpdatedIdsWithNewId, getUpdatedIdsWithoutNewId } from "./utils";
|
||||||
|
|
||||||
export interface ChannelDetailsPageProps<TErrors> {
|
export interface ChannelDetailsPageProps<TErrors> {
|
||||||
|
@ -42,11 +44,15 @@ export interface ChannelDetailsPageProps<TErrors> {
|
||||||
searchShippingZonesData?: SearchData;
|
searchShippingZonesData?: SearchData;
|
||||||
fetchMoreShippingZones: FetchMoreProps;
|
fetchMoreShippingZones: FetchMoreProps;
|
||||||
channelShippingZones?: ChannelShippingZones;
|
channelShippingZones?: ChannelShippingZones;
|
||||||
|
searchWarehousesData?: SearchData;
|
||||||
|
fetchMoreWarehouses: FetchMoreProps;
|
||||||
|
channelWarehouses?: ChannelWarehouses;
|
||||||
countries: CountryFragment[];
|
countries: CountryFragment[];
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
onSubmit: (data: FormData) => SubmitPromise<TErrors[]>;
|
onSubmit: (data: FormData) => SubmitPromise<TErrors[]>;
|
||||||
updateChannelStatus?: () => void;
|
updateChannelStatus?: () => void;
|
||||||
searchShippingZones: (query: string) => void;
|
searchShippingZones: (query: string) => void;
|
||||||
|
searchWarehouses: (query: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChannelDetailsPage = function<TErrors>({
|
const ChannelDetailsPage = function<TErrors>({
|
||||||
|
@ -62,8 +68,12 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
searchShippingZones,
|
searchShippingZones,
|
||||||
searchShippingZonesData,
|
searchShippingZonesData,
|
||||||
fetchMoreShippingZones,
|
fetchMoreShippingZones,
|
||||||
countries,
|
|
||||||
channelShippingZones = [],
|
channelShippingZones = [],
|
||||||
|
searchWarehouses,
|
||||||
|
searchWarehousesData,
|
||||||
|
fetchMoreWarehouses,
|
||||||
|
channelWarehouses = [],
|
||||||
|
countries,
|
||||||
}: ChannelDetailsPageProps<TErrors>) {
|
}: ChannelDetailsPageProps<TErrors>) {
|
||||||
const navigate = useNavigator();
|
const navigate = useNavigator();
|
||||||
|
|
||||||
|
@ -76,6 +86,9 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
const [shippingZonesToDisplay, setShippingZonesToDisplay] = useStateFromProps<
|
const [shippingZonesToDisplay, setShippingZonesToDisplay] = useStateFromProps<
|
||||||
ChannelShippingZones
|
ChannelShippingZones
|
||||||
>(channelShippingZones);
|
>(channelShippingZones);
|
||||||
|
const [warehousesToDisplay, setWarehousesToDisplay] = useStateFromProps<
|
||||||
|
ChannelWarehouses
|
||||||
|
>(channelWarehouses);
|
||||||
|
|
||||||
const countryChoices = mapCountriesToChoices(countries || []);
|
const countryChoices = mapCountriesToChoices(countries || []);
|
||||||
|
|
||||||
|
@ -86,6 +99,8 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
slug: "",
|
slug: "",
|
||||||
shippingZonesIdsToAdd: [],
|
shippingZonesIdsToAdd: [],
|
||||||
shippingZonesIdsToRemove: [],
|
shippingZonesIdsToRemove: [],
|
||||||
|
warehousesIdsToAdd: [],
|
||||||
|
warehousesIdsToRemove: [],
|
||||||
defaultCountry: (defaultCountry?.code || "") as CountryCode,
|
defaultCountry: (defaultCountry?.code || "") as CountryCode,
|
||||||
...formData,
|
...formData,
|
||||||
};
|
};
|
||||||
|
@ -96,6 +111,12 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
!shippingZonesToDisplay.some(({ id }) => id === searchedZoneId),
|
!shippingZonesToDisplay.some(({ id }) => id === searchedZoneId),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getFilteredWarehousesChoices = (): RelayToFlat<SearchWarehousesQuery["search"]> =>
|
||||||
|
getParsedSearchData({ data: searchWarehousesData }).filter(
|
||||||
|
({ id: searchedWarehouseId }) =>
|
||||||
|
!warehousesToDisplay.some(({ id }) => id === searchedWarehouseId),
|
||||||
|
);
|
||||||
|
|
||||||
const checkIfSaveIsDisabled = (data: FormData) => {
|
const checkIfSaveIsDisabled = (data: FormData) => {
|
||||||
const isValid =
|
const isValid =
|
||||||
!!data.name &&
|
!!data.name &&
|
||||||
|
@ -114,7 +135,7 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
initial={initialData}
|
initial={initialData}
|
||||||
checkIfSaveIsDisabled={checkIfSaveIsDisabled}
|
checkIfSaveIsDisabled={checkIfSaveIsDisabled}
|
||||||
>
|
>
|
||||||
{({ change, data, submit, set, isSaveDisabled }) => {
|
{({ change, data, submit, set, isSaveDisabled, triggerChange }) => {
|
||||||
const handleCurrencyCodeSelect = createSingleAutocompleteSelectHandler(
|
const handleCurrencyCodeSelect = createSingleAutocompleteSelectHandler(
|
||||||
change,
|
change,
|
||||||
setSelectedCurrencyCode,
|
setSelectedCurrencyCode,
|
||||||
|
@ -127,6 +148,8 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
);
|
);
|
||||||
|
|
||||||
const addShippingZone = (zoneId: string) => {
|
const addShippingZone = (zoneId: string) => {
|
||||||
|
triggerChange();
|
||||||
|
|
||||||
set({
|
set({
|
||||||
...data,
|
...data,
|
||||||
shippingZonesIdsToRemove: getUpdatedIdsWithoutNewId(
|
shippingZonesIdsToRemove: getUpdatedIdsWithoutNewId(
|
||||||
|
@ -148,6 +171,8 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeShippingZone = (zoneId: string) => {
|
const removeShippingZone = (zoneId: string) => {
|
||||||
|
triggerChange();
|
||||||
|
|
||||||
set({
|
set({
|
||||||
...data,
|
...data,
|
||||||
shippingZonesIdsToAdd: getUpdatedIdsWithoutNewId(
|
shippingZonesIdsToAdd: getUpdatedIdsWithoutNewId(
|
||||||
|
@ -165,6 +190,49 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 (
|
||||||
<>
|
<>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
@ -193,7 +261,7 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ShippingZonesCard
|
<ShippingZones
|
||||||
shippingZonesChoices={getFilteredShippingZonesChoices()}
|
shippingZonesChoices={getFilteredShippingZonesChoices()}
|
||||||
shippingZones={shippingZonesToDisplay}
|
shippingZones={shippingZonesToDisplay}
|
||||||
addShippingZone={addShippingZone}
|
addShippingZone={addShippingZone}
|
||||||
|
@ -201,6 +269,15 @@ const ChannelDetailsPage = function<TErrors>({
|
||||||
searchShippingZones={searchShippingZones}
|
searchShippingZones={searchShippingZones}
|
||||||
fetchMoreShippingZones={fetchMoreShippingZones}
|
fetchMoreShippingZones={fetchMoreShippingZones}
|
||||||
/>
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<Warehouses
|
||||||
|
warehousesChoices={getFilteredWarehousesChoices()}
|
||||||
|
warehouses={warehousesToDisplay}
|
||||||
|
addWarehouse={addWarehouse}
|
||||||
|
removeWarehouse={removeWarehouse}
|
||||||
|
searchWarehouses={searchWarehouses}
|
||||||
|
fetchMoreWarehouses={fetchMoreWarehouses}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Savebar
|
<Savebar
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { ChannelShippingZonesQuery } from "@saleor/graphql";
|
import {
|
||||||
|
ChannelShippingZonesQuery,
|
||||||
|
ChannelWarehousesQuery,
|
||||||
|
} from "@saleor/graphql";
|
||||||
import { RelayToFlat } from "@saleor/types";
|
import { RelayToFlat } from "@saleor/types";
|
||||||
|
|
||||||
export type ChannelShippingZones = RelayToFlat<
|
export type ChannelShippingZones = RelayToFlat<
|
||||||
|
@ -6,3 +9,9 @@ export type ChannelShippingZones = RelayToFlat<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type ChannelShippingZone = ChannelShippingZones[0];
|
export type ChannelShippingZone = ChannelShippingZones[0];
|
||||||
|
|
||||||
|
export type ChannelWarehouses = RelayToFlat<
|
||||||
|
ChannelWarehousesQuery["warehouses"]
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type ChannelWarehouse = ChannelWarehouses[0];
|
||||||
|
|
|
@ -16,6 +16,7 @@ import useShop from "@saleor/hooks/useShop";
|
||||||
import { sectionNames } from "@saleor/intl";
|
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 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";
|
||||||
|
@ -44,6 +45,8 @@ export const ChannelCreateView = ({}) => {
|
||||||
const handleSubmit = ({
|
const handleSubmit = ({
|
||||||
shippingZonesIdsToAdd,
|
shippingZonesIdsToAdd,
|
||||||
shippingZonesIdsToRemove,
|
shippingZonesIdsToRemove,
|
||||||
|
warehousesIdsToAdd,
|
||||||
|
warehousesIdsToRemove,
|
||||||
currencyCode,
|
currencyCode,
|
||||||
...rest
|
...rest
|
||||||
}: FormData) =>
|
}: FormData) =>
|
||||||
|
@ -54,6 +57,7 @@ export const ChannelCreateView = ({}) => {
|
||||||
...rest,
|
...rest,
|
||||||
currencyCode: currencyCode.toUpperCase(),
|
currencyCode: currencyCode.toUpperCase(),
|
||||||
addShippingZones: shippingZonesIdsToAdd,
|
addShippingZones: shippingZonesIdsToAdd,
|
||||||
|
addWarehouses: warehousesIdsToAdd,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -67,6 +71,14 @@ export const ChannelCreateView = ({}) => {
|
||||||
variables: DEFAULT_INITIAL_SEARCH_DATA,
|
variables: DEFAULT_INITIAL_SEARCH_DATA,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
loadMore: fetchMoreWarehouses,
|
||||||
|
search: searchWarehouses,
|
||||||
|
result: searchWarehousesResult,
|
||||||
|
} = useWarehouseSearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA,
|
||||||
|
});
|
||||||
|
|
||||||
const currencyCodeChoices = currencyCodes.data.map(currencyData => ({
|
const currencyCodeChoices = currencyCodes.data.map(currencyData => ({
|
||||||
label: intl.formatMessage(
|
label: intl.formatMessage(
|
||||||
{
|
{
|
||||||
|
@ -109,6 +121,12 @@ export const ChannelCreateView = ({}) => {
|
||||||
searchShippingZonesResult,
|
searchShippingZonesResult,
|
||||||
fetchMoreShippingZones,
|
fetchMoreShippingZones,
|
||||||
)}
|
)}
|
||||||
|
searchWarehouses={searchWarehouses}
|
||||||
|
searchWarehousesData={searchWarehousesResult.data}
|
||||||
|
fetchMoreWarehouses={getSearchFetchMoreProps(
|
||||||
|
searchWarehousesResult,
|
||||||
|
fetchMoreWarehouses,
|
||||||
|
)}
|
||||||
disabled={createChannelOpts.loading}
|
disabled={createChannelOpts.loading}
|
||||||
errors={createChannelOpts?.data?.channelCreate?.errors || []}
|
errors={createChannelOpts?.data?.channelCreate?.errors || []}
|
||||||
currencyCodes={currencyCodeChoices}
|
currencyCodes={currencyCodeChoices}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
useChannelShippingZonesQuery,
|
useChannelShippingZonesQuery,
|
||||||
useChannelsQuery,
|
useChannelsQuery,
|
||||||
useChannelUpdateMutation,
|
useChannelUpdateMutation,
|
||||||
|
useChannelWarehousesQuery,
|
||||||
} from "@saleor/graphql";
|
} from "@saleor/graphql";
|
||||||
import { getSearchFetchMoreProps } from "@saleor/hooks/makeTopLevelSearch/utils";
|
import { getSearchFetchMoreProps } from "@saleor/hooks/makeTopLevelSearch/utils";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
@ -26,6 +27,7 @@ import useShop from "@saleor/hooks/useShop";
|
||||||
import { sectionNames } from "@saleor/intl";
|
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 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 React from "react";
|
import React from "react";
|
||||||
|
@ -103,6 +105,8 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
|
||||||
slug,
|
slug,
|
||||||
shippingZonesIdsToRemove,
|
shippingZonesIdsToRemove,
|
||||||
shippingZonesIdsToAdd,
|
shippingZonesIdsToAdd,
|
||||||
|
warehousesIdsToRemove,
|
||||||
|
warehousesIdsToAdd,
|
||||||
defaultCountry,
|
defaultCountry,
|
||||||
}: FormData) =>
|
}: FormData) =>
|
||||||
extractMutationErrors(
|
extractMutationErrors(
|
||||||
|
@ -115,6 +119,8 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
|
||||||
defaultCountry,
|
defaultCountry,
|
||||||
addShippingZones: shippingZonesIdsToAdd,
|
addShippingZones: shippingZonesIdsToAdd,
|
||||||
removeShippingZones: shippingZonesIdsToRemove,
|
removeShippingZones: shippingZonesIdsToRemove,
|
||||||
|
addWarehouses: warehousesIdsToAdd,
|
||||||
|
removeWarehouses: warehousesIdsToRemove,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
@ -176,6 +182,25 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
|
||||||
variables: DEFAULT_INITIAL_SEARCH_DATA,
|
variables: DEFAULT_INITIAL_SEARCH_DATA,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: channelWarehousesData,
|
||||||
|
loading: channelsWarehousesLoading,
|
||||||
|
} = useChannelWarehousesQuery({
|
||||||
|
variables: {
|
||||||
|
filter: {
|
||||||
|
channels: [id],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
loadMore: fetchMoreWarehouses,
|
||||||
|
search: searchWarehouses,
|
||||||
|
result: searchWarehousesResult,
|
||||||
|
} = useWarehouseSearch({
|
||||||
|
variables: DEFAULT_INITIAL_SEARCH_DATA,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WindowTitle
|
<WindowTitle
|
||||||
|
@ -200,9 +225,21 @@ export const ChannelDetails: React.FC<ChannelDetailsProps> = ({
|
||||||
searchShippingZonesResult,
|
searchShippingZonesResult,
|
||||||
fetchMoreShippingZones,
|
fetchMoreShippingZones,
|
||||||
)}
|
)}
|
||||||
|
channelWarehouses={channelWarehousesData?.warehouses?.edges?.map(
|
||||||
|
({ node }) => node,
|
||||||
|
)}
|
||||||
|
searchWarehouses={searchWarehouses}
|
||||||
|
searchWarehousesData={searchWarehousesResult.data}
|
||||||
|
fetchMoreWarehouses={getSearchFetchMoreProps(
|
||||||
|
searchWarehousesResult,
|
||||||
|
fetchMoreWarehouses,
|
||||||
|
)}
|
||||||
channel={data?.channel}
|
channel={data?.channel}
|
||||||
disabled={
|
disabled={
|
||||||
updateChannelOpts.loading || loading || channelsShippingZonesLoading
|
updateChannelOpts.loading ||
|
||||||
|
loading ||
|
||||||
|
channelsShippingZonesLoading ||
|
||||||
|
channelsWarehousesLoading
|
||||||
}
|
}
|
||||||
disabledStatus={
|
disabledStatus={
|
||||||
activateChannelOpts.loading || deactivateChannelOpts.loading
|
activateChannelOpts.loading || deactivateChannelOpts.loading
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
"AttributeCreated",
|
"AttributeCreated",
|
||||||
"AttributeDeleted",
|
"AttributeDeleted",
|
||||||
"AttributeUpdated",
|
"AttributeUpdated",
|
||||||
|
"AttributeValueCreated",
|
||||||
|
"AttributeValueDeleted",
|
||||||
|
"AttributeValueUpdated",
|
||||||
"CategoryCreated",
|
"CategoryCreated",
|
||||||
"CategoryDeleted",
|
"CategoryDeleted",
|
||||||
"CategoryUpdated",
|
"CategoryUpdated",
|
||||||
|
@ -195,6 +198,7 @@
|
||||||
"Attribute",
|
"Attribute",
|
||||||
"Category",
|
"Category",
|
||||||
"Checkout",
|
"Checkout",
|
||||||
|
"CheckoutLine",
|
||||||
"Collection",
|
"Collection",
|
||||||
"DigitalContent",
|
"DigitalContent",
|
||||||
"Fulfillment",
|
"Fulfillment",
|
||||||
|
@ -203,6 +207,7 @@
|
||||||
"Menu",
|
"Menu",
|
||||||
"MenuItem",
|
"MenuItem",
|
||||||
"Order",
|
"Order",
|
||||||
|
"OrderLine",
|
||||||
"Page",
|
"Page",
|
||||||
"PageType",
|
"PageType",
|
||||||
"Payment",
|
"Payment",
|
||||||
|
|
|
@ -13495,6 +13495,7 @@ export const SearchWarehousesDocument = gql`
|
||||||
sortBy: {direction: ASC, field: NAME}
|
sortBy: {direction: ASC, field: NAME}
|
||||||
filter: {search: $query}
|
filter: {search: $query}
|
||||||
) {
|
) {
|
||||||
|
totalCount
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
|
@ -16343,6 +16344,46 @@ 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 WebhookCreateDocument = gql`
|
export const WebhookCreateDocument = gql`
|
||||||
mutation WebhookCreate($input: WebhookCreateInput!) {
|
mutation WebhookCreate($input: WebhookCreateInput!) {
|
||||||
webhookCreate(input: $input) {
|
webhookCreate(input: $input) {
|
||||||
|
|
|
@ -518,6 +518,14 @@ export type AttributeValueCreateFieldPolicy = {
|
||||||
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
|
export type AttributeValueCreatedKeySpecifier = ('issuedAt' | 'version' | 'issuingPrincipal' | 'recipient' | 'attributeValue' | AttributeValueCreatedKeySpecifier)[];
|
||||||
|
export type AttributeValueCreatedFieldPolicy = {
|
||||||
|
issuedAt?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
version?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
issuingPrincipal?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
|
};
|
||||||
export type AttributeValueDeleteKeySpecifier = ('attribute' | 'attributeErrors' | 'errors' | 'attributeValue' | AttributeValueDeleteKeySpecifier)[];
|
export type AttributeValueDeleteKeySpecifier = ('attribute' | 'attributeErrors' | 'errors' | 'attributeValue' | AttributeValueDeleteKeySpecifier)[];
|
||||||
export type AttributeValueDeleteFieldPolicy = {
|
export type AttributeValueDeleteFieldPolicy = {
|
||||||
attribute?: FieldPolicy<any> | FieldReadFunction<any>,
|
attribute?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
@ -525,6 +533,14 @@ export type AttributeValueDeleteFieldPolicy = {
|
||||||
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
|
export type AttributeValueDeletedKeySpecifier = ('issuedAt' | 'version' | 'issuingPrincipal' | 'recipient' | 'attributeValue' | AttributeValueDeletedKeySpecifier)[];
|
||||||
|
export type AttributeValueDeletedFieldPolicy = {
|
||||||
|
issuedAt?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
version?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
issuingPrincipal?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
|
};
|
||||||
export type AttributeValueTranslatableContentKeySpecifier = ('id' | 'name' | 'richText' | 'plainText' | 'translation' | 'attributeValue' | AttributeValueTranslatableContentKeySpecifier)[];
|
export type AttributeValueTranslatableContentKeySpecifier = ('id' | 'name' | 'richText' | 'plainText' | 'translation' | 'attributeValue' | AttributeValueTranslatableContentKeySpecifier)[];
|
||||||
export type AttributeValueTranslatableContentFieldPolicy = {
|
export type AttributeValueTranslatableContentFieldPolicy = {
|
||||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
@ -555,6 +571,14 @@ export type AttributeValueUpdateFieldPolicy = {
|
||||||
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
|
export type AttributeValueUpdatedKeySpecifier = ('issuedAt' | 'version' | 'issuingPrincipal' | 'recipient' | 'attributeValue' | AttributeValueUpdatedKeySpecifier)[];
|
||||||
|
export type AttributeValueUpdatedFieldPolicy = {
|
||||||
|
issuedAt?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
version?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
issuingPrincipal?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
attributeValue?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
|
};
|
||||||
export type BulkProductErrorKeySpecifier = ('field' | 'message' | 'code' | 'attributes' | 'values' | 'index' | 'warehouses' | 'channels' | BulkProductErrorKeySpecifier)[];
|
export type BulkProductErrorKeySpecifier = ('field' | 'message' | 'code' | 'attributes' | 'values' | 'index' | 'warehouses' | 'channels' | BulkProductErrorKeySpecifier)[];
|
||||||
export type BulkProductErrorFieldPolicy = {
|
export type BulkProductErrorFieldPolicy = {
|
||||||
field?: FieldPolicy<any> | FieldReadFunction<any>,
|
field?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
@ -684,7 +708,7 @@ export type CategoryUpdatedFieldPolicy = {
|
||||||
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
category?: FieldPolicy<any> | FieldReadFunction<any>
|
category?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type ChannelKeySpecifier = ('id' | 'name' | 'isActive' | 'currencyCode' | 'slug' | 'hasOrders' | 'defaultCountry' | ChannelKeySpecifier)[];
|
export type ChannelKeySpecifier = ('id' | 'name' | 'isActive' | 'currencyCode' | 'slug' | 'hasOrders' | 'defaultCountry' | 'warehouses' | ChannelKeySpecifier)[];
|
||||||
export type ChannelFieldPolicy = {
|
export type ChannelFieldPolicy = {
|
||||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
name?: FieldPolicy<any> | FieldReadFunction<any>,
|
name?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
@ -692,7 +716,8 @@ export type ChannelFieldPolicy = {
|
||||||
currencyCode?: FieldPolicy<any> | FieldReadFunction<any>,
|
currencyCode?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
slug?: FieldPolicy<any> | FieldReadFunction<any>,
|
slug?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
hasOrders?: FieldPolicy<any> | FieldReadFunction<any>,
|
hasOrders?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
defaultCountry?: FieldPolicy<any> | FieldReadFunction<any>
|
defaultCountry?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
warehouses?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type ChannelActivateKeySpecifier = ('channel' | 'channelErrors' | 'errors' | ChannelActivateKeySpecifier)[];
|
export type ChannelActivateKeySpecifier = ('channel' | 'channelErrors' | 'errors' | ChannelActivateKeySpecifier)[];
|
||||||
export type ChannelActivateFieldPolicy = {
|
export type ChannelActivateFieldPolicy = {
|
||||||
|
@ -734,12 +759,13 @@ export type ChannelDeletedFieldPolicy = {
|
||||||
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
channel?: FieldPolicy<any> | FieldReadFunction<any>
|
channel?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type ChannelErrorKeySpecifier = ('field' | 'message' | 'code' | 'shippingZones' | ChannelErrorKeySpecifier)[];
|
export type ChannelErrorKeySpecifier = ('field' | 'message' | 'code' | 'shippingZones' | 'warehouses' | ChannelErrorKeySpecifier)[];
|
||||||
export type ChannelErrorFieldPolicy = {
|
export type ChannelErrorFieldPolicy = {
|
||||||
field?: FieldPolicy<any> | FieldReadFunction<any>,
|
field?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
message?: FieldPolicy<any> | FieldReadFunction<any>,
|
message?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
code?: FieldPolicy<any> | FieldReadFunction<any>,
|
code?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
shippingZones?: FieldPolicy<any> | FieldReadFunction<any>
|
shippingZones?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
warehouses?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type ChannelStatusChangedKeySpecifier = ('issuedAt' | 'version' | 'issuingPrincipal' | 'recipient' | 'channel' | ChannelStatusChangedKeySpecifier)[];
|
export type ChannelStatusChangedKeySpecifier = ('issuedAt' | 'version' | 'issuingPrincipal' | 'recipient' | 'channel' | ChannelStatusChangedKeySpecifier)[];
|
||||||
export type ChannelStatusChangedFieldPolicy = {
|
export type ChannelStatusChangedFieldPolicy = {
|
||||||
|
@ -886,9 +912,15 @@ export type CheckoutLanguageCodeUpdateFieldPolicy = {
|
||||||
checkoutErrors?: FieldPolicy<any> | FieldReadFunction<any>,
|
checkoutErrors?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
errors?: FieldPolicy<any> | FieldReadFunction<any>
|
errors?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type CheckoutLineKeySpecifier = ('id' | 'variant' | 'quantity' | 'unitPrice' | 'undiscountedUnitPrice' | 'totalPrice' | 'undiscountedTotalPrice' | 'requiresShipping' | CheckoutLineKeySpecifier)[];
|
export type CheckoutLineKeySpecifier = ('id' | 'privateMetadata' | 'privateMetafield' | 'privateMetafields' | 'metadata' | 'metafield' | 'metafields' | 'variant' | 'quantity' | 'unitPrice' | 'undiscountedUnitPrice' | 'totalPrice' | 'undiscountedTotalPrice' | 'requiresShipping' | CheckoutLineKeySpecifier)[];
|
||||||
export type CheckoutLineFieldPolicy = {
|
export type CheckoutLineFieldPolicy = {
|
||||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
privateMetafield?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
privateMetafields?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
metadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
metafield?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
metafields?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
variant?: FieldPolicy<any> | FieldReadFunction<any>,
|
variant?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
quantity?: FieldPolicy<any> | FieldReadFunction<any>,
|
quantity?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
unitPrice?: FieldPolicy<any> | FieldReadFunction<any>,
|
unitPrice?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
@ -2736,9 +2768,15 @@ export type OrderFullyPaidFieldPolicy = {
|
||||||
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
recipient?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
order?: FieldPolicy<any> | FieldReadFunction<any>
|
order?: FieldPolicy<any> | FieldReadFunction<any>
|
||||||
};
|
};
|
||||||
export type OrderLineKeySpecifier = ('id' | 'productName' | 'variantName' | 'productSku' | 'productVariantId' | 'isShippingRequired' | 'quantity' | 'quantityFulfilled' | 'unitDiscountReason' | 'taxRate' | 'digitalContentUrl' | 'thumbnail' | 'unitPrice' | 'undiscountedUnitPrice' | 'unitDiscount' | 'unitDiscountValue' | 'totalPrice' | 'variant' | 'translatedProductName' | 'translatedVariantName' | 'allocations' | 'quantityToFulfill' | 'unitDiscountType' | OrderLineKeySpecifier)[];
|
export type OrderLineKeySpecifier = ('id' | 'privateMetadata' | 'privateMetafield' | 'privateMetafields' | 'metadata' | 'metafield' | 'metafields' | 'productName' | 'variantName' | 'productSku' | 'productVariantId' | 'isShippingRequired' | 'quantity' | 'quantityFulfilled' | 'unitDiscountReason' | 'taxRate' | 'digitalContentUrl' | 'thumbnail' | 'unitPrice' | 'undiscountedUnitPrice' | 'unitDiscount' | 'unitDiscountValue' | 'totalPrice' | 'variant' | 'translatedProductName' | 'translatedVariantName' | 'allocations' | 'quantityToFulfill' | 'unitDiscountType' | OrderLineKeySpecifier)[];
|
||||||
export type OrderLineFieldPolicy = {
|
export type OrderLineFieldPolicy = {
|
||||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
privateMetafield?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
privateMetafields?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
metadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
metafield?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
metafields?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
productName?: FieldPolicy<any> | FieldReadFunction<any>,
|
productName?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
variantName?: FieldPolicy<any> | FieldReadFunction<any>,
|
variantName?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
productSku?: FieldPolicy<any> | FieldReadFunction<any>,
|
productSku?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||||
|
@ -5271,10 +5309,18 @@ export type StrictTypedTypePolicies = {
|
||||||
keyFields?: false | AttributeValueCreateKeySpecifier | (() => undefined | AttributeValueCreateKeySpecifier),
|
keyFields?: false | AttributeValueCreateKeySpecifier | (() => undefined | AttributeValueCreateKeySpecifier),
|
||||||
fields?: AttributeValueCreateFieldPolicy,
|
fields?: AttributeValueCreateFieldPolicy,
|
||||||
},
|
},
|
||||||
|
AttributeValueCreated?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
|
keyFields?: false | AttributeValueCreatedKeySpecifier | (() => undefined | AttributeValueCreatedKeySpecifier),
|
||||||
|
fields?: AttributeValueCreatedFieldPolicy,
|
||||||
|
},
|
||||||
AttributeValueDelete?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
AttributeValueDelete?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
keyFields?: false | AttributeValueDeleteKeySpecifier | (() => undefined | AttributeValueDeleteKeySpecifier),
|
keyFields?: false | AttributeValueDeleteKeySpecifier | (() => undefined | AttributeValueDeleteKeySpecifier),
|
||||||
fields?: AttributeValueDeleteFieldPolicy,
|
fields?: AttributeValueDeleteFieldPolicy,
|
||||||
},
|
},
|
||||||
|
AttributeValueDeleted?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
|
keyFields?: false | AttributeValueDeletedKeySpecifier | (() => undefined | AttributeValueDeletedKeySpecifier),
|
||||||
|
fields?: AttributeValueDeletedFieldPolicy,
|
||||||
|
},
|
||||||
AttributeValueTranslatableContent?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
AttributeValueTranslatableContent?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
keyFields?: false | AttributeValueTranslatableContentKeySpecifier | (() => undefined | AttributeValueTranslatableContentKeySpecifier),
|
keyFields?: false | AttributeValueTranslatableContentKeySpecifier | (() => undefined | AttributeValueTranslatableContentKeySpecifier),
|
||||||
fields?: AttributeValueTranslatableContentFieldPolicy,
|
fields?: AttributeValueTranslatableContentFieldPolicy,
|
||||||
|
@ -5291,6 +5337,10 @@ export type StrictTypedTypePolicies = {
|
||||||
keyFields?: false | AttributeValueUpdateKeySpecifier | (() => undefined | AttributeValueUpdateKeySpecifier),
|
keyFields?: false | AttributeValueUpdateKeySpecifier | (() => undefined | AttributeValueUpdateKeySpecifier),
|
||||||
fields?: AttributeValueUpdateFieldPolicy,
|
fields?: AttributeValueUpdateFieldPolicy,
|
||||||
},
|
},
|
||||||
|
AttributeValueUpdated?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
|
keyFields?: false | AttributeValueUpdatedKeySpecifier | (() => undefined | AttributeValueUpdatedKeySpecifier),
|
||||||
|
fields?: AttributeValueUpdatedFieldPolicy,
|
||||||
|
},
|
||||||
BulkProductError?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
BulkProductError?: Omit<TypePolicy, "fields" | "keyFields"> & {
|
||||||
keyFields?: false | BulkProductErrorKeySpecifier | (() => undefined | BulkProductErrorKeySpecifier),
|
keyFields?: false | BulkProductErrorKeySpecifier | (() => undefined | BulkProductErrorKeySpecifier),
|
||||||
fields?: BulkProductErrorFieldPolicy,
|
fields?: BulkProductErrorFieldPolicy,
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -447,6 +447,11 @@ export const sectionNames = defineMessages({
|
||||||
defaultMessage: "Shipping Methods",
|
defaultMessage: "Shipping Methods",
|
||||||
description: "shipping section name",
|
description: "shipping section name",
|
||||||
},
|
},
|
||||||
|
shippingZones: {
|
||||||
|
id: "V1MytH",
|
||||||
|
defaultMessage: "Shipping Zones",
|
||||||
|
description: "shipping zones section name",
|
||||||
|
},
|
||||||
siteSettings: {
|
siteSettings: {
|
||||||
id: "viFkCw",
|
id: "viFkCw",
|
||||||
defaultMessage: "Site Settings",
|
defaultMessage: "Site Settings",
|
||||||
|
|
|
@ -2319,6 +2319,7 @@ export const shopOrderSettings: ShopOrderSettingsFragment = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const warehouseSearch: SearchWarehousesQuery["search"] = {
|
export const warehouseSearch: SearchWarehousesQuery["search"] = {
|
||||||
|
totalCount: 20,
|
||||||
edges: [
|
edges: [
|
||||||
{
|
{
|
||||||
node: {
|
node: {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import AddIcon from "@material-ui/icons/Add";
|
||||||
import Link from "@saleor/components/Link";
|
import Link from "@saleor/components/Link";
|
||||||
import { IconButton, makeStyles } from "@saleor/macaw-ui";
|
import { IconButton, makeStyles } from "@saleor/macaw-ui";
|
||||||
import React, { MutableRefObject } from "react";
|
import React, { MutableRefObject } from "react";
|
||||||
import { MessageDescriptor, useIntl } from "react-intl";
|
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
|
@ -21,7 +20,7 @@ const useStyles = makeStyles(
|
||||||
);
|
);
|
||||||
|
|
||||||
interface CardAddItemsFooterProps {
|
interface CardAddItemsFooterProps {
|
||||||
title: MessageDescriptor;
|
title: string;
|
||||||
onAdd: () => void;
|
onAdd: () => void;
|
||||||
testIds: {
|
testIds: {
|
||||||
link: string;
|
link: string;
|
||||||
|
@ -37,13 +36,12 @@ const CardAddItemsFooter: React.FC<CardAddItemsFooterProps> = ({
|
||||||
ref,
|
ref,
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
|
||||||
const classes = useStyles({});
|
const classes = useStyles({});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.container} ref={ref}>
|
<div className={classes.container} ref={ref}>
|
||||||
<Link data-test-id={testIds.link} onClick={onAdd}>
|
<Link data-test-id={testIds.link} onClick={onAdd}>
|
||||||
{intl.formatMessage(title)}
|
{title}
|
||||||
</Link>
|
</Link>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|
|
@ -28,14 +28,8 @@ import PreviewPill from "@saleor/components/PreviewPill";
|
||||||
import { ProductErrorFragment, WarehouseFragment } from "@saleor/graphql";
|
import { ProductErrorFragment, WarehouseFragment } from "@saleor/graphql";
|
||||||
import { FormChange, FormErrors } from "@saleor/hooks/useForm";
|
import { FormChange, FormErrors } from "@saleor/hooks/useForm";
|
||||||
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
|
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
|
||||||
import {
|
import { sectionNames } from "@saleor/intl";
|
||||||
Button,
|
import { Button, DeleteIcon, IconButton, PlusIcon } from "@saleor/macaw-ui";
|
||||||
DeleteIcon,
|
|
||||||
IconButton,
|
|
||||||
ICONBUTTON_SIZE,
|
|
||||||
makeStyles,
|
|
||||||
PlusIcon,
|
|
||||||
} from "@saleor/macaw-ui";
|
|
||||||
import { renderCollection } from "@saleor/misc";
|
import { renderCollection } from "@saleor/misc";
|
||||||
import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors";
|
import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors";
|
||||||
import createNonNegativeValueChangeHandler from "@saleor/utils/handlers/nonNegativeValueChangeHandler";
|
import createNonNegativeValueChangeHandler from "@saleor/utils/handlers/nonNegativeValueChangeHandler";
|
||||||
|
@ -46,6 +40,8 @@ import { ProductCreateData } from "../ProductCreatePage";
|
||||||
import { ProductUpdateSubmitData } from "../ProductUpdatePage/form";
|
import { ProductUpdateSubmitData } from "../ProductUpdatePage/form";
|
||||||
import { ProductVariantCreateData } from "../ProductVariantCreatePage/form";
|
import { ProductVariantCreateData } from "../ProductVariantCreatePage/form";
|
||||||
import { ProductVariantUpdateData } from "../ProductVariantPage/form";
|
import { ProductVariantUpdateData } from "../ProductVariantPage/form";
|
||||||
|
import { messages } from "./messages";
|
||||||
|
import { useStyles } from "./styles";
|
||||||
|
|
||||||
export interface ProductStockFormsetData {
|
export interface ProductStockFormsetData {
|
||||||
quantityAllocated: number;
|
quantityAllocated: number;
|
||||||
|
@ -90,98 +86,6 @@ export interface ProductStocksProps {
|
||||||
onWarehouseConfigure: () => void;
|
onWarehouseConfigure: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
|
||||||
theme => ({
|
|
||||||
colAction: {
|
|
||||||
padding: 0,
|
|
||||||
width: `calc(${ICONBUTTON_SIZE}px + ${theme.spacing(1)})`,
|
|
||||||
},
|
|
||||||
colName: {},
|
|
||||||
colQuantity: {
|
|
||||||
textAlign: "right",
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
colSoldUnits: {
|
|
||||||
textAlign: "right",
|
|
||||||
width: 150,
|
|
||||||
},
|
|
||||||
colThreshold: {
|
|
||||||
textAlign: "right",
|
|
||||||
width: 180,
|
|
||||||
},
|
|
||||||
editWarehouses: {
|
|
||||||
marginRight: theme.spacing(-1),
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
padding: theme.spacing(1.5),
|
|
||||||
textAlign: "right",
|
|
||||||
},
|
|
||||||
menuItem: {
|
|
||||||
"&:not(:last-of-type)": {
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
noWarehouseInfo: {
|
|
||||||
marginTop: theme.spacing(),
|
|
||||||
},
|
|
||||||
paper: {
|
|
||||||
padding: theme.spacing(2),
|
|
||||||
},
|
|
||||||
popper: {
|
|
||||||
marginTop: theme.spacing(1),
|
|
||||||
zIndex: 2,
|
|
||||||
},
|
|
||||||
quantityContainer: {
|
|
||||||
paddingTop: theme.spacing(),
|
|
||||||
},
|
|
||||||
quantityHeader: {
|
|
||||||
alignItems: "center",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
},
|
|
||||||
skuInputContainer: {
|
|
||||||
display: "grid",
|
|
||||||
gridColumnGap: theme.spacing(3),
|
|
||||||
gridTemplateColumns: "repeat(2, 1fr)",
|
|
||||||
},
|
|
||||||
dateTimeInputs: {
|
|
||||||
marginTop: theme.spacing(2),
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
},
|
|
||||||
preorderInfo: {
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
marginTop: theme.spacing(2),
|
|
||||||
display: "block",
|
|
||||||
},
|
|
||||||
caption: {
|
|
||||||
fontSize: 14,
|
|
||||||
},
|
|
||||||
thresholdRow: {
|
|
||||||
display: "grid",
|
|
||||||
gridColumnGap: theme.spacing(3),
|
|
||||||
gridTemplateColumns: "3fr 1fr",
|
|
||||||
marginTop: theme.spacing(1),
|
|
||||||
},
|
|
||||||
thresholdInput: {
|
|
||||||
maxWidth: 400,
|
|
||||||
},
|
|
||||||
preorderItemsLeftCount: {
|
|
||||||
fontSize: 14,
|
|
||||||
paddingTop: theme.spacing(2),
|
|
||||||
textAlign: "center",
|
|
||||||
},
|
|
||||||
preorderLimitInfo: {
|
|
||||||
marginTop: theme.spacing(3),
|
|
||||||
},
|
|
||||||
preview: {
|
|
||||||
marginLeft: theme.spacing(1),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
name: "ProductStocks",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const ProductStocks: React.FC<ProductStocksProps> = ({
|
const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
data,
|
data,
|
||||||
disabled,
|
disabled,
|
||||||
|
@ -200,7 +104,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
onWarehouseStockDelete,
|
onWarehouseStockDelete,
|
||||||
onWarehouseConfigure,
|
onWarehouseConfigure,
|
||||||
}) => {
|
}) => {
|
||||||
const classes = useStyles({});
|
const classes = useStyles();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const anchor = React.useRef<HTMLDivElement>();
|
const anchor = React.useRef<HTMLDivElement>();
|
||||||
const [isExpanded, setExpansionState] = React.useState(false);
|
const [isExpanded, setExpansionState] = React.useState(false);
|
||||||
|
@ -218,13 +122,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardTitle
|
<CardTitle title={intl.formatMessage(messages.title)} />
|
||||||
title={intl.formatMessage({
|
|
||||||
id: "4qe6hO",
|
|
||||||
defaultMessage: "Inventory",
|
|
||||||
description: "product stock, section header",
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className={classes.skuInputContainer}>
|
<div className={classes.skuInputContainer}>
|
||||||
<TextField
|
<TextField
|
||||||
|
@ -232,10 +130,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
error={!!formErrors.sku}
|
error={!!formErrors.sku}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={getProductErrorMessage(formErrors.sku, intl)}
|
helperText={getProductErrorMessage(formErrors.sku, intl)}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage(messages.sku)}
|
||||||
id: "xB7BTp",
|
|
||||||
defaultMessage: "SKU (Stock Keeping Unit)",
|
|
||||||
})}
|
|
||||||
name="sku"
|
name="sku"
|
||||||
onChange={onFormDataChange}
|
onChange={onFormDataChange}
|
||||||
value={data.sku}
|
value={data.sku}
|
||||||
|
@ -252,11 +147,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={
|
label={
|
||||||
<>
|
<>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.variantInPreorder} />
|
||||||
id="eAFU/E"
|
|
||||||
defaultMessage="Variant currently in preorder"
|
|
||||||
description="product inventory, checkbox"
|
|
||||||
/>
|
|
||||||
<PreviewPill className={classes.preview} />
|
<PreviewPill className={classes.preview} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -272,16 +163,9 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={
|
label={
|
||||||
<>
|
<>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.trackInventory} />
|
||||||
id="TjGYna"
|
|
||||||
defaultMessage="Track Inventory"
|
|
||||||
description="product inventory, checkbox"
|
|
||||||
/>
|
|
||||||
<Typography variant="caption">
|
<Typography variant="caption">
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.trackInventoryDescription} />
|
||||||
id="jABdx1"
|
|
||||||
defaultMessage="Active inventory tracking will automatically calculate changes of stock"
|
|
||||||
/>
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -295,14 +179,18 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
<Typography>
|
<Typography>
|
||||||
<div className={classes.quantityHeader}>
|
<div className={classes.quantityHeader}>
|
||||||
<span>
|
<span>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.quantity} />
|
||||||
id="bp/i0x"
|
|
||||||
defaultMessage="Quantity"
|
|
||||||
description="header"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{!productVariantChannelListings?.length && (
|
||||||
|
<>
|
||||||
|
<FormSpacer />
|
||||||
|
<Typography variant="caption">
|
||||||
|
<FormattedMessage {...messages.noChannelWarehousesAllocation} />
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{!warehouses?.length && (
|
{!warehouses?.length && (
|
||||||
<Typography
|
<Typography
|
||||||
|
@ -312,9 +200,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
{hasVariants ? (
|
{hasVariants ? (
|
||||||
<>
|
<>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="D8nsBc"
|
{...messages.configureWarehouseForVariant}
|
||||||
defaultMessage="There are no warehouses set up for your store. To add stock quantity to the variant please <a>configure a warehouse</a>"
|
|
||||||
description="no warehouses info"
|
|
||||||
values={{
|
values={{
|
||||||
a: chunks => (
|
a: chunks => (
|
||||||
<Link onClick={onWarehouseConfigure}>{chunks}</Link>
|
<Link onClick={onWarehouseConfigure}>{chunks}</Link>
|
||||||
|
@ -325,9 +211,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="RLBLPQ"
|
{...messages.configureWarehouseForProduct}
|
||||||
defaultMessage="There are no warehouses set up for your store. To add stock quantity to the product please <a>configure a warehouse</a>"
|
|
||||||
description="no warehouses info"
|
|
||||||
values={{
|
values={{
|
||||||
a: chunks => (
|
a: chunks => (
|
||||||
<Link onClick={onWarehouseConfigure}>{chunks}</Link>
|
<Link onClick={onWarehouseConfigure}>{chunks}</Link>
|
||||||
|
@ -340,7 +224,9 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
)}
|
)}
|
||||||
{warehouses?.length > 0 && !data.isPreorder && (
|
{productVariantChannelListings?.length > 0 &&
|
||||||
|
warehouses?.length > 0 &&
|
||||||
|
!data.isPreorder && (
|
||||||
<Table>
|
<Table>
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col className={classes.colName} />
|
<col className={classes.colName} />
|
||||||
|
@ -350,25 +236,13 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className={classes.colName}>
|
<TableCell className={classes.colName}>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.warehouseName} />
|
||||||
id="KTAg0f"
|
|
||||||
defaultMessage="Warehouse Name"
|
|
||||||
description="tabel column header"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colQuantity}>
|
<TableCell className={classes.colQuantity}>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.allocated} />
|
||||||
id="g/FRtd"
|
|
||||||
defaultMessage="Allocated"
|
|
||||||
description="table column header, allocated product quantity"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colQuantity}>
|
<TableCell className={classes.colQuantity}>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.quantity} />
|
||||||
id="ge/xFX"
|
|
||||||
defaultMessage="Quantity"
|
|
||||||
description="table column header"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colAction} />
|
<TableCell className={classes.colAction} />
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
@ -417,11 +291,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell colSpan={3}>
|
<TableCell colSpan={3}>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.assignWarehouse} />
|
||||||
id="cBHRxx"
|
|
||||||
defaultMessage="Assign Warehouse"
|
|
||||||
description="button"
|
|
||||||
/>
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colAction}>
|
<TableCell className={classes.colAction}>
|
||||||
|
@ -477,12 +347,7 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
{data.isPreorder && (
|
{data.isPreorder && (
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography variant="caption" className={classes.caption}>
|
<Typography variant="caption" className={classes.caption}>
|
||||||
{intl.formatMessage({
|
<FormattedMessage {...messages.preorderEndDateSetup} />
|
||||||
id: "REVk27",
|
|
||||||
defaultMessage:
|
|
||||||
"Set up an end date of preorder. When end date will be reached product will be automatically taken from preorder to standard selling",
|
|
||||||
description: "info text",
|
|
||||||
})}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{data.hasPreorderEndDate && (
|
{data.hasPreorderEndDate && (
|
||||||
|
@ -519,22 +384,11 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{data.hasPreorderEndDate
|
{data.hasPreorderEndDate
|
||||||
? intl.formatMessage({
|
? intl.formatMessage(messages.endDateCancel)
|
||||||
id: "2qJc9y",
|
: intl.formatMessage(messages.endDateSetup)}
|
||||||
defaultMessage: "CANCEL END DATE",
|
|
||||||
})
|
|
||||||
: intl.formatMessage({
|
|
||||||
id: "7Ii5ZQ",
|
|
||||||
defaultMessage: "SETUP END DATE",
|
|
||||||
})}
|
|
||||||
</Button>
|
</Button>
|
||||||
<Typography variant="caption" className={classes.preorderLimitInfo}>
|
<Typography variant="caption" className={classes.preorderLimitInfo}>
|
||||||
{intl.formatMessage({
|
<FormattedMessage {...messages.preorderProductsAvailability} />
|
||||||
id: "Gz+4CI",
|
|
||||||
defaultMessage:
|
|
||||||
"Preordered products will be available in all warehouses. You can set a threshold for sold quantity. Leaving input blank will be interpreted as no limit to sale. Sold items will be allocated at the warehouse assigned to chosen shipping zone.",
|
|
||||||
description: "info text",
|
|
||||||
})}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<div className={classes.thresholdRow}>
|
<div className={classes.thresholdRow}>
|
||||||
<TextField
|
<TextField
|
||||||
|
@ -543,15 +397,10 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
}}
|
}}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={intl.formatMessage({
|
helperText={intl.formatMessage(
|
||||||
id: "NcY4ph",
|
messages.preorderTresholdDescription,
|
||||||
defaultMessage:
|
)}
|
||||||
"Threshold that cannot be exceeded even if per channel thresholds are still available",
|
label={intl.formatMessage(messages.preorderTresholdLabel)}
|
||||||
})}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
id: "RJ5QxE",
|
|
||||||
defaultMessage: "Global threshold",
|
|
||||||
})}
|
|
||||||
name="globalThreshold"
|
name="globalThreshold"
|
||||||
onChange={onThresholdChange}
|
onChange={onThresholdChange}
|
||||||
value={data.globalThreshold ?? ""}
|
value={data.globalThreshold ?? ""}
|
||||||
|
@ -563,19 +412,10 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
className={classes.preorderItemsLeftCount}
|
className={classes.preorderItemsLeftCount}
|
||||||
>
|
>
|
||||||
{data.globalThreshold
|
{data.globalThreshold
|
||||||
? intl.formatMessage(
|
? intl.formatMessage(messages.preorderTresholdUnitsLeft, {
|
||||||
{
|
unitsLeft,
|
||||||
id: "7wkGxW",
|
})
|
||||||
defaultMessage: "{unitsLeft} units left",
|
: intl.formatMessage(messages.preorderTresholdUnlimited)}
|
||||||
description: "app has been installed",
|
|
||||||
},
|
|
||||||
{ unitsLeft },
|
|
||||||
)
|
|
||||||
: intl.formatMessage({
|
|
||||||
id: "CEavJt",
|
|
||||||
defaultMessage: "Unlimited",
|
|
||||||
description: "section header",
|
|
||||||
})}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -592,25 +432,13 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className={classes.colName}>
|
<TableCell className={classes.colName}>
|
||||||
<FormattedMessage
|
<FormattedMessage {...sectionNames.channels} />
|
||||||
id="JyQEHU"
|
|
||||||
defaultMessage="Channels"
|
|
||||||
description="tabel column header"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colSoldUnits}>
|
<TableCell className={classes.colSoldUnits}>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.soldUnits} />
|
||||||
id="HcQEUk"
|
|
||||||
defaultMessage="Sold units"
|
|
||||||
description="table column header, sold units preorder quantity"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className={classes.colThreshold}>
|
<TableCell className={classes.colThreshold}>
|
||||||
<FormattedMessage
|
<FormattedMessage {...messages.channelTreshold} />
|
||||||
id="MNZY28"
|
|
||||||
defaultMessage="Channel threshold"
|
|
||||||
description="table column header"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
@ -638,10 +466,9 @@ const ProductStocks: React.FC<ProductStocksProps> = ({
|
||||||
min: 0,
|
min: 0,
|
||||||
type: "number",
|
type: "number",
|
||||||
}}
|
}}
|
||||||
placeholder={intl.formatMessage({
|
placeholder={intl.formatMessage(
|
||||||
id: "ekXood",
|
messages.preorderTresholdUnlimited,
|
||||||
defaultMessage: "Unlimited",
|
)}
|
||||||
})}
|
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
onVariantChannelListingChange(listing.id, {
|
onVariantChannelListingChange(listing.id, {
|
||||||
costPrice: listing.costPrice,
|
costPrice: listing.costPrice,
|
||||||
|
|
121
src/products/components/ProductStocks/messages.ts
Normal file
121
src/products/components/ProductStocks/messages.ts
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
import { defineMessages } from "react-intl";
|
||||||
|
|
||||||
|
export const messages = defineMessages({
|
||||||
|
title: {
|
||||||
|
id: "4qe6hO",
|
||||||
|
defaultMessage: "Inventory",
|
||||||
|
description: "product stock, section header",
|
||||||
|
},
|
||||||
|
sku: {
|
||||||
|
id: "SM+yG0",
|
||||||
|
defaultMessage: "SKU (Stock Keeping Unit)",
|
||||||
|
description: "input label",
|
||||||
|
},
|
||||||
|
variantInPreorder: {
|
||||||
|
id: "eAFU/E",
|
||||||
|
defaultMessage: "Variant currently in preorder",
|
||||||
|
description: "product inventory, checkbox",
|
||||||
|
},
|
||||||
|
trackInventory: {
|
||||||
|
id: "TjGYna",
|
||||||
|
defaultMessage: "Track Inventory",
|
||||||
|
description: "product inventory, checkbox",
|
||||||
|
},
|
||||||
|
trackInventoryDescription: {
|
||||||
|
id: "Wyl25+",
|
||||||
|
defaultMessage:
|
||||||
|
"Active inventory tracking will automatically calculate changes of stock",
|
||||||
|
description: "product inventory, checkbox description",
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
id: "bp/i0x",
|
||||||
|
defaultMessage: "Quantity",
|
||||||
|
description: "header",
|
||||||
|
},
|
||||||
|
warehouseName: {
|
||||||
|
id: "ErvPaM",
|
||||||
|
defaultMessage: "Warehouse Name",
|
||||||
|
description: "header",
|
||||||
|
},
|
||||||
|
allocated: {
|
||||||
|
id: "/C//FB",
|
||||||
|
defaultMessage: "Allocated",
|
||||||
|
description: "header, allocated product quantity",
|
||||||
|
},
|
||||||
|
noChannelWarehousesAllocation: {
|
||||||
|
id: "taS/08",
|
||||||
|
defaultMessage:
|
||||||
|
"Assign this variant to a channel in the product channel manager to define warehouses allocation",
|
||||||
|
description: "variant stocks section subtitle",
|
||||||
|
},
|
||||||
|
configureWarehouseForVariant: {
|
||||||
|
id: "D8nsBc",
|
||||||
|
defaultMessage:
|
||||||
|
"There are no warehouses set up for your store. To add stock quantity to the variant please <a>configure a warehouse</a>",
|
||||||
|
description: "no warehouses info",
|
||||||
|
},
|
||||||
|
configureWarehouseForProduct: {
|
||||||
|
id: "RLBLPQ",
|
||||||
|
defaultMessage:
|
||||||
|
"There are no warehouses set up for your store. To add stock quantity to the product please <a>configure a warehouse</a>",
|
||||||
|
description: "no warehouses info",
|
||||||
|
},
|
||||||
|
assignWarehouse: {
|
||||||
|
id: "cBHRxx",
|
||||||
|
defaultMessage: "Assign Warehouse",
|
||||||
|
description: "button",
|
||||||
|
},
|
||||||
|
preorderEndDateSetup: {
|
||||||
|
id: "REVk27",
|
||||||
|
defaultMessage:
|
||||||
|
"Set up an end date of preorder. When end date will be reached product will be automatically taken from preorder to standard selling",
|
||||||
|
description: "info text",
|
||||||
|
},
|
||||||
|
endDateCancel: {
|
||||||
|
id: "v9ILn/",
|
||||||
|
defaultMessage: "CANCEL END DATE",
|
||||||
|
description: "button",
|
||||||
|
},
|
||||||
|
endDateSetup: {
|
||||||
|
id: "9IWg/f",
|
||||||
|
defaultMessage: "SETUP END DATE",
|
||||||
|
description: "button",
|
||||||
|
},
|
||||||
|
preorderProductsAvailability: {
|
||||||
|
id: "Gz+4CI",
|
||||||
|
defaultMessage:
|
||||||
|
"Preordered products will be available in all warehouses. You can set a threshold for sold quantity. Leaving input blank will be interpreted as no limit to sale. Sold items will be allocated at the warehouse assigned to chosen shipping zone.",
|
||||||
|
description: "info text",
|
||||||
|
},
|
||||||
|
preorderTresholdLabel: {
|
||||||
|
id: "/iijFq",
|
||||||
|
defaultMessage: "Global threshold",
|
||||||
|
description: "input label",
|
||||||
|
},
|
||||||
|
preorderTresholdDescription: {
|
||||||
|
id: "HYC6cH",
|
||||||
|
defaultMessage:
|
||||||
|
"Threshold that cannot be exceeded even if per channel thresholds are still available",
|
||||||
|
description: "input description",
|
||||||
|
},
|
||||||
|
preorderTresholdUnitsLeft: {
|
||||||
|
id: "JkO0jp",
|
||||||
|
defaultMessage: "{unitsLeft} units left",
|
||||||
|
description: "input description",
|
||||||
|
},
|
||||||
|
preorderTresholdUnlimited: {
|
||||||
|
id: "tlGXkh",
|
||||||
|
defaultMessage: "Unlimited",
|
||||||
|
description: "input description",
|
||||||
|
},
|
||||||
|
soldUnits: {
|
||||||
|
id: "HcQEUk",
|
||||||
|
defaultMessage: "Sold units",
|
||||||
|
description: "table column header, sold units preorder quantity",
|
||||||
|
},
|
||||||
|
channelTreshold: {
|
||||||
|
id: "MNZY28",
|
||||||
|
defaultMessage: "Channel threshold",
|
||||||
|
description: "table column header",
|
||||||
|
},
|
||||||
|
});
|
93
src/products/components/ProductStocks/styles.ts
Normal file
93
src/products/components/ProductStocks/styles.ts
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import { ICONBUTTON_SIZE, makeStyles } from "@saleor/macaw-ui";
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
colAction: {
|
||||||
|
padding: 0,
|
||||||
|
width: `calc(${ICONBUTTON_SIZE}px + ${theme.spacing(1)})`,
|
||||||
|
},
|
||||||
|
colName: {},
|
||||||
|
colQuantity: {
|
||||||
|
textAlign: "right",
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
colSoldUnits: {
|
||||||
|
textAlign: "right",
|
||||||
|
width: 150,
|
||||||
|
},
|
||||||
|
colThreshold: {
|
||||||
|
textAlign: "right",
|
||||||
|
width: 180,
|
||||||
|
},
|
||||||
|
editWarehouses: {
|
||||||
|
marginRight: theme.spacing(-1),
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
padding: theme.spacing(1.5),
|
||||||
|
textAlign: "right",
|
||||||
|
},
|
||||||
|
menuItem: {
|
||||||
|
"&:not(:last-of-type)": {
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
noWarehouseInfo: {
|
||||||
|
marginTop: theme.spacing(),
|
||||||
|
},
|
||||||
|
paper: {
|
||||||
|
padding: theme.spacing(2),
|
||||||
|
},
|
||||||
|
popper: {
|
||||||
|
marginTop: theme.spacing(1),
|
||||||
|
zIndex: 2,
|
||||||
|
},
|
||||||
|
quantityContainer: {
|
||||||
|
paddingTop: theme.spacing(),
|
||||||
|
},
|
||||||
|
quantityHeader: {
|
||||||
|
alignItems: "center",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
skuInputContainer: {
|
||||||
|
display: "grid",
|
||||||
|
gridColumnGap: theme.spacing(3),
|
||||||
|
gridTemplateColumns: "repeat(2, 1fr)",
|
||||||
|
},
|
||||||
|
dateTimeInputs: {
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
},
|
||||||
|
preorderInfo: {
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
marginTop: theme.spacing(2),
|
||||||
|
display: "block",
|
||||||
|
},
|
||||||
|
caption: {
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
thresholdRow: {
|
||||||
|
display: "grid",
|
||||||
|
gridColumnGap: theme.spacing(3),
|
||||||
|
gridTemplateColumns: "3fr 1fr",
|
||||||
|
marginTop: theme.spacing(1),
|
||||||
|
},
|
||||||
|
thresholdInput: {
|
||||||
|
maxWidth: 400,
|
||||||
|
},
|
||||||
|
preorderItemsLeftCount: {
|
||||||
|
fontSize: 14,
|
||||||
|
paddingTop: theme.spacing(2),
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
preorderLimitInfo: {
|
||||||
|
marginTop: theme.spacing(3),
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
marginLeft: theme.spacing(1),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: "ProductStocks",
|
||||||
|
},
|
||||||
|
);
|
|
@ -112,12 +112,6 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
|
||||||
result: searchAttributeValuesOpts,
|
result: searchAttributeValuesOpts,
|
||||||
reset: searchAttributeReset,
|
reset: searchAttributeReset,
|
||||||
} = useAttributeValueSearchHandler(DEFAULT_INITIAL_SEARCH_DATA);
|
} = useAttributeValueSearchHandler(DEFAULT_INITIAL_SEARCH_DATA);
|
||||||
const warehouses = useWarehouseListQuery({
|
|
||||||
displayLoader: true,
|
|
||||||
variables: {
|
|
||||||
first: 50,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const [updateMetadata] = useUpdateMetadataMutation({});
|
const [updateMetadata] = useUpdateMetadataMutation({});
|
||||||
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
||||||
const taxTypes = useTaxTypeListQuery({});
|
const taxTypes = useTaxTypeListQuery({});
|
||||||
|
@ -160,6 +154,16 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const warehouses = useWarehouseListQuery({
|
||||||
|
displayLoader: true,
|
||||||
|
variables: {
|
||||||
|
first: 50,
|
||||||
|
filter: {
|
||||||
|
channels: currentChannels.map(channel => channel.id),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const handleSuccess = (productId: string) => {
|
const handleSuccess = (productId: string) => {
|
||||||
notify({
|
notify({
|
||||||
status: "success",
|
status: "success",
|
||||||
|
|
|
@ -156,12 +156,6 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
result: searchAttributeValuesOpts,
|
result: searchAttributeValuesOpts,
|
||||||
reset: searchAttributeReset,
|
reset: searchAttributeReset,
|
||||||
} = useAttributeValueSearchHandler(DEFAULT_INITIAL_SEARCH_DATA);
|
} = useAttributeValueSearchHandler(DEFAULT_INITIAL_SEARCH_DATA);
|
||||||
const warehouses = useWarehouseListQuery({
|
|
||||||
displayLoader: true,
|
|
||||||
variables: {
|
|
||||||
first: 50,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const shop = useShop();
|
const shop = useShop();
|
||||||
const [updateMetadata] = useUpdateMetadataMutation({});
|
const [updateMetadata] = useUpdateMetadataMutation({});
|
||||||
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
const [updatePrivateMetadata] = useUpdatePrivateMetadataMutation({});
|
||||||
|
@ -324,6 +318,16 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
{ formId: PRODUCT_UPDATE_FORM_ID },
|
{ formId: PRODUCT_UPDATE_FORM_ID },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const warehouses = useWarehouseListQuery({
|
||||||
|
displayLoader: true,
|
||||||
|
variables: {
|
||||||
|
first: 50,
|
||||||
|
filter: {
|
||||||
|
channels: currentChannels.map(channel => channel.id),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const [
|
const [
|
||||||
updateChannels,
|
updateChannels,
|
||||||
updateChannelsOpts,
|
updateChannelsOpts,
|
||||||
|
|
|
@ -82,13 +82,6 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({
|
||||||
setErrors([]);
|
setErrors([]);
|
||||||
}, [variantId]);
|
}, [variantId]);
|
||||||
|
|
||||||
const warehouses = useWarehouseListQuery({
|
|
||||||
displayLoader: true,
|
|
||||||
variables: {
|
|
||||||
first: 50,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data, loading } = useProductVariantDetailsQuery({
|
const { data, loading } = useProductVariantDetailsQuery({
|
||||||
displayLoader: true,
|
displayLoader: true,
|
||||||
variables: {
|
variables: {
|
||||||
|
@ -196,6 +189,16 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({
|
||||||
const variant = data?.productVariant;
|
const variant = data?.productVariant;
|
||||||
const channels = createVariantChannels(variant);
|
const channels = createVariantChannels(variant);
|
||||||
|
|
||||||
|
const warehouses = useWarehouseListQuery({
|
||||||
|
displayLoader: true,
|
||||||
|
variables: {
|
||||||
|
first: 50,
|
||||||
|
filter: {
|
||||||
|
channels: channels.map(channel => channel.id),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const [
|
const [
|
||||||
deactivatePreorder,
|
deactivatePreorder,
|
||||||
deactivatePreoderOpts,
|
deactivatePreoderOpts,
|
||||||
|
|
|
@ -14,6 +14,7 @@ export const searchWarehouses = gql`
|
||||||
sortBy: { direction: ASC, field: NAME }
|
sortBy: { direction: ASC, field: NAME }
|
||||||
filter: { search: $query }
|
filter: { search: $query }
|
||||||
) {
|
) {
|
||||||
|
totalCount
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -36,3 +36,17 @@ 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
Loading…
Reference in a new issue