diff --git a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx index b3740c60e..d8c23ed2e 100644 --- a/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx +++ b/src/products/components/ProductUpdatePage/ProductUpdatePage.tsx @@ -252,7 +252,10 @@ export const ProductUpdatePage: React.FC = ({ disabled={disabled} errors={errors} stocks={stocks} - onChange={changeStockData} + onChange={(id, value) => { + triggerChange(); + changeStockData(id, value); + }} onFormDataChange={change} onWarehousesEdit={onWarehousesEdit} /> diff --git a/src/products/components/ProductWarehousesDialog/ProductWarehousesDialog.tsx b/src/products/components/ProductWarehousesDialog/ProductWarehousesDialog.tsx index ec602ea12..9faaa1be9 100644 --- a/src/products/components/ProductWarehousesDialog/ProductWarehousesDialog.tsx +++ b/src/products/components/ProductWarehousesDialog/ProductWarehousesDialog.tsx @@ -13,13 +13,14 @@ import ConfirmButton, { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { buttonMessages } from "@saleor/intl"; -import { UserError } from "@saleor/types"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import Skeleton from "@saleor/components/Skeleton"; import { Product_variants_stocks } from "@saleor/products/types/Product"; import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import { isSelected, toggle } from "@saleor/utils/lists"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; +import { BulkStockErrorFragment } from "@saleor/products/types/BulkStockErrorFragment"; +import { StockErrorFragment } from "@saleor/products/types/StockErrorFragment"; const useStyles = makeStyles( theme => ({ @@ -41,7 +42,7 @@ const useStyles = makeStyles( export interface ProductWarehousesDialogProps { confirmButtonState: ConfirmButtonTransitionState; disabled: boolean; - errors: UserError[]; + errors: Array; open: boolean; stocks: Product_variants_stocks[]; warehouses: SearchWarehouses_search_edges_node[]; diff --git a/src/products/mutations.ts b/src/products/mutations.ts index 42605ba11..98247c432 100644 --- a/src/products/mutations.ts +++ b/src/products/mutations.ts @@ -71,6 +71,19 @@ export const bulkProductErrorFragment = gql` index } `; +const bulkStockErrorFragment = gql` + fragment BulkStockErrorFragment on BulkStockError { + code + field + index + } +`; +const stockErrorFragment = gql` + fragment StockErrorFragment on StockError { + code + field + } +`; export const productImageCreateMutation = gql` ${productErrorFragment} @@ -179,8 +192,10 @@ export const TypedProductUpdateMutation = TypedMutation< >(productUpdateMutation); export const simpleProductUpdateMutation = gql` + ${bulkStockErrorFragment} ${productErrorFragment} ${productFragmentDetails} + ${stockErrorFragment} ${fragmentVariant} mutation SimpleProductUpdate( $id: ID! @@ -196,6 +211,9 @@ export const simpleProductUpdateMutation = gql` $productVariantId: ID! $productVariantInput: ProductVariantInput! $seo: SeoInput + $addStocks: [StockInput!]! + $deleteStocks: [ID!]! + $updateStocks: [StockInput!]! ) { productUpdate( id: $id @@ -227,6 +245,39 @@ export const simpleProductUpdateMutation = gql` ...ProductVariant } } + productVariantStocksCreate( + stocks: $addStocks + variantId: $productVariantId + ) { + errors: bulkStockErrors { + ...BulkStockErrorFragment + } + productVariant { + ...ProductVariant + } + } + productVariantStocksDelete( + warehouseIds: $deleteStocks + variantId: $productVariantId + ) { + errors: stockErrors { + ...StockErrorFragment + } + productVariant { + ...ProductVariant + } + } + productVariantStocksUpdate( + stocks: $updateStocks + variantId: $productVariantId + ) { + errors: bulkStockErrors { + ...BulkStockErrorFragment + } + productVariant { + ...ProductVariant + } + } } `; export const TypedSimpleProductUpdateMutation = TypedMutation< @@ -499,6 +550,7 @@ export const TypedProductVariantBulkDeleteMutation = TypedMutation< >(ProductVariantBulkDeleteMutation); const addOrRemoveStocks = gql` + ${bulkStockErrorFragment} ${stockFragment} mutation AddOrRemoveStocks( $variantId: ID! @@ -506,10 +558,8 @@ const addOrRemoveStocks = gql` $remove: [ID!]! ) { productVariantStocksCreate(stocks: $add, variantId: $variantId) { - bulkStockErrors { - code - field - index + errors: bulkStockErrors { + ...BulkStockErrorFragment } productVariant { id @@ -519,7 +569,7 @@ const addOrRemoveStocks = gql` } } productVariantStocksDelete(warehouseIds: $remove, variantId: $variantId) { - stockErrors { + errors: stockErrors { code field } diff --git a/src/products/types/AddOrRemoveStocks.ts b/src/products/types/AddOrRemoveStocks.ts index 4bf5efc6d..723501871 100644 --- a/src/products/types/AddOrRemoveStocks.ts +++ b/src/products/types/AddOrRemoveStocks.ts @@ -8,7 +8,7 @@ import { StockInput, ProductErrorCode, StockErrorCode } from "./../../types/glob // GraphQL mutation operation: AddOrRemoveStocks // ==================================================== -export interface AddOrRemoveStocks_productVariantStocksCreate_bulkStockErrors { +export interface AddOrRemoveStocks_productVariantStocksCreate_errors { __typename: "BulkStockError"; code: ProductErrorCode; field: string | null; @@ -36,11 +36,11 @@ export interface AddOrRemoveStocks_productVariantStocksCreate_productVariant { export interface AddOrRemoveStocks_productVariantStocksCreate { __typename: "ProductVariantStocksCreate"; - bulkStockErrors: AddOrRemoveStocks_productVariantStocksCreate_bulkStockErrors[]; + errors: AddOrRemoveStocks_productVariantStocksCreate_errors[]; productVariant: AddOrRemoveStocks_productVariantStocksCreate_productVariant | null; } -export interface AddOrRemoveStocks_productVariantStocksDelete_stockErrors { +export interface AddOrRemoveStocks_productVariantStocksDelete_errors { __typename: "StockError"; code: StockErrorCode; field: string | null; @@ -67,7 +67,7 @@ export interface AddOrRemoveStocks_productVariantStocksDelete_productVariant { export interface AddOrRemoveStocks_productVariantStocksDelete { __typename: "ProductVariantStocksDelete"; - stockErrors: AddOrRemoveStocks_productVariantStocksDelete_stockErrors[]; + errors: AddOrRemoveStocks_productVariantStocksDelete_errors[]; productVariant: AddOrRemoveStocks_productVariantStocksDelete_productVariant | null; } diff --git a/src/products/types/BulkStockErrorFragment.ts b/src/products/types/BulkStockErrorFragment.ts new file mode 100644 index 000000000..9333796c8 --- /dev/null +++ b/src/products/types/BulkStockErrorFragment.ts @@ -0,0 +1,16 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { ProductErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: BulkStockErrorFragment +// ==================================================== + +export interface BulkStockErrorFragment { + __typename: "BulkStockError"; + code: ProductErrorCode; + field: string | null; + index: number | null; +} diff --git a/src/products/types/SimpleProductUpdate.ts b/src/products/types/SimpleProductUpdate.ts index d9d137e59..c54d9ea19 100644 --- a/src/products/types/SimpleProductUpdate.ts +++ b/src/products/types/SimpleProductUpdate.ts @@ -2,7 +2,7 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeValueInput, ProductVariantInput, SeoInput, ProductErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; +import { AttributeValueInput, ProductVariantInput, SeoInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, StockErrorCode } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: SimpleProductUpdate @@ -315,9 +315,380 @@ export interface SimpleProductUpdate_productVariantUpdate { productVariant: SimpleProductUpdate_productVariantUpdate_productVariant | null; } +export interface SimpleProductUpdate_productVariantStocksCreate_errors { + __typename: "BulkStockError"; + code: ProductErrorCode; + field: string | null; + index: number | null; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + valueRequired: boolean; + values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_attribute; + values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes_values | null)[]; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (SimpleProductUpdate_productVariantStocksCreate_productVariant_product_variants_images | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_product { + __typename: "Product"; + id: string; + images: (SimpleProductUpdate_productVariantStocksCreate_productVariant_product_images | null)[] | null; + name: string; + thumbnail: SimpleProductUpdate_productVariantStocksCreate_productVariant_product_thumbnail | null; + variants: (SimpleProductUpdate_productVariantStocksCreate_productVariant_product_variants | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_stocks_warehouse { + __typename: "Warehouse"; + id: string; + name: string; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_stocks { + __typename: "Stock"; + id: string; + quantity: number; + warehouse: SimpleProductUpdate_productVariantStocksCreate_productVariant_stocks_warehouse; +} + +export interface SimpleProductUpdate_productVariantStocksCreate_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: SimpleProductUpdate_productVariantStocksCreate_productVariant_attributes[]; + costPrice: SimpleProductUpdate_productVariantStocksCreate_productVariant_costPrice | null; + images: (SimpleProductUpdate_productVariantStocksCreate_productVariant_images | null)[] | null; + name: string; + priceOverride: SimpleProductUpdate_productVariantStocksCreate_productVariant_priceOverride | null; + product: SimpleProductUpdate_productVariantStocksCreate_productVariant_product; + sku: string; + stocks: (SimpleProductUpdate_productVariantStocksCreate_productVariant_stocks | null)[] | null; + trackInventory: boolean; +} + +export interface SimpleProductUpdate_productVariantStocksCreate { + __typename: "ProductVariantStocksCreate"; + errors: SimpleProductUpdate_productVariantStocksCreate_errors[]; + productVariant: SimpleProductUpdate_productVariantStocksCreate_productVariant | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_errors { + __typename: "StockError"; + code: StockErrorCode; + field: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + valueRequired: boolean; + values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_attribute; + values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes_values | null)[]; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (SimpleProductUpdate_productVariantStocksDelete_productVariant_product_variants_images | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_product { + __typename: "Product"; + id: string; + images: (SimpleProductUpdate_productVariantStocksDelete_productVariant_product_images | null)[] | null; + name: string; + thumbnail: SimpleProductUpdate_productVariantStocksDelete_productVariant_product_thumbnail | null; + variants: (SimpleProductUpdate_productVariantStocksDelete_productVariant_product_variants | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_stocks_warehouse { + __typename: "Warehouse"; + id: string; + name: string; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_stocks { + __typename: "Stock"; + id: string; + quantity: number; + warehouse: SimpleProductUpdate_productVariantStocksDelete_productVariant_stocks_warehouse; +} + +export interface SimpleProductUpdate_productVariantStocksDelete_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: SimpleProductUpdate_productVariantStocksDelete_productVariant_attributes[]; + costPrice: SimpleProductUpdate_productVariantStocksDelete_productVariant_costPrice | null; + images: (SimpleProductUpdate_productVariantStocksDelete_productVariant_images | null)[] | null; + name: string; + priceOverride: SimpleProductUpdate_productVariantStocksDelete_productVariant_priceOverride | null; + product: SimpleProductUpdate_productVariantStocksDelete_productVariant_product; + sku: string; + stocks: (SimpleProductUpdate_productVariantStocksDelete_productVariant_stocks | null)[] | null; + trackInventory: boolean; +} + +export interface SimpleProductUpdate_productVariantStocksDelete { + __typename: "ProductVariantStocksDelete"; + errors: SimpleProductUpdate_productVariantStocksDelete_errors[]; + productVariant: SimpleProductUpdate_productVariantStocksDelete_productVariant | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_errors { + __typename: "BulkStockError"; + code: ProductErrorCode; + field: string | null; + index: number | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_attribute_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_attribute { + __typename: "Attribute"; + id: string; + name: string | null; + slug: string | null; + valueRequired: boolean; + values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_attribute_values | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes { + __typename: "SelectedAttribute"; + attribute: SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_attribute; + values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes_values | null)[]; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_costPrice { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_priceOverride { + __typename: "Money"; + amount: number; + currency: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_images { + __typename: "ProductImage"; + id: string; + alt: string; + sortOrder: number | null; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_thumbnail { + __typename: "Image"; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_variants_images { + __typename: "ProductImage"; + id: string; + url: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_variants { + __typename: "ProductVariant"; + id: string; + name: string; + sku: string; + images: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_variants_images | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_product { + __typename: "Product"; + id: string; + images: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_images | null)[] | null; + name: string; + thumbnail: SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_thumbnail | null; + variants: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_variants | null)[] | null; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_stocks_warehouse { + __typename: "Warehouse"; + id: string; + name: string; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_stocks { + __typename: "Stock"; + id: string; + quantity: number; + warehouse: SimpleProductUpdate_productVariantStocksUpdate_productVariant_stocks_warehouse; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant { + __typename: "ProductVariant"; + id: string; + attributes: SimpleProductUpdate_productVariantStocksUpdate_productVariant_attributes[]; + costPrice: SimpleProductUpdate_productVariantStocksUpdate_productVariant_costPrice | null; + images: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_images | null)[] | null; + name: string; + priceOverride: SimpleProductUpdate_productVariantStocksUpdate_productVariant_priceOverride | null; + product: SimpleProductUpdate_productVariantStocksUpdate_productVariant_product; + sku: string; + stocks: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_stocks | null)[] | null; + trackInventory: boolean; +} + +export interface SimpleProductUpdate_productVariantStocksUpdate { + __typename: "ProductVariantStocksUpdate"; + errors: SimpleProductUpdate_productVariantStocksUpdate_errors[]; + productVariant: SimpleProductUpdate_productVariantStocksUpdate_productVariant | null; +} + export interface SimpleProductUpdate { productUpdate: SimpleProductUpdate_productUpdate | null; productVariantUpdate: SimpleProductUpdate_productVariantUpdate | null; + productVariantStocksCreate: SimpleProductUpdate_productVariantStocksCreate | null; + productVariantStocksDelete: SimpleProductUpdate_productVariantStocksDelete | null; + productVariantStocksUpdate: SimpleProductUpdate_productVariantStocksUpdate | null; } export interface SimpleProductUpdateVariables { @@ -334,4 +705,7 @@ export interface SimpleProductUpdateVariables { productVariantId: string; productVariantInput: ProductVariantInput; seo?: SeoInput | null; + addStocks: StockInput[]; + deleteStocks: string[]; + updateStocks: StockInput[]; } diff --git a/src/products/types/StockErrorFragment.ts b/src/products/types/StockErrorFragment.ts new file mode 100644 index 000000000..18a48980f --- /dev/null +++ b/src/products/types/StockErrorFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { StockErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: StockErrorFragment +// ==================================================== + +export interface StockErrorFragment { + __typename: "StockError"; + code: StockErrorCode; + field: string | null; +} diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index b6a1f6f03..9c0433895 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -88,8 +88,8 @@ export const ProductUpdate: React.FC = ({ id, params }) => { const [addOrRemoveStocks, addOrRemoveStocksOpts] = useAddOrRemoveStocks({ onCompleted: data => { if ( - data.productVariantStocksCreate.bulkStockErrors.length === 0 && - data.productVariantStocksDelete.stockErrors.length === 0 + data.productVariantStocksCreate.errors.length === 0 && + data.productVariantStocksDelete.errors.length === 0 ) { notify({ text: intl.formatMessage(commonMessages.savedChanges) @@ -376,11 +376,12 @@ export const ProductUpdate: React.FC = ({ id, params }) => { {!product?.productType?.hasVariants && ( ({ + quantity: parseInt(stock.value, 0), + warehouse: stock.id + })) }); } };