diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f74d94b3..f95a476aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ All notable, unreleased changes to this project will be documented in this file. - Fix list pagination crash on search - #1230 by @orzechdev - Fix positive float number input validation - #1233 by @orzechdev - Use MacawUI - #1229 by @dominik-zeglen +- Add variant create options dialog - #1238 by @orzechdev # 2.11.1 diff --git a/cypress/elements/catalog/products/product-details.js b/cypress/elements/catalog/products/product-details.js index 840722eeb..74b8c58c2 100644 --- a/cypress/elements/catalog/products/product-details.js +++ b/cypress/elements/catalog/products/product-details.js @@ -9,6 +9,10 @@ export const PRODUCT_DETAILS = { visibleRadioBtn: "[name='isPublished']", channelAvailabilityItem: "[data-test='channel-availability-item']", addVariantsButton: "[data-test*='button-add-variant']", + addVariantsOptionDialog: { + optionMultiple: '[data-test-id="variant-create-option-multiple"]', + optionSingle: '[data-test-id="variant-create-option-single"]' + }, descriptionInput: "[data-test-id='description']", ratingInput: "[name='rating']", skuInput: "[name='sku']", diff --git a/cypress/steps/catalog/products/VariantsSteps.js b/cypress/steps/catalog/products/VariantsSteps.js index 9316fc43b..9546f5ab8 100644 --- a/cypress/steps/catalog/products/VariantsSteps.js +++ b/cypress/steps/catalog/products/VariantsSteps.js @@ -16,6 +16,8 @@ export function variantsShouldBeVisible({ name, price }) { } export function createFirstVariant({ sku, warehouseId, price, attribute }) { cy.get(PRODUCT_DETAILS.addVariantsButton).click(); + cy.get(PRODUCT_DETAILS.addVariantsOptionDialog.optionMultiple).click(); + cy.get(BUTTON_SELECTORS.submit).click(); cy.get(VARIANTS_SELECTORS.valueContainer) .click() .contains(attribute) diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index 6670bf84b..43b25aec4 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -2038,10 +2038,6 @@ "src_dot_components_dot_CompanyAddressInput_dot_944851093": { "string": "Country area" }, - "src_dot_components_dot_ConfirmButton_dot_2845142593": { - "context": "button", - "string": "Error" - }, "src_dot_components_dot_CountryList_dot_2460766407": { "context": "number of countries", "string": "{number} Countries" @@ -2466,18 +2462,6 @@ "context": "weight", "string": "{value} {unit}" }, - "src_dot_components_dot_messages_dot_1219076963": { - "context": "snackbar expand", - "string": "Expand" - }, - "src_dot_components_dot_messages_dot_2473863536": { - "context": "snackbar button undo", - "string": "Undo" - }, - "src_dot_components_dot_messages_dot_3444275093": { - "context": "snackbar collapse", - "string": "Collapse" - }, "src_dot_configuration": { "context": "configuration section name", "string": "Configuration" @@ -3369,6 +3353,9 @@ "src_dot_endHour": { "string": "End Hour" }, + "src_dot_error": { + "string": "Error" + }, "src_dot_exchangeRates": { "context": "Manage and Update your warehouse information", "string": "Exchange Rates" @@ -5560,6 +5547,30 @@ "context": "product label", "string": "Published" }, + "src_dot_products_dot_components_dot_ProductVariantCreateDialog_dot_description": { + "context": "create product variants", + "string": "How would you like to create variants:" + }, + "src_dot_products_dot_components_dot_ProductVariantCreateDialog_dot_optionMultipleDescription": { + "context": "option description", + "string": "Use variant creator to create matrix of selected attribute values to create variants" + }, + "src_dot_products_dot_components_dot_ProductVariantCreateDialog_dot_optionMultipleTitle": { + "context": "option", + "string": "Create multiple variant via variant creator" + }, + "src_dot_products_dot_components_dot_ProductVariantCreateDialog_dot_optionSingleDescription": { + "context": "option description", + "string": "Create new variant using variant details view" + }, + "src_dot_products_dot_components_dot_ProductVariantCreateDialog_dot_optionSingleTitle": { + "context": "option", + "string": "Create single variant" + }, + "src_dot_products_dot_components_dot_ProductVariantCreateDialog_dot_title": { + "context": "dialog header", + "string": "Create Variants" + }, "src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_attributesHeader": { "context": "attributes, section header", "string": "Variant Attributes" diff --git a/src/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog.tsx b/src/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog.tsx new file mode 100644 index 000000000..38d46c146 --- /dev/null +++ b/src/products/components/ProductVariantCreateDialog/ProductVariantCreateDialog.tsx @@ -0,0 +1,121 @@ +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Typography +} from "@material-ui/core"; +import ConfirmButton from "@saleor/components/ConfirmButton"; +import Form from "@saleor/components/Form"; +import FormSpacer from "@saleor/components/FormSpacer"; +import RadioGroupField from "@saleor/components/RadioGroupField"; +import { buttonMessages } from "@saleor/intl"; +import { makeStyles } from "@saleor/macaw-ui"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { messages } from "./messages"; +import { ProductVariantCreateOptionEnum } from "./types"; + +const useStyles = makeStyles( + theme => ({ + option: { + marginBottom: theme.spacing(2), + width: 400 + } + }), + { name: "ProductVariantCreateDialog" } +); + +interface ProductVariantCreateDialogForm { + option: ProductVariantCreateOptionEnum; +} + +export interface ProductVariantCreateDialogProps { + open: boolean; + onClose: () => void; + onConfirm: (option: ProductVariantCreateOptionEnum) => void; +} + +const ProductVariantCreateDialog: React.FC = props => { + const { open, onConfirm, onClose } = props; + + const classes = useStyles(props); + + const initialForm = { + option: ProductVariantCreateOptionEnum.MULTIPLE + }; + + const handleSubmit = (form: ProductVariantCreateDialogForm) => { + onConfirm(form.option); + }; + + const options = [ + { + title: messages.optionMultipleTitle, + subtitle: messages.optionMultipleDescription, + type: ProductVariantCreateOptionEnum.MULTIPLE + }, + { + title: messages.optionSingleTitle, + subtitle: messages.optionSingleDescription, + type: ProductVariantCreateOptionEnum.SINGLE + } + ]; + + return ( + +
+ {({ change, data }) => ( + <> + + + + + + + + + ({ + label: ( +
+ + + + + + +
+ ), + value: option.type + }))} + name="option" + value={data.option} + onChange={change} + /> +
+ + + + + + + )} +
+
+ ); +}; +ProductVariantCreateDialog.displayName = "ProductVariantCreateDialog"; +export default ProductVariantCreateDialog; diff --git a/src/products/components/ProductVariantCreateDialog/index.ts b/src/products/components/ProductVariantCreateDialog/index.ts new file mode 100644 index 000000000..6f4e84eb6 --- /dev/null +++ b/src/products/components/ProductVariantCreateDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductVariantCreateDialog"; +export * from "./ProductVariantCreateDialog"; diff --git a/src/products/components/ProductVariantCreateDialog/messages.ts b/src/products/components/ProductVariantCreateDialog/messages.ts new file mode 100644 index 000000000..44a5cea2d --- /dev/null +++ b/src/products/components/ProductVariantCreateDialog/messages.ts @@ -0,0 +1,29 @@ +import { defineMessages } from "react-intl"; + +export const messages = defineMessages({ + title: { + defaultMessage: "Create Variants", + description: "dialog header" + }, + description: { + defaultMessage: "How would you like to create variants:", + description: "create product variants" + }, + optionMultipleTitle: { + defaultMessage: "Create multiple variant via variant creator", + description: "option" + }, + optionMultipleDescription: { + defaultMessage: + "Use variant creator to create matrix of selected attribute values to create variants", + description: "option description" + }, + optionSingleTitle: { + defaultMessage: "Create single variant", + description: "option" + }, + optionSingleDescription: { + defaultMessage: "Create new variant using variant details view", + description: "option description" + } +}); diff --git a/src/products/components/ProductVariantCreateDialog/types.ts b/src/products/components/ProductVariantCreateDialog/types.ts new file mode 100644 index 000000000..83090fbcf --- /dev/null +++ b/src/products/components/ProductVariantCreateDialog/types.ts @@ -0,0 +1,4 @@ +export enum ProductVariantCreateOptionEnum { + MULTIPLE = "multiple", + SINGLE = "single" +} diff --git a/src/products/urls.ts b/src/products/urls.ts index a7b73b68c..07a3facbf 100644 --- a/src/products/urls.ts +++ b/src/products/urls.ts @@ -67,6 +67,7 @@ export const productListUrl = (params?: ProductListUrlQueryParams): string => export const productPath = (id: string) => urlJoin(productSection + id); export type ProductUrlDialog = + | "add-variants" | "remove" | "remove-variants" | "assign-attribute-value" diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 6486f0d06..20d697a2b 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -28,6 +28,7 @@ import useNotifier from "@saleor/hooks/useNotifier"; import useOnSetDefaultVariant from "@saleor/hooks/useOnSetDefaultVariant"; import useShop from "@saleor/hooks/useShop"; import { commonMessages } from "@saleor/intl"; +import ProductVariantCreateDialog from "@saleor/products/components/ProductVariantCreateDialog"; import { useProductChannelListingUpdate, useProductDeleteMutation, @@ -369,6 +370,7 @@ export const ProductUpdate: React.FC = ({ id, params }) => { return ; } const handleVariantAdd = () => navigate(productVariantAddUrl(id)); + const handleVariantsAdd = () => navigate(productVariantCreatorUrl(id)); const handleImageDelete = (id: string) => () => deleteProductImage({ variables: { id } }); @@ -563,7 +565,7 @@ export const ProductUpdate: React.FC = ({ id, params }) => { }} onWarehouseConfigure={() => navigate(warehouseAddPath)} onVariantAdd={handleVariantAdd} - onVariantsAdd={() => navigate(productVariantCreatorUrl(id))} + onVariantsAdd={() => openModal("add-variants")} onVariantShow={variantId => () => navigate(productVariantEditUrl(product.id, variantId))} onVariantReorder={handleVariantReorder} @@ -643,6 +645,13 @@ export const ProductUpdate: React.FC = ({ id, params }) => { /> + + option === "multiple" ? handleVariantsAdd() : handleVariantAdd() + } + /> ); };