Use error codes in product types section

This commit is contained in:
dominik-zeglen 2020-03-10 12:38:01 +01:00
parent 2fd7893df5
commit 0f28c8f4f5
22 changed files with 122 additions and 236 deletions

View file

@ -30,6 +30,8 @@ import useSearchQuery from "@saleor/hooks/useSearchQuery";
import { buttonMessages } from "@saleor/intl"; import { buttonMessages } from "@saleor/intl";
import { maybe, renderCollection } from "@saleor/misc"; import { maybe, renderCollection } from "@saleor/misc";
import { FetchMoreProps } from "@saleor/types"; import { FetchMoreProps } from "@saleor/types";
import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
import { getProductErrorMessage } from "@saleor/utils/errors";
import { SearchAttributes_productType_availableAttributes_edges_node } from "../../hooks/useAvailableAttributeSearch/types/SearchAttributes"; import { SearchAttributes_productType_availableAttributes_edges_node } from "../../hooks/useAvailableAttributeSearch/types/SearchAttributes";
const useStyles = makeStyles( const useStyles = makeStyles(
@ -61,7 +63,7 @@ const useStyles = makeStyles(
export interface AssignAttributeDialogProps extends FetchMoreProps { export interface AssignAttributeDialogProps extends FetchMoreProps {
confirmButtonState: ConfirmButtonTransitionState; confirmButtonState: ConfirmButtonTransitionState;
errors: string[]; errors: ProductErrorFragment[];
open: boolean; open: boolean;
attributes: SearchAttributes_productType_availableAttributes_edges_node[]; attributes: SearchAttributes_productType_availableAttributes_edges_node[];
selected: string[]; selected: string[];
@ -188,7 +190,7 @@ const AssignAttributeDialog: React.FC<AssignAttributeDialogProps> = ({
<DialogContent> <DialogContent>
{errors.map((error, errorIndex) => ( {errors.map((error, errorIndex) => (
<DialogContentText color="error" key={errorIndex}> <DialogContentText color="error" key={errorIndex}>
{error} {getProductErrorMessage(error, intl)}
</DialogContentText> </DialogContentText>
))} ))}
</DialogContent> </DialogContent>

View file

@ -1,112 +0,0 @@
import Button from "@material-ui/core/Button";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogTitle from "@material-ui/core/DialogTitle";
import TextField from "@material-ui/core/TextField";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import Form from "@saleor/components/Form";
import { FormSpacer } from "@saleor/components/FormSpacer";
import ListField from "@saleor/components/ListField";
import { buttonMessages } from "@saleor/intl";
import { UserError } from "@saleor/types";
import { getFieldError } from "@saleor/utils/errors";
export interface FormData {
name: string;
values: Array<{
label: string;
value: string;
}>;
}
export interface ProductTypeAttributeEditDialogProps {
disabled: boolean;
errors: UserError[];
name: string;
opened: boolean;
title: string;
values: Array<{
label: string;
value: string;
}>;
onClose: () => void;
onConfirm: (data: FormData) => void;
}
const ProductTypeAttributeEditDialog: React.FC<ProductTypeAttributeEditDialogProps> = ({
disabled,
errors,
name,
opened,
title,
values,
onClose,
onConfirm
}) => {
const intl = useIntl();
const initialForm: FormData = {
name: name || "",
values: values || []
};
return (
<Dialog onClose={onClose} open={opened}>
<Form initial={initialForm} onSubmit={onConfirm}>
{({ change, data }) => (
<>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<TextField
disabled={disabled}
error={!!getFieldError(errors, "name")}
fullWidth
label={intl.formatMessage({
defaultMessage: "Attribute name"
})}
helperText={getFieldError(errors, "name")?.message}
name="name"
value={data.name}
onChange={change}
/>
<FormSpacer />
<ListField
autoComplete="off"
disabled={disabled}
error={
!!getFieldError(errors, "values") ||
!!getFieldError(errors, "addValues") ||
!!getFieldError(errors, "removeValues")
}
fullWidth
name="values"
label={intl.formatMessage({
defaultMessage: "Attribute values"
})}
helperText={
getFieldError(errors, "values") ||
getFieldError(errors, "addValues") ||
getFieldError(errors, "removeValues")
}
values={data.values}
onChange={change}
/>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>
<FormattedMessage {...buttonMessages.back} />
</Button>
<Button color="primary" variant="contained" type="submit">
<FormattedMessage {...buttonMessages.confirm} />
</Button>
</DialogActions>
</>
)}
</Form>
</Dialog>
);
};
ProductTypeAttributeEditDialog.displayName = "ProductTypeAttributeEditDialog";
export default ProductTypeAttributeEditDialog;

View file

@ -1,2 +0,0 @@
export { default } from "./ProductTypeAttributeEditDialog";
export * from "./ProductTypeAttributeEditDialog";

View file

@ -13,8 +13,8 @@ import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { ProductTypeDetails_taxTypes } from "@saleor/productTypes/types/ProductTypeDetails"; import { ProductTypeDetails_taxTypes } from "@saleor/productTypes/types/ProductTypeDetails";
import { UserError } from "@saleor/types";
import { WeightUnitsEnum } from "@saleor/types/globalTypes"; import { WeightUnitsEnum } from "@saleor/types/globalTypes";
import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
import ProductTypeDetails from "../ProductTypeDetails/ProductTypeDetails"; import ProductTypeDetails from "../ProductTypeDetails/ProductTypeDetails";
import ProductTypeShipping from "../ProductTypeShipping/ProductTypeShipping"; import ProductTypeShipping from "../ProductTypeShipping/ProductTypeShipping";
import ProductTypeTaxes from "../ProductTypeTaxes/ProductTypeTaxes"; import ProductTypeTaxes from "../ProductTypeTaxes/ProductTypeTaxes";
@ -27,7 +27,7 @@ export interface ProductTypeForm {
} }
export interface ProductTypeCreatePageProps { export interface ProductTypeCreatePageProps {
errors: UserError[]; errors: ProductErrorFragment[];
defaultWeightUnit: WeightUnitsEnum; defaultWeightUnit: WeightUnitsEnum;
disabled: boolean; disabled: boolean;
pageTitle: string; pageTitle: string;
@ -106,6 +106,7 @@ const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
disabled={disabled} disabled={disabled}
data={data} data={data}
defaultWeightUnit={defaultWeightUnit} defaultWeightUnit={defaultWeightUnit}
errors={errors}
onChange={change} onChange={change}
/> />
</div> </div>

View file

@ -7,8 +7,8 @@ import { useIntl } from "react-intl";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import { UserError } from "@saleor/types"; import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
import { getFieldError } from "@saleor/utils/errors"; import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors";
const useStyles = makeStyles( const useStyles = makeStyles(
{ {
@ -24,16 +24,18 @@ interface ProductTypeDetailsProps {
name: string; name: string;
}; };
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: ProductErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
} }
const ProductTypeDetails: React.FC<ProductTypeDetailsProps> = props => { const ProductTypeDetails: React.FC<ProductTypeDetailsProps> = props => {
const { data, disabled, errors, onChange } = props; const { data, disabled, errors, onChange } = props;
const classes = useStyles(props);
const classes = useStyles(props);
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["name"], errors);
return ( return (
<Card className={classes.root}> <Card className={classes.root}>
<CardTitle <CardTitle
@ -42,9 +44,9 @@ const ProductTypeDetails: React.FC<ProductTypeDetailsProps> = props => {
<CardContent> <CardContent>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "name")} error={!!formErrors.name}
fullWidth fullWidth
helperText={getFieldError(errors, "name")?.message} helperText={getProductErrorMessage(formErrors.name, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Product Type Name" defaultMessage: "Product Type Name"
})} })}

View file

@ -14,8 +14,9 @@ import { ChangeEvent, FormChange } from "@saleor/hooks/useForm";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { ListActions, ReorderEvent, UserError } from "@saleor/types"; import { ListActions, ReorderEvent } from "@saleor/types";
import { AttributeTypeEnum, WeightUnitsEnum } from "@saleor/types/globalTypes"; import { AttributeTypeEnum, WeightUnitsEnum } from "@saleor/types/globalTypes";
import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
import { import {
ProductTypeDetails_productType, ProductTypeDetails_productType,
ProductTypeDetails_taxTypes ProductTypeDetails_taxTypes
@ -41,7 +42,7 @@ export interface ProductTypeForm {
} }
export interface ProductTypeDetailsPageProps { export interface ProductTypeDetailsPageProps {
errors: UserError[]; errors: ProductErrorFragment[];
productType: ProductTypeDetails_productType; productType: ProductTypeDetails_productType;
defaultWeightUnit: WeightUnitsEnum; defaultWeightUnit: WeightUnitsEnum;
disabled: boolean; disabled: boolean;
@ -200,6 +201,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
disabled={disabled} disabled={disabled}
data={data} data={data}
defaultWeightUnit={defaultWeightUnit} defaultWeightUnit={defaultWeightUnit}
errors={errors}
onChange={change} onChange={change}
/> />
</div> </div>

View file

@ -6,6 +6,8 @@ import { useIntl } from "react-intl";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors";
import { WeightUnitsEnum } from "../../../types/globalTypes"; import { WeightUnitsEnum } from "../../../types/globalTypes";
interface ProductTypeShippingProps { interface ProductTypeShippingProps {
@ -15,6 +17,7 @@ interface ProductTypeShippingProps {
}; };
defaultWeightUnit: WeightUnitsEnum; defaultWeightUnit: WeightUnitsEnum;
disabled: boolean; disabled: boolean;
errors: ProductErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void; onChange: (event: React.ChangeEvent<any>) => void;
} }
@ -22,10 +25,13 @@ const ProductTypeShipping: React.FC<ProductTypeShippingProps> = ({
data, data,
defaultWeightUnit, defaultWeightUnit,
disabled, disabled,
errors,
onChange onChange
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["weight"], errors);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -48,15 +54,19 @@ const ProductTypeShipping: React.FC<ProductTypeShippingProps> = ({
{data.isShippingRequired && ( {data.isShippingRequired && (
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!formErrors.weight}
InputProps={{ endAdornment: defaultWeightUnit }} InputProps={{ endAdornment: defaultWeightUnit }}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Weight" defaultMessage: "Weight"
})} })}
name="weight" name="weight"
helperText={intl.formatMessage({ helperText={
defaultMessage: getProductErrorMessage(formErrors.weight, intl) ||
"Used to calculate rates for shipping for products of this product type, when specific weight is not given" intl.formatMessage({
})} defaultMessage:
"Used to calculate rates for shipping for products of this product type, when specific weight is not given"
})
}
type="number" type="number"
value={data.weight} value={data.weight}
onChange={onChange} onChange={onChange}

View file

@ -1,5 +1,6 @@
import gql from "graphql-tag"; import gql from "graphql-tag";
import { productErrorFragment } from "@saleor/attributes/mutations";
import { TypedMutation } from "../mutations"; import { TypedMutation } from "../mutations";
import { productTypeDetailsFragment } from "./queries"; import { productTypeDetailsFragment } from "./queries";
import { import {
@ -32,11 +33,11 @@ import {
} from "./types/UnassignAttribute"; } from "./types/UnassignAttribute";
export const productTypeDeleteMutation = gql` export const productTypeDeleteMutation = gql`
${productErrorFragment}
mutation ProductTypeDelete($id: ID!) { mutation ProductTypeDelete($id: ID!) {
productTypeDelete(id: $id) { productTypeDelete(id: $id) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
productType { productType {
id id
@ -50,11 +51,11 @@ export const TypedProductTypeDeleteMutation = TypedMutation<
>(productTypeDeleteMutation); >(productTypeDeleteMutation);
export const productTypeBulkDeleteMutation = gql` export const productTypeBulkDeleteMutation = gql`
${productErrorFragment}
mutation ProductTypeBulkDelete($ids: [ID]!) { mutation ProductTypeBulkDelete($ids: [ID]!) {
productTypeBulkDelete(ids: $ids) { productTypeBulkDelete(ids: $ids) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
} }
} }
@ -65,12 +66,12 @@ export const TypedProductTypeBulkDeleteMutation = TypedMutation<
>(productTypeBulkDeleteMutation); >(productTypeBulkDeleteMutation);
export const productTypeUpdateMutation = gql` export const productTypeUpdateMutation = gql`
${productErrorFragment}
${productTypeDetailsFragment} ${productTypeDetailsFragment}
mutation ProductTypeUpdate($id: ID!, $input: ProductTypeInput!) { mutation ProductTypeUpdate($id: ID!, $input: ProductTypeInput!) {
productTypeUpdate(id: $id, input: $input) { productTypeUpdate(id: $id, input: $input) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
productType { productType {
...ProductTypeDetailsFragment ...ProductTypeDetailsFragment
@ -84,12 +85,12 @@ export const TypedProductTypeUpdateMutation = TypedMutation<
>(productTypeUpdateMutation); >(productTypeUpdateMutation);
export const assignAttributeMutation = gql` export const assignAttributeMutation = gql`
${productErrorFragment}
${productTypeDetailsFragment} ${productTypeDetailsFragment}
mutation AssignAttribute($id: ID!, $operations: [AttributeAssignInput!]!) { mutation AssignAttribute($id: ID!, $operations: [AttributeAssignInput!]!) {
attributeAssign(productTypeId: $id, operations: $operations) { attributeAssign(productTypeId: $id, operations: $operations) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
productType { productType {
...ProductTypeDetailsFragment ...ProductTypeDetailsFragment
@ -103,12 +104,12 @@ export const TypedAssignAttributeMutation = TypedMutation<
>(assignAttributeMutation); >(assignAttributeMutation);
export const unassignAttributeMutation = gql` export const unassignAttributeMutation = gql`
${productErrorFragment}
${productTypeDetailsFragment} ${productTypeDetailsFragment}
mutation UnassignAttribute($id: ID!, $ids: [ID]!) { mutation UnassignAttribute($id: ID!, $ids: [ID]!) {
attributeUnassign(productTypeId: $id, attributeIds: $ids) { attributeUnassign(productTypeId: $id, attributeIds: $ids) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
productType { productType {
...ProductTypeDetailsFragment ...ProductTypeDetailsFragment
@ -122,12 +123,12 @@ export const TypedUnassignAttributeMutation = TypedMutation<
>(unassignAttributeMutation); >(unassignAttributeMutation);
export const productTypeCreateMutation = gql` export const productTypeCreateMutation = gql`
${productErrorFragment}
${productTypeDetailsFragment} ${productTypeDetailsFragment}
mutation ProductTypeCreate($input: ProductTypeInput!) { mutation ProductTypeCreate($input: ProductTypeInput!) {
productTypeCreate(input: $input) { productTypeCreate(input: $input) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
productType { productType {
...ProductTypeDetailsFragment ...ProductTypeDetailsFragment
@ -141,6 +142,7 @@ export const TypedProductTypeCreateMutation = TypedMutation<
>(productTypeCreateMutation); >(productTypeCreateMutation);
const productTypeAttributeReorder = gql` const productTypeAttributeReorder = gql`
${productErrorFragment}
${productTypeDetailsFragment} ${productTypeDetailsFragment}
mutation ProductTypeAttributeReorder( mutation ProductTypeAttributeReorder(
$move: ReorderInput! $move: ReorderInput!
@ -152,9 +154,8 @@ const productTypeAttributeReorder = gql`
productTypeId: $productTypeId productTypeId: $productTypeId
type: $type type: $type
) { ) {
errors { errors: productErrors {
field ...ProductErrorFragment
message
} }
productType { productType {
...ProductTypeDetailsFragment ...ProductTypeDetailsFragment

View file

@ -2,16 +2,16 @@
/* 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 { AttributeAssignInput } from "./../../types/globalTypes"; import { AttributeAssignInput, ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: AssignAttribute // GraphQL mutation operation: AssignAttribute
// ==================================================== // ====================================================
export interface AssignAttribute_attributeAssign_errors { export interface AssignAttribute_attributeAssign_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface AssignAttribute_attributeAssign_productType_taxType { export interface AssignAttribute_attributeAssign_productType_taxType {

View file

@ -2,16 +2,16 @@
/* 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 { ReorderInput, AttributeTypeEnum } from "./../../types/globalTypes"; import { ReorderInput, AttributeTypeEnum, ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductTypeAttributeReorder // GraphQL mutation operation: ProductTypeAttributeReorder
// ==================================================== // ====================================================
export interface ProductTypeAttributeReorder_productTypeReorderAttributes_errors { export interface ProductTypeAttributeReorder_productTypeReorderAttributes_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_taxType { export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_taxType {

View file

@ -2,14 +2,16 @@
/* 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 { ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductTypeBulkDelete // GraphQL mutation operation: ProductTypeBulkDelete
// ==================================================== // ====================================================
export interface ProductTypeBulkDelete_productTypeBulkDelete_errors { export interface ProductTypeBulkDelete_productTypeBulkDelete_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface ProductTypeBulkDelete_productTypeBulkDelete { export interface ProductTypeBulkDelete_productTypeBulkDelete {

View file

@ -2,16 +2,16 @@
/* 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 { ProductTypeInput } from "./../../types/globalTypes"; import { ProductTypeInput, ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductTypeCreate // GraphQL mutation operation: ProductTypeCreate
// ==================================================== // ====================================================
export interface ProductTypeCreate_productTypeCreate_errors { export interface ProductTypeCreate_productTypeCreate_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface ProductTypeCreate_productTypeCreate_productType_taxType { export interface ProductTypeCreate_productTypeCreate_productType_taxType {

View file

@ -2,14 +2,16 @@
/* 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 { ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductTypeDelete // GraphQL mutation operation: ProductTypeDelete
// ==================================================== // ====================================================
export interface ProductTypeDelete_productTypeDelete_errors { export interface ProductTypeDelete_productTypeDelete_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface ProductTypeDelete_productTypeDelete_productType { export interface ProductTypeDelete_productTypeDelete_productType {

View file

@ -2,16 +2,16 @@
/* 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 { ProductTypeInput } from "./../../types/globalTypes"; import { ProductTypeInput, ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductTypeUpdate // GraphQL mutation operation: ProductTypeUpdate
// ==================================================== // ====================================================
export interface ProductTypeUpdate_productTypeUpdate_errors { export interface ProductTypeUpdate_productTypeUpdate_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface ProductTypeUpdate_productTypeUpdate_productType_taxType { export interface ProductTypeUpdate_productTypeUpdate_productType_taxType {

View file

@ -2,14 +2,16 @@
/* 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 { ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: UnassignAttribute // GraphQL mutation operation: UnassignAttribute
// ==================================================== // ====================================================
export interface UnassignAttribute_attributeUnassign_errors { export interface UnassignAttribute_attributeUnassign_errors {
__typename: "Error"; __typename: "ProductError";
code: ProductErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface UnassignAttribute_attributeUnassign_productType_taxType { export interface UnassignAttribute_attributeUnassign_productType_taxType {

View file

@ -57,10 +57,9 @@ export const ProductTypeCreate: React.FC = () => {
<ProductTypeCreatePage <ProductTypeCreatePage
defaultWeightUnit={maybe(() => data.shop.defaultWeightUnit)} defaultWeightUnit={maybe(() => data.shop.defaultWeightUnit)}
disabled={loading} disabled={loading}
errors={maybe( errors={
() => createProductTypeOpts.data.productTypeCreate.errors, createProductTypeOpts.data?.productTypeCreate.errors || []
[] }
)}
pageTitle={intl.formatMessage({ pageTitle={intl.formatMessage({
defaultMessage: "Create Product Type", defaultMessage: "Create Product Type",
description: "header", description: "header",

View file

@ -1,19 +1,19 @@
import React from "react"; import React from "react";
import { UserError } from "../../../types"; import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment";
interface ProductTypeUpdateErrorsState { interface ProductTypeUpdateErrorsState {
addAttributeErrors: UserError[]; addAttributeErrors: ProductErrorFragment[];
editAttributeErrors: UserError[]; editAttributeErrors: ProductErrorFragment[];
formErrors: UserError[]; formErrors: ProductErrorFragment[];
} }
interface ProductTypeUpdateErrorsProps { interface ProductTypeUpdateErrorsProps {
children: (props: { children: (props: {
errors: ProductTypeUpdateErrorsState; errors: ProductTypeUpdateErrorsState;
set: { set: {
addAttributeErrors: (errors: UserError[]) => void; addAttributeErrors: (errors: ProductErrorFragment[]) => void;
editAttributeErrors: (errors: UserError[]) => void; editAttributeErrors: (errors: ProductErrorFragment[]) => void;
formErrors: (errors: UserError[]) => void; formErrors: (errors: ProductErrorFragment[]) => void;
}; };
}) => React.ReactNode; }) => React.ReactNode;
} }
@ -32,11 +32,12 @@ export class ProductTypeUpdateErrors extends React.Component<
return this.props.children({ return this.props.children({
errors: this.state, errors: this.state,
set: { set: {
addAttributeErrors: (addAttributeErrors: UserError[]) => addAttributeErrors: (addAttributeErrors: ProductErrorFragment[]) =>
this.setState({ addAttributeErrors }), this.setState({ addAttributeErrors }),
editAttributeErrors: (editAttributeErrors: UserError[]) => editAttributeErrors: (editAttributeErrors: ProductErrorFragment[]) =>
this.setState({ editAttributeErrors }), this.setState({ editAttributeErrors }),
formErrors: (formErrors: UserError[]) => this.setState({ formErrors }) formErrors: (formErrors: ProductErrorFragment[]) =>
this.setState({ formErrors })
} }
}); });
} }

View file

@ -319,13 +319,10 @@ export const ProductTypeUpdate: React.FC<ProductTypeUpdateProps> = ({
) )
)} )}
confirmButtonState={assignAttribute.opts.status} confirmButtonState={assignAttribute.opts.status}
errors={maybe( errors={
() => assignAttribute.opts.data?.attributeAssign
assignAttribute.opts.data.attributeAssign.errors.map( .errors || []
err => err.message }
),
[]
)}
loading={result.loading} loading={result.loading}
onClose={closeModal} onClose={closeModal}
onSubmit={handleAssignAttribute} onSubmit={handleAssignAttribute}

View file

@ -6,7 +6,7 @@ import { fetchMoreProps } from "@saleor/fixtures";
import AssignAttributeDialog, { import AssignAttributeDialog, {
AssignAttributeDialogProps AssignAttributeDialogProps
} from "@saleor/productTypes/components/AssignAttributeDialog"; } from "@saleor/productTypes/components/AssignAttributeDialog";
import { formError } from "@saleor/storybook/misc"; import { ProductErrorCode } from "@saleor/types/globalTypes";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
const props: AssignAttributeDialogProps = { const props: AssignAttributeDialogProps = {
@ -30,5 +30,14 @@ storiesOf("Generics / Assign attributes dialog", module)
<AssignAttributeDialog {...props} attributes={undefined} loading={true} /> <AssignAttributeDialog {...props} attributes={undefined} loading={true} />
)) ))
.add("errors", () => ( .add("errors", () => (
<AssignAttributeDialog {...props} errors={[formError("").message]} /> <AssignAttributeDialog
{...props}
errors={[
{
__typename: "ProductError" as "ProductError",
code: ProductErrorCode.INVALID,
field: null
}
]}
/>
)); ));

View file

@ -1,38 +0,0 @@
import { storiesOf } from "@storybook/react";
import React from "react";
import { formError } from "@saleor/storybook/misc";
import ProductTypeAttributeEditDialog, {
ProductTypeAttributeEditDialogProps
} from "../../../productTypes/components/ProductTypeAttributeEditDialog";
import { attributes } from "../../../productTypes/fixtures";
import Decorator from "../../Decorator";
const attribute = attributes[0];
const props: ProductTypeAttributeEditDialogProps = {
disabled: false,
errors: [],
name: attribute.name,
onClose: () => undefined,
onConfirm: () => undefined,
opened: true,
title: "Add Attribute",
values: attribute.values.map(value => ({
label: value.name,
value: value.id
}))
};
storiesOf("Product types / Edit attribute", module)
.addDecorator(Decorator)
.add("default", () => <ProductTypeAttributeEditDialog {...props} />)
.add("loading", () => (
<ProductTypeAttributeEditDialog {...props} disabled={true} />
))
.add("form errors", () => (
<ProductTypeAttributeEditDialog
{...props}
errors={["name", "values"].map(field => formError(field))}
/>
));

View file

@ -2,12 +2,11 @@ import { Omit } from "@material-ui/core";
import { storiesOf } from "@storybook/react"; import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import { formError } from "@saleor/storybook/misc";
import ProductTypeCreatePage, { import ProductTypeCreatePage, {
ProductTypeCreatePageProps, ProductTypeCreatePageProps,
ProductTypeForm ProductTypeForm
} from "../../../productTypes/components/ProductTypeCreatePage"; } from "../../../productTypes/components/ProductTypeCreatePage";
import { WeightUnitsEnum } from "../../../types/globalTypes"; import { WeightUnitsEnum, ProductErrorCode } from "../../../types/globalTypes";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
const props: Omit<ProductTypeCreatePageProps, "classes"> = { const props: Omit<ProductTypeCreatePageProps, "classes"> = {
@ -30,6 +29,10 @@ storiesOf("Views / Product types / Create product type", module)
.add("form errors", () => ( .add("form errors", () => (
<ProductTypeCreatePage <ProductTypeCreatePage
{...props} {...props}
errors={(["name"] as Array<keyof ProductTypeForm>).map(formError)} errors={(["name"] as Array<keyof ProductTypeForm>).map(field => ({
__typename: "ProductError",
code: ProductErrorCode.INVALID,
field
}))}
/> />
)); ));

View file

@ -3,13 +3,12 @@ import { storiesOf } from "@storybook/react";
import React from "react"; import React from "react";
import { listActionsProps } from "@saleor/fixtures"; import { listActionsProps } from "@saleor/fixtures";
import { formError } from "@saleor/storybook/misc";
import ProductTypeDetailsPage, { import ProductTypeDetailsPage, {
ProductTypeDetailsPageProps, ProductTypeDetailsPageProps,
ProductTypeForm ProductTypeForm
} from "../../../productTypes/components/ProductTypeDetailsPage"; } from "../../../productTypes/components/ProductTypeDetailsPage";
import { productType } from "../../../productTypes/fixtures"; import { productType } from "../../../productTypes/fixtures";
import { WeightUnitsEnum } from "../../../types/globalTypes"; import { WeightUnitsEnum, ProductErrorCode } from "../../../types/globalTypes";
import Decorator from "../../Decorator"; import Decorator from "../../Decorator";
const props: Omit<ProductTypeDetailsPageProps, "classes"> = { const props: Omit<ProductTypeDetailsPageProps, "classes"> = {
@ -55,6 +54,12 @@ storiesOf("Views / Product types / Product type details", module)
.add("form errors", () => ( .add("form errors", () => (
<ProductTypeDetailsPage <ProductTypeDetailsPage
{...props} {...props}
errors={(["name"] as Array<keyof ProductTypeForm>).map(formError)} errors={(["name", "weight"] as Array<keyof ProductTypeForm>).map(
field => ({
__typename: "ProductError",
code: ProductErrorCode.INVALID,
field
})
)}
/> />
)); ));