Use error codes in product types section
This commit is contained in:
parent
2fd7893df5
commit
0f28c8f4f5
22 changed files with 122 additions and 236 deletions
|
@ -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>
|
||||||
|
|
|
@ -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;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export { default } from "./ProductTypeAttributeEditDialog";
|
|
||||||
export * from "./ProductTypeAttributeEditDialog";
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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 })
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
@ -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))}
|
|
||||||
/>
|
|
||||||
));
|
|
|
@ -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
|
||||||
|
}))}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
@ -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
|
||||||
|
})
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
Loading…
Reference in a new issue