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={
getProductErrorMessage(formErrors.weight, intl) ||
intl.formatMessage({
defaultMessage: defaultMessage:
"Used to calculate rates for shipping for products of this product type, when specific weight is not given" "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
})
)}
/> />
)); ));