Add variant create options dialog (#1238)
* Add variant create options dialog * Update e2e tests * Update option field name * Refactor * Use macaw UI in Variant create dialog * Update messages
This commit is contained in:
parent
e831791493
commit
b024a0fde6
10 changed files with 201 additions and 17 deletions
|
@ -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 list pagination crash on search - #1230 by @orzechdev
|
||||||
- Fix positive float number input validation - #1233 by @orzechdev
|
- Fix positive float number input validation - #1233 by @orzechdev
|
||||||
- Use MacawUI - #1229 by @dominik-zeglen
|
- Use MacawUI - #1229 by @dominik-zeglen
|
||||||
|
- Add variant create options dialog - #1238 by @orzechdev
|
||||||
|
|
||||||
# 2.11.1
|
# 2.11.1
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@ export const PRODUCT_DETAILS = {
|
||||||
visibleRadioBtn: "[name='isPublished']",
|
visibleRadioBtn: "[name='isPublished']",
|
||||||
channelAvailabilityItem: "[data-test='channel-availability-item']",
|
channelAvailabilityItem: "[data-test='channel-availability-item']",
|
||||||
addVariantsButton: "[data-test*='button-add-variant']",
|
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']",
|
descriptionInput: "[data-test-id='description']",
|
||||||
ratingInput: "[name='rating']",
|
ratingInput: "[name='rating']",
|
||||||
skuInput: "[name='sku']",
|
skuInput: "[name='sku']",
|
||||||
|
|
|
@ -16,6 +16,8 @@ export function variantsShouldBeVisible({ name, price }) {
|
||||||
}
|
}
|
||||||
export function createFirstVariant({ sku, warehouseId, price, attribute }) {
|
export function createFirstVariant({ sku, warehouseId, price, attribute }) {
|
||||||
cy.get(PRODUCT_DETAILS.addVariantsButton).click();
|
cy.get(PRODUCT_DETAILS.addVariantsButton).click();
|
||||||
|
cy.get(PRODUCT_DETAILS.addVariantsOptionDialog.optionMultiple).click();
|
||||||
|
cy.get(BUTTON_SELECTORS.submit).click();
|
||||||
cy.get(VARIANTS_SELECTORS.valueContainer)
|
cy.get(VARIANTS_SELECTORS.valueContainer)
|
||||||
.click()
|
.click()
|
||||||
.contains(attribute)
|
.contains(attribute)
|
||||||
|
|
|
@ -2038,10 +2038,6 @@
|
||||||
"src_dot_components_dot_CompanyAddressInput_dot_944851093": {
|
"src_dot_components_dot_CompanyAddressInput_dot_944851093": {
|
||||||
"string": "Country area"
|
"string": "Country area"
|
||||||
},
|
},
|
||||||
"src_dot_components_dot_ConfirmButton_dot_2845142593": {
|
|
||||||
"context": "button",
|
|
||||||
"string": "Error"
|
|
||||||
},
|
|
||||||
"src_dot_components_dot_CountryList_dot_2460766407": {
|
"src_dot_components_dot_CountryList_dot_2460766407": {
|
||||||
"context": "number of countries",
|
"context": "number of countries",
|
||||||
"string": "{number} Countries"
|
"string": "{number} Countries"
|
||||||
|
@ -2466,18 +2462,6 @@
|
||||||
"context": "weight",
|
"context": "weight",
|
||||||
"string": "{value} {unit}"
|
"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": {
|
"src_dot_configuration": {
|
||||||
"context": "configuration section name",
|
"context": "configuration section name",
|
||||||
"string": "Configuration"
|
"string": "Configuration"
|
||||||
|
@ -3369,6 +3353,9 @@
|
||||||
"src_dot_endHour": {
|
"src_dot_endHour": {
|
||||||
"string": "End Hour"
|
"string": "End Hour"
|
||||||
},
|
},
|
||||||
|
"src_dot_error": {
|
||||||
|
"string": "Error"
|
||||||
|
},
|
||||||
"src_dot_exchangeRates": {
|
"src_dot_exchangeRates": {
|
||||||
"context": "Manage and Update your warehouse information",
|
"context": "Manage and Update your warehouse information",
|
||||||
"string": "Exchange Rates"
|
"string": "Exchange Rates"
|
||||||
|
@ -5560,6 +5547,30 @@
|
||||||
"context": "product label",
|
"context": "product label",
|
||||||
"string": "Published"
|
"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": {
|
"src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_attributesHeader": {
|
||||||
"context": "attributes, section header",
|
"context": "attributes, section header",
|
||||||
"string": "Variant Attributes"
|
"string": "Variant Attributes"
|
||||||
|
|
|
@ -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<ProductVariantCreateDialogProps> = 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 (
|
||||||
|
<Dialog onClose={onClose} open={open}>
|
||||||
|
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||||
|
{({ change, data }) => (
|
||||||
|
<>
|
||||||
|
<DialogTitle>
|
||||||
|
<FormattedMessage {...messages.title} />
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography variant="body2">
|
||||||
|
<FormattedMessage {...messages.description} />
|
||||||
|
</Typography>
|
||||||
|
<FormSpacer />
|
||||||
|
<RadioGroupField
|
||||||
|
alignTop
|
||||||
|
choices={options.map(option => ({
|
||||||
|
label: (
|
||||||
|
<div
|
||||||
|
className={classes.option}
|
||||||
|
data-test-id={`variant-create-option-${option.type}`}
|
||||||
|
>
|
||||||
|
<Typography variant="body1">
|
||||||
|
<FormattedMessage {...option.title} />
|
||||||
|
</Typography>
|
||||||
|
<Typography color="textSecondary" variant="caption">
|
||||||
|
<FormattedMessage {...option.subtitle} />
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
value: option.type
|
||||||
|
}))}
|
||||||
|
name="option"
|
||||||
|
value={data.option}
|
||||||
|
onChange={change}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<ConfirmButton
|
||||||
|
transitionState="default"
|
||||||
|
color="primary"
|
||||||
|
variant="contained"
|
||||||
|
type="submit"
|
||||||
|
data-test-id="submit"
|
||||||
|
data-test="submit"
|
||||||
|
>
|
||||||
|
<FormattedMessage {...buttonMessages.create} />
|
||||||
|
</ConfirmButton>
|
||||||
|
</DialogActions>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
ProductVariantCreateDialog.displayName = "ProductVariantCreateDialog";
|
||||||
|
export default ProductVariantCreateDialog;
|
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./ProductVariantCreateDialog";
|
||||||
|
export * from "./ProductVariantCreateDialog";
|
|
@ -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"
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum ProductVariantCreateOptionEnum {
|
||||||
|
MULTIPLE = "multiple",
|
||||||
|
SINGLE = "single"
|
||||||
|
}
|
|
@ -67,6 +67,7 @@ export const productListUrl = (params?: ProductListUrlQueryParams): string =>
|
||||||
|
|
||||||
export const productPath = (id: string) => urlJoin(productSection + id);
|
export const productPath = (id: string) => urlJoin(productSection + id);
|
||||||
export type ProductUrlDialog =
|
export type ProductUrlDialog =
|
||||||
|
| "add-variants"
|
||||||
| "remove"
|
| "remove"
|
||||||
| "remove-variants"
|
| "remove-variants"
|
||||||
| "assign-attribute-value"
|
| "assign-attribute-value"
|
||||||
|
|
|
@ -28,6 +28,7 @@ import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import useOnSetDefaultVariant from "@saleor/hooks/useOnSetDefaultVariant";
|
import useOnSetDefaultVariant from "@saleor/hooks/useOnSetDefaultVariant";
|
||||||
import useShop from "@saleor/hooks/useShop";
|
import useShop from "@saleor/hooks/useShop";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import ProductVariantCreateDialog from "@saleor/products/components/ProductVariantCreateDialog";
|
||||||
import {
|
import {
|
||||||
useProductChannelListingUpdate,
|
useProductChannelListingUpdate,
|
||||||
useProductDeleteMutation,
|
useProductDeleteMutation,
|
||||||
|
@ -369,6 +370,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
return <NotFoundPage onBack={handleBack} />;
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
}
|
}
|
||||||
const handleVariantAdd = () => navigate(productVariantAddUrl(id));
|
const handleVariantAdd = () => navigate(productVariantAddUrl(id));
|
||||||
|
const handleVariantsAdd = () => navigate(productVariantCreatorUrl(id));
|
||||||
|
|
||||||
const handleImageDelete = (id: string) => () =>
|
const handleImageDelete = (id: string) => () =>
|
||||||
deleteProductImage({ variables: { id } });
|
deleteProductImage({ variables: { id } });
|
||||||
|
@ -563,7 +565,7 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
}}
|
}}
|
||||||
onWarehouseConfigure={() => navigate(warehouseAddPath)}
|
onWarehouseConfigure={() => navigate(warehouseAddPath)}
|
||||||
onVariantAdd={handleVariantAdd}
|
onVariantAdd={handleVariantAdd}
|
||||||
onVariantsAdd={() => navigate(productVariantCreatorUrl(id))}
|
onVariantsAdd={() => openModal("add-variants")}
|
||||||
onVariantShow={variantId => () =>
|
onVariantShow={variantId => () =>
|
||||||
navigate(productVariantEditUrl(product.id, variantId))}
|
navigate(productVariantEditUrl(product.id, variantId))}
|
||||||
onVariantReorder={handleVariantReorder}
|
onVariantReorder={handleVariantReorder}
|
||||||
|
@ -643,6 +645,13 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
|
||||||
/>
|
/>
|
||||||
</DialogContentText>
|
</DialogContentText>
|
||||||
</ActionDialog>
|
</ActionDialog>
|
||||||
|
<ProductVariantCreateDialog
|
||||||
|
open={params.action === "add-variants"}
|
||||||
|
onClose={closeModal}
|
||||||
|
onConfirm={option =>
|
||||||
|
option === "multiple" ? handleVariantsAdd() : handleVariantAdd()
|
||||||
|
}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue