Fix attribute errors
This commit is contained in:
parent
d63d9b41be
commit
4d27960d79
14 changed files with 153 additions and 114 deletions
|
@ -1,6 +1,6 @@
|
||||||
schema {
|
schema {
|
||||||
query: Query
|
query: Query
|
||||||
mutation: Mutations
|
mutation: Mutation
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountAddressCreate {
|
type AccountAddressCreate {
|
||||||
|
@ -405,7 +405,6 @@ type AttributeValueDelete {
|
||||||
|
|
||||||
input AttributeValueInput {
|
input AttributeValueInput {
|
||||||
id: ID
|
id: ID
|
||||||
slug: String
|
|
||||||
values: [String]!
|
values: [String]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1990,7 +1989,7 @@ input MoveProductInput {
|
||||||
sortOrder: Int
|
sortOrder: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutations {
|
type Mutation {
|
||||||
webhookCreate(input: WebhookCreateInput!): WebhookCreate
|
webhookCreate(input: WebhookCreateInput!): WebhookCreate
|
||||||
webhookDelete(id: ID!): WebhookDelete
|
webhookDelete(id: ID!): WebhookDelete
|
||||||
webhookUpdate(id: ID!, input: WebhookUpdateInput!): WebhookUpdate
|
webhookUpdate(id: ID!, input: WebhookUpdateInput!): WebhookUpdate
|
||||||
|
@ -3383,6 +3382,8 @@ type Query {
|
||||||
serviceAccount(id: ID!): ServiceAccount
|
serviceAccount(id: ID!): ServiceAccount
|
||||||
user(id: ID!): User
|
user(id: ID!): User
|
||||||
node(id: ID!): Node
|
node(id: ID!): Node
|
||||||
|
_entities(representations: [_Any]): [_Entity]
|
||||||
|
_service: _Service
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReducedRate {
|
type ReducedRate {
|
||||||
|
@ -4324,6 +4325,7 @@ enum WebhookEventTypeEnum {
|
||||||
ORDER_FULLY_PAID
|
ORDER_FULLY_PAID
|
||||||
ORDER_UPDATED
|
ORDER_UPDATED
|
||||||
ORDER_CANCELLED
|
ORDER_CANCELLED
|
||||||
|
ORDER_FULFILLED
|
||||||
CUSTOMER_CREATED
|
CUSTOMER_CREATED
|
||||||
PRODUCT_CREATED
|
PRODUCT_CREATED
|
||||||
}
|
}
|
||||||
|
@ -4361,3 +4363,11 @@ enum WeightUnitsEnum {
|
||||||
OZ
|
OZ
|
||||||
G
|
G
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scalar _Any
|
||||||
|
|
||||||
|
union _Entity = Address | ServiceAccount | User | ProductVariant | Product | ProductType | Collection | Category | ProductImage
|
||||||
|
|
||||||
|
type _Service {
|
||||||
|
sdl: String
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import Card from "@material-ui/core/Card";
|
import Card from "@material-ui/core/Card";
|
||||||
import CardContent from "@material-ui/core/CardContent";
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { IntlShape, useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import SingleAutocompleteSelectField, {
|
import SingleAutocompleteSelectField, {
|
||||||
SingleAutocompleteChoiceType
|
SingleAutocompleteChoiceType
|
||||||
|
@ -11,6 +13,8 @@ import SingleAutocompleteSelectField, {
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
|
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { VariantCreate_productVariantCreate_productErrors } from "@saleor/products/types/VariantCreate";
|
||||||
|
import { ProductErrorCode } from "@saleor/types/globalTypes";
|
||||||
import { ProductVariant_attributes_attribute_values } from "../../types/ProductVariant";
|
import { ProductVariant_attributes_attribute_values } from "../../types/ProductVariant";
|
||||||
|
|
||||||
export interface VariantAttributeInputData {
|
export interface VariantAttributeInputData {
|
||||||
|
@ -24,7 +28,7 @@ export type VariantAttributeInput = FormsetAtomicData<
|
||||||
interface ProductVariantAttributesProps {
|
interface ProductVariantAttributesProps {
|
||||||
attributes: VariantAttributeInput[];
|
attributes: VariantAttributeInput[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: Record<string, string>;
|
errors: VariantCreate_productVariantCreate_productErrors[];
|
||||||
onChange: FormsetChange<VariantAttributeInputData>;
|
onChange: FormsetChange<VariantAttributeInputData>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +67,19 @@ function getAttributeValueChoices(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function translateErrors(intl: IntlShape) {
|
||||||
|
return {
|
||||||
|
[ProductErrorCode.REQUIRED]: intl.formatMessage({
|
||||||
|
defaultMessage: "All attributes should have value",
|
||||||
|
description: "product attribute error"
|
||||||
|
}),
|
||||||
|
[ProductErrorCode.UNIQUE]: intl.formatMessage({
|
||||||
|
defaultMessage: "This variant already exists",
|
||||||
|
description: "product attribute error"
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
||||||
attributes,
|
attributes,
|
||||||
disabled,
|
disabled,
|
||||||
|
@ -71,6 +88,8 @@ const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const translatedErrors = translateErrors(intl);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardTitle
|
<CardTitle
|
||||||
|
@ -81,30 +100,38 @@ const ProductVariantAttributes: React.FC<ProductVariantAttributesProps> = ({
|
||||||
{attributes === undefined ? (
|
{attributes === undefined ? (
|
||||||
<Skeleton />
|
<Skeleton />
|
||||||
) : (
|
) : (
|
||||||
attributes.map((attribute, attributeIndex) => {
|
attributes.map(attribute => (
|
||||||
return (
|
<SingleAutocompleteSelectField
|
||||||
<SingleAutocompleteSelectField
|
key={attribute.id}
|
||||||
key={attributeIndex}
|
disabled={disabled}
|
||||||
disabled={disabled}
|
displayValue={getAttributeDisplayValue(
|
||||||
displayValue={getAttributeDisplayValue(
|
attribute.id,
|
||||||
attribute.id,
|
attribute.value,
|
||||||
attribute.value,
|
attributes
|
||||||
attributes
|
)}
|
||||||
)}
|
label={attribute.label}
|
||||||
error={!!errors[attribute.id]}
|
name={`attribute:${attribute.id}`}
|
||||||
helperText={errors[attribute.id]}
|
onChange={event => onChange(attribute.id, event.target.value)}
|
||||||
label={attribute.label}
|
value={getAttributeValue(attribute.id, attributes)}
|
||||||
name={`attribute:${attribute.id}`}
|
choices={getAttributeValueChoices(attribute.id, attributes)}
|
||||||
onChange={event => onChange(attribute.id, event.target.value)}
|
allowCustomValues
|
||||||
value={getAttributeValue(attribute.id, attributes)}
|
data-tc="variant-attribute-input"
|
||||||
choices={getAttributeValueChoices(attribute.id, attributes)}
|
/>
|
||||||
allowCustomValues
|
))
|
||||||
data-tc="variant-attribute-input"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
{errors.length > 0 && (
|
||||||
|
<>
|
||||||
|
<FormSpacer />
|
||||||
|
{errors
|
||||||
|
.filter(error => error.field === "attributes")
|
||||||
|
.map(error => (
|
||||||
|
<Typography color="error" key={error.code}>
|
||||||
|
{translatedErrors[error.code]}
|
||||||
|
</Typography>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,12 +13,9 @@ import useFormset, {
|
||||||
FormsetChange,
|
FormsetChange,
|
||||||
FormsetData
|
FormsetData
|
||||||
} from "@saleor/hooks/useFormset";
|
} from "@saleor/hooks/useFormset";
|
||||||
import {
|
import { VariantCreate_productVariantCreate_productErrors } from "@saleor/products/types/VariantCreate";
|
||||||
getVariantAttributeErrors,
|
import { getVariantAttributeInputFromProduct } from "@saleor/products/utils/data";
|
||||||
getVariantAttributeInputFromProduct
|
|
||||||
} from "@saleor/products/utils/data";
|
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { UserError } from "../../../types";
|
|
||||||
import { ProductVariantCreateData_product } from "../../types/ProductVariantCreateData";
|
import { ProductVariantCreateData_product } from "../../types/ProductVariantCreateData";
|
||||||
import ProductVariantAttributes, {
|
import ProductVariantAttributes, {
|
||||||
VariantAttributeInputData
|
VariantAttributeInputData
|
||||||
|
@ -42,7 +39,7 @@ export interface ProductVariantCreatePageSubmitData
|
||||||
|
|
||||||
interface ProductVariantCreatePageProps {
|
interface ProductVariantCreatePageProps {
|
||||||
currencySymbol: string;
|
currencySymbol: string;
|
||||||
errors: UserError[];
|
errors: VariantCreate_productVariantCreate_productErrors[];
|
||||||
header: string;
|
header: string;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
product: ProductVariantCreateData_product;
|
product: ProductVariantCreateData_product;
|
||||||
|
@ -54,7 +51,7 @@ interface ProductVariantCreatePageProps {
|
||||||
|
|
||||||
const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||||
currencySymbol,
|
currencySymbol,
|
||||||
errors: formErrors,
|
errors: apiErrors,
|
||||||
loading,
|
loading,
|
||||||
header,
|
header,
|
||||||
product,
|
product,
|
||||||
|
@ -96,7 +93,7 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form initial={initialForm} errors={formErrors} onSubmit={handleSubmit}>
|
<Form initial={initialForm} errors={apiErrors} onSubmit={handleSubmit}>
|
||||||
{({ change, data, errors, hasChanged, submit, triggerChange }) => {
|
{({ change, data, errors, hasChanged, submit, triggerChange }) => {
|
||||||
const handleAttributeChange: FormsetChange = (id, value) => {
|
const handleAttributeChange: FormsetChange = (id, value) => {
|
||||||
changeAttributeData(id, value);
|
changeAttributeData(id, value);
|
||||||
|
@ -123,10 +120,7 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||||
<ProductVariantAttributes
|
<ProductVariantAttributes
|
||||||
attributes={attributes}
|
attributes={attributes}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
errors={getVariantAttributeErrors(
|
errors={apiErrors}
|
||||||
formErrors,
|
|
||||||
maybe(() => product.productType.variantAttributes)
|
|
||||||
)}
|
|
||||||
onChange={handleAttributeChange}
|
onChange={handleAttributeChange}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -12,12 +12,9 @@ import useFormset, {
|
||||||
FormsetChange,
|
FormsetChange,
|
||||||
FormsetData
|
FormsetData
|
||||||
} from "@saleor/hooks/useFormset";
|
} from "@saleor/hooks/useFormset";
|
||||||
import {
|
import { VariantUpdate_productVariantUpdate_productErrors } from "@saleor/products/types/VariantUpdate";
|
||||||
getAttributeInputFromVariant,
|
import { getAttributeInputFromVariant } from "@saleor/products/utils/data";
|
||||||
getVariantAttributeErrors
|
|
||||||
} from "@saleor/products/utils/data";
|
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { UserError } from "../../../types";
|
|
||||||
import { ProductVariant } from "../../types/ProductVariant";
|
import { ProductVariant } from "../../types/ProductVariant";
|
||||||
import ProductVariantAttributes, {
|
import ProductVariantAttributes, {
|
||||||
VariantAttributeInputData
|
VariantAttributeInputData
|
||||||
|
@ -42,7 +39,7 @@ export interface ProductVariantPageSubmitData
|
||||||
|
|
||||||
interface ProductVariantPageProps {
|
interface ProductVariantPageProps {
|
||||||
variant?: ProductVariant;
|
variant?: ProductVariant;
|
||||||
errors: UserError[];
|
errors: VariantUpdate_productVariantUpdate_productErrors[];
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
placeholderImage?: string;
|
placeholderImage?: string;
|
||||||
|
@ -56,7 +53,7 @@ interface ProductVariantPageProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||||
errors: formErrors,
|
errors: apiErrors,
|
||||||
loading,
|
loading,
|
||||||
header,
|
header,
|
||||||
placeholderImage,
|
placeholderImage,
|
||||||
|
@ -114,7 +111,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||||
<PageHeader title={header} />
|
<PageHeader title={header} />
|
||||||
<Form
|
<Form
|
||||||
initial={initialForm}
|
initial={initialForm}
|
||||||
errors={formErrors}
|
errors={apiErrors}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
confirmLeave
|
confirmLeave
|
||||||
>
|
>
|
||||||
|
@ -146,14 +143,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||||
<ProductVariantAttributes
|
<ProductVariantAttributes
|
||||||
attributes={attributes}
|
attributes={attributes}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
errors={getVariantAttributeErrors(
|
errors={apiErrors}
|
||||||
formErrors,
|
|
||||||
maybe(() =>
|
|
||||||
variant.attributes.map(
|
|
||||||
attribute => attribute.attribute
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
onChange={handleAttributeChange}
|
onChange={handleAttributeChange}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -306,7 +306,8 @@ export const variantUpdateMutation = gql`
|
||||||
trackInventory: $trackInventory
|
trackInventory: $trackInventory
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
errors {
|
productErrors {
|
||||||
|
code
|
||||||
field
|
field
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
|
@ -325,7 +326,8 @@ export const variantCreateMutation = gql`
|
||||||
${fragmentVariant}
|
${fragmentVariant}
|
||||||
mutation VariantCreate($input: ProductVariantCreateInput!) {
|
mutation VariantCreate($input: ProductVariantCreateInput!) {
|
||||||
productVariantCreate(input: $input) {
|
productVariantCreate(input: $input) {
|
||||||
errors {
|
productErrors {
|
||||||
|
code
|
||||||
field
|
field
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,15 @@
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
// This file was automatically generated and should not be edited.
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
import { ProductVariantCreateInput } from "./../../types/globalTypes";
|
import { ProductVariantCreateInput, ProductErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
// ====================================================
|
// ====================================================
|
||||||
// GraphQL mutation operation: VariantCreate
|
// GraphQL mutation operation: VariantCreate
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
export interface VariantCreate_productVariantCreate_errors {
|
export interface VariantCreate_productVariantCreate_productErrors {
|
||||||
__typename: "Error";
|
__typename: "ProductError";
|
||||||
|
code: ProductErrorCode | null;
|
||||||
field: string | null;
|
field: string | null;
|
||||||
message: string | null;
|
message: string | null;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ export interface VariantCreate_productVariantCreate_productVariant {
|
||||||
|
|
||||||
export interface VariantCreate_productVariantCreate {
|
export interface VariantCreate_productVariantCreate {
|
||||||
__typename: "ProductVariantCreate";
|
__typename: "ProductVariantCreate";
|
||||||
errors: VariantCreate_productVariantCreate_errors[] | null;
|
productErrors: VariantCreate_productVariantCreate_productErrors[] | null;
|
||||||
productVariant: VariantCreate_productVariantCreate_productVariant | null;
|
productVariant: VariantCreate_productVariantCreate_productVariant | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,15 @@
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
// This file was automatically generated and should not be edited.
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
import { AttributeValueInput } from "./../../types/globalTypes";
|
import { AttributeValueInput, ProductErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
// ====================================================
|
// ====================================================
|
||||||
// GraphQL mutation operation: VariantUpdate
|
// GraphQL mutation operation: VariantUpdate
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
export interface VariantUpdate_productVariantUpdate_errors {
|
export interface VariantUpdate_productVariantUpdate_productErrors {
|
||||||
__typename: "Error";
|
__typename: "ProductError";
|
||||||
|
code: ProductErrorCode | null;
|
||||||
field: string | null;
|
field: string | null;
|
||||||
message: string | null;
|
message: string | null;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant {
|
||||||
|
|
||||||
export interface VariantUpdate_productVariantUpdate {
|
export interface VariantUpdate_productVariantUpdate {
|
||||||
__typename: "ProductVariantUpdate";
|
__typename: "ProductVariantUpdate";
|
||||||
errors: VariantUpdate_productVariantUpdate_errors[] | null;
|
productErrors: VariantUpdate_productVariantUpdate_productErrors[] | null;
|
||||||
productVariant: VariantUpdate_productVariantUpdate_productVariant | null;
|
productVariant: VariantUpdate_productVariantUpdate_productVariant | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,17 +9,10 @@ import {
|
||||||
ProductDetails_product_collections,
|
ProductDetails_product_collections,
|
||||||
ProductDetails_product_variants
|
ProductDetails_product_variants
|
||||||
} from "@saleor/products/types/ProductDetails";
|
} from "@saleor/products/types/ProductDetails";
|
||||||
import { UserError } from "@saleor/types";
|
|
||||||
import { ProductAttributeInput } from "../components/ProductAttributes";
|
import { ProductAttributeInput } from "../components/ProductAttributes";
|
||||||
import { VariantAttributeInput } from "../components/ProductVariantAttributes";
|
import { VariantAttributeInput } from "../components/ProductVariantAttributes";
|
||||||
import {
|
import { ProductVariant } from "../types/ProductVariant";
|
||||||
ProductVariant,
|
import { ProductVariantCreateData_product } from "../types/ProductVariantCreateData";
|
||||||
ProductVariant_attributes_attribute
|
|
||||||
} from "../types/ProductVariant";
|
|
||||||
import {
|
|
||||||
ProductVariantCreateData_product,
|
|
||||||
ProductVariantCreateData_product_productType_variantAttributes
|
|
||||||
} from "../types/ProductVariantCreateData";
|
|
||||||
|
|
||||||
export interface Collection {
|
export interface Collection {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -197,28 +190,3 @@ export function getProductUpdatePageFormData(
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getVariantAttributeErrors(
|
|
||||||
errors: UserError[],
|
|
||||||
variantAttributes: Array<
|
|
||||||
| ProductVariantCreateData_product_productType_variantAttributes
|
|
||||||
| ProductVariant_attributes_attribute
|
|
||||||
>
|
|
||||||
): Record<string, string> {
|
|
||||||
return maybe(
|
|
||||||
() =>
|
|
||||||
errors.reduce((acc, err) => {
|
|
||||||
const slug = err.field.split(":")[1];
|
|
||||||
const attribute = variantAttributes.find(
|
|
||||||
attribute => attribute.slug === slug
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!!attribute) {
|
|
||||||
acc[attribute.id] = err.message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acc;
|
|
||||||
}, {}),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
navigate(productUrl(productId));
|
navigate(productUrl(productId));
|
||||||
};
|
};
|
||||||
const handleUpdate = (data: VariantUpdate) => {
|
const handleUpdate = (data: VariantUpdate) => {
|
||||||
if (!maybe(() => data.productVariantUpdate.errors.length)) {
|
if (!maybe(() => data.productVariantUpdate.productErrors.length)) {
|
||||||
notify({ text: intl.formatMessage(commonMessages.savedChanges) });
|
notify({ text: intl.formatMessage(commonMessages.savedChanges) });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -74,7 +74,10 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
const formTransitionState = getMutationState(
|
const formTransitionState = getMutationState(
|
||||||
updateVariant.opts.called,
|
updateVariant.opts.called,
|
||||||
updateVariant.opts.loading,
|
updateVariant.opts.loading,
|
||||||
maybe(() => updateVariant.opts.data.productVariantUpdate.errors)
|
maybe(
|
||||||
|
() =>
|
||||||
|
updateVariant.opts.data.productVariantUpdate.productErrors
|
||||||
|
)
|
||||||
);
|
);
|
||||||
const removeTransitionState = getMutationState(
|
const removeTransitionState = getMutationState(
|
||||||
deleteVariant.opts.called,
|
deleteVariant.opts.called,
|
||||||
|
@ -105,7 +108,9 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
<WindowTitle title={maybe(() => data.productVariant.name)} />
|
<WindowTitle title={maybe(() => data.productVariant.name)} />
|
||||||
<ProductVariantPage
|
<ProductVariantPage
|
||||||
errors={maybe(
|
errors={maybe(
|
||||||
() => updateVariant.opts.data.productVariantUpdate.errors,
|
() =>
|
||||||
|
updateVariant.opts.data.productVariantUpdate
|
||||||
|
.productErrors,
|
||||||
[]
|
[]
|
||||||
)}
|
)}
|
||||||
saveButtonBarState={formTransitionState}
|
saveButtonBarState={formTransitionState}
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
>
|
>
|
||||||
{({ data, loading: productLoading }) => {
|
{({ data, loading: productLoading }) => {
|
||||||
const handleCreateSuccess = (data: VariantCreate) => {
|
const handleCreateSuccess = (data: VariantCreate) => {
|
||||||
if (data.productVariantCreate.errors.length === 0) {
|
if (data.productVariantCreate.productErrors.length === 0) {
|
||||||
notify({
|
notify({
|
||||||
text: intl.formatMessage({
|
text: intl.formatMessage({
|
||||||
defaultMessage: "Product created"
|
defaultMessage: "Product created"
|
||||||
|
@ -83,7 +83,8 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
variantCreateResult.called,
|
variantCreateResult.called,
|
||||||
variantCreateResult.loading,
|
variantCreateResult.loading,
|
||||||
maybe(
|
maybe(
|
||||||
() => variantCreateResult.data.productVariantCreate.errors
|
() =>
|
||||||
|
variantCreateResult.data.productVariantCreate.productErrors
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
@ -98,7 +99,8 @@ export const ProductVariant: React.StatelessComponent<ProductUpdateProps> = ({
|
||||||
currencySymbol={maybe(() => shop.defaultCurrency)}
|
currencySymbol={maybe(() => shop.defaultCurrency)}
|
||||||
errors={maybe(
|
errors={maybe(
|
||||||
() =>
|
() =>
|
||||||
variantCreateResult.data.productVariantCreate.errors,
|
variantCreateResult.data.productVariantCreate
|
||||||
|
.productErrors,
|
||||||
[]
|
[]
|
||||||
)}
|
)}
|
||||||
header={intl.formatMessage({
|
header={intl.formatMessage({
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
export const formError = (field: string) => ({
|
export function formError<TErrorPayload>(
|
||||||
field,
|
field: string,
|
||||||
message: "Generic form error"
|
opts?: Partial<Omit<TErrorPayload, "field" | "message">>
|
||||||
});
|
) {
|
||||||
|
return {
|
||||||
|
field,
|
||||||
|
message: "Generic form error",
|
||||||
|
...opts
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import placeholderImage from "@assets/images/placeholder255x255.png";
|
import placeholderImage from "@assets/images/placeholder255x255.png";
|
||||||
import { formError } from "@saleor/storybook/misc";
|
import { ProductErrorCode } from "@saleor/types/globalTypes";
|
||||||
import ProductVariantCreatePage from "../../../products/components/ProductVariantCreatePage";
|
import ProductVariantCreatePage from "../../../products/components/ProductVariantCreatePage";
|
||||||
import { product as productFixture } from "../../../products/fixtures";
|
import { product as productFixture } from "../../../products/fixtures";
|
||||||
import Decorator from "../../Decorator";
|
import Decorator from "../../Decorator";
|
||||||
|
@ -27,7 +27,24 @@ storiesOf("Views / Products / Create product variant", module)
|
||||||
.add("with errors", () => (
|
.add("with errors", () => (
|
||||||
<ProductVariantCreatePage
|
<ProductVariantCreatePage
|
||||||
currencySymbol="USD"
|
currencySymbol="USD"
|
||||||
errors={[formError("attributes:color")]}
|
errors={[
|
||||||
|
{
|
||||||
|
code: ProductErrorCode.REQUIRED,
|
||||||
|
field: "attributes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: ProductErrorCode.UNIQUE,
|
||||||
|
field: "attributes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: ProductErrorCode.ALREADY_EXISTS,
|
||||||
|
field: "sku"
|
||||||
|
}
|
||||||
|
].map(error => ({
|
||||||
|
__typename: "ProductError",
|
||||||
|
message: "Generic form error",
|
||||||
|
...error
|
||||||
|
}))}
|
||||||
header="Add variant"
|
header="Add variant"
|
||||||
loading={false}
|
loading={false}
|
||||||
product={product}
|
product={product}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import placeholderImage from "@assets/images/placeholder60x60.png";
|
import placeholderImage from "@assets/images/placeholder60x60.png";
|
||||||
import { formError } from "@saleor/storybook/misc";
|
import { ProductErrorCode } from "@saleor/types/globalTypes";
|
||||||
import ProductVariantPage from "../../../products/components/ProductVariantPage";
|
import ProductVariantPage from "../../../products/components/ProductVariantPage";
|
||||||
import { variant as variantFixture } from "../../../products/fixtures";
|
import { variant as variantFixture } from "../../../products/fixtures";
|
||||||
import Decorator from "../../Decorator";
|
import Decorator from "../../Decorator";
|
||||||
|
@ -51,6 +51,23 @@ storiesOf("Views / Products / Product variant details", module)
|
||||||
onSubmit={() => undefined}
|
onSubmit={() => undefined}
|
||||||
onVariantClick={() => undefined}
|
onVariantClick={() => undefined}
|
||||||
saveButtonBarState="default"
|
saveButtonBarState="default"
|
||||||
errors={["attributes:Borders", "attributes:Legacy"].map(formError)}
|
errors={[
|
||||||
|
{
|
||||||
|
code: ProductErrorCode.REQUIRED,
|
||||||
|
field: "attributes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: ProductErrorCode.UNIQUE,
|
||||||
|
field: "attributes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: ProductErrorCode.ALREADY_EXISTS,
|
||||||
|
field: "sku"
|
||||||
|
}
|
||||||
|
].map(error => ({
|
||||||
|
__typename: "ProductError",
|
||||||
|
message: "Generic form error",
|
||||||
|
...error
|
||||||
|
}))}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
@ -382,7 +382,6 @@ export interface AttributeValueCreateInput {
|
||||||
|
|
||||||
export interface AttributeValueInput {
|
export interface AttributeValueInput {
|
||||||
id?: string | null;
|
id?: string | null;
|
||||||
slug?: string | null;
|
|
||||||
values: (string | null)[];
|
values: (string | null)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue