From bf92214fc39b4aaf73f5c77aa13633a2d54f632b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20=C5=BBegle=C5=84?= Date: Wed, 11 Mar 2020 10:56:04 +0100 Subject: [PATCH] Revert "Use error formatting in product type section" --- .../AttributeDetails/AttributeDetails.tsx | 21 ++-- .../AttributePage/AttributePage.tsx | 5 +- .../AttributeProperties.tsx | 17 ++- .../AttributeValueEditDialog.tsx | 15 +-- src/attributes/errors.ts | 38 ------ src/attributes/mutations.ts | 67 +++++------ src/attributes/types/AttributeBulkDelete.ts | 6 +- src/attributes/types/AttributeCreate.ts | 16 +-- src/attributes/types/AttributeDelete.ts | 6 +- src/attributes/types/AttributeUpdate.ts | 16 +-- src/attributes/types/AttributeValueCreate.ts | 16 +-- src/attributes/types/AttributeValueDelete.ts | 16 +-- src/attributes/types/AttributeValueReorder.ts | 16 +-- src/attributes/types/AttributeValueUpdate.ts | 16 +-- src/attributes/types/ProductErrorFragment.ts | 15 --- .../views/AttributeCreate/AttributeCreate.tsx | 51 +++++--- .../AttributeDetails/AttributeDetails.tsx | 36 +++--- .../AssignAttributeDialog.tsx | 6 +- .../ProductTypeAttributeEditDialog.tsx | 112 ++++++++++++++++++ .../ProductTypeAttributeEditDialog/index.ts | 2 + .../ProductTypeCreatePage.tsx | 5 +- .../ProductTypeDetails/ProductTypeDetails.tsx | 14 +-- .../ProductTypeDetailsPage.tsx | 6 +- .../ProductTypeShipping.tsx | 18 +-- src/productTypes/mutations.ts | 43 ++++--- src/productTypes/types/AssignAttribute.ts | 6 +- .../types/ProductTypeAttributeReorder.ts | 6 +- .../types/ProductTypeBulkDelete.ts | 6 +- src/productTypes/types/ProductTypeCreate.ts | 6 +- src/productTypes/types/ProductTypeDelete.ts | 6 +- src/productTypes/types/ProductTypeUpdate.ts | 6 +- src/productTypes/types/UnassignAttribute.ts | 6 +- src/productTypes/views/ProductTypeCreate.tsx | 7 +- .../views/ProductTypeUpdate/errors.tsx | 21 ++-- .../views/ProductTypeUpdate/index.tsx | 11 +- .../__snapshots__/Stories.test.ts.snap | 10 +- .../stories/attributes/AttributePage.tsx | 24 +--- .../attributes/AttributeValueEditDialog.tsx | 17 +-- .../components/AssignAttributeDialog.tsx | 13 +- .../ProductTypeAttributeEditDialog.tsx | 38 ++++++ .../productTypes/ProductTypeCreatePage.tsx | 9 +- .../productTypes/ProductTypeDetailsPage.tsx | 11 +- src/types.ts | 2 +- src/utils/errors.ts | 11 ++ src/utils/errors/common.ts | 12 -- src/utils/errors/index.ts | 26 ---- src/utils/errors/product.ts | 50 -------- 47 files changed, 417 insertions(+), 466 deletions(-) delete mode 100644 src/attributes/errors.ts delete mode 100644 src/attributes/types/ProductErrorFragment.ts create mode 100644 src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx create mode 100644 src/productTypes/components/ProductTypeAttributeEditDialog/index.ts create mode 100644 src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx create mode 100644 src/utils/errors.ts delete mode 100644 src/utils/errors/common.ts delete mode 100644 src/utils/errors/index.ts delete mode 100644 src/utils/errors/product.ts diff --git a/src/attributes/components/AttributeDetails/AttributeDetails.tsx b/src/attributes/components/AttributeDetails/AttributeDetails.tsx index 26b3ea201..a0eb97cfe 100644 --- a/src/attributes/components/AttributeDetails/AttributeDetails.tsx +++ b/src/attributes/components/AttributeDetails/AttributeDetails.tsx @@ -10,17 +10,16 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import SingleSelectField from "@saleor/components/SingleSelectField"; import { commonMessages } from "@saleor/intl"; +import { UserError } from "@saleor/types"; import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; -import { getProductErrorMessage, getFormErrors } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { getFieldError } from "@saleor/utils/errors"; import { AttributePageFormData } from "../AttributePage"; -import { getAttributeSlugErrorMessage } from "../../errors"; export interface AttributeDetailsProps { canChangeType: boolean; data: AttributePageFormData; disabled: boolean; - errors: ProductErrorFragment[]; + errors: UserError[]; onChange: (event: React.ChangeEvent) => void; } @@ -49,8 +48,6 @@ const AttributeDetails: React.FC = ({ } ]; - const formErrors = getFormErrors(["name", "slug", "inputType"], errors); - return ( = ({ = ({ placeholder={slugify(data.name).toLowerCase()} fullWidth helperText={ - getAttributeSlugErrorMessage(formErrors.slug, intl) || + getFieldError(errors, "slug")?.message || intl.formatMessage({ defaultMessage: "This is used internally. Make sure you don’t use spaces", @@ -96,8 +93,8 @@ const AttributeDetails: React.FC = ({ void; diff --git a/src/attributes/components/AttributeProperties/AttributeProperties.tsx b/src/attributes/components/AttributeProperties/AttributeProperties.tsx index 1ad3fcd36..4e12f1d29 100644 --- a/src/attributes/components/AttributeProperties/AttributeProperties.tsx +++ b/src/attributes/components/AttributeProperties/AttributeProperties.tsx @@ -11,14 +11,14 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox"; import FormSpacer from "@saleor/components/FormSpacer"; import Hr from "@saleor/components/Hr"; import { commonMessages } from "@saleor/intl"; -import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { UserError } from "@saleor/types"; +import { getFieldError } from "@saleor/utils/errors"; import { AttributePageFormData } from "../AttributePage"; export interface AttributePropertiesProps { data: AttributePageFormData; disabled: boolean; - errors: ProductErrorFragment[]; + errors: UserError[]; onChange: (event: React.ChangeEvent) => void; } @@ -30,8 +30,6 @@ const AttributeProperties: React.FC = ({ }) => { const intl = useIntl(); - const formErrors = getFormErrors(["storefrontSearchPosition"], errors); - return ( @@ -88,12 +86,11 @@ const AttributeProperties: React.FC = ({ {data.filterableInStorefront && ( void; onClose: () => void; @@ -46,7 +45,6 @@ const AttributeValueEditDialog: React.FC = ({ name: maybe(() => attributeValue.name, "") }; const errors = useModalDialogErrors(apiErrors, open); - const formErrors = getFormErrors(["name"], errors); return ( @@ -70,12 +68,9 @@ const AttributeValueEditDialog: React.FC = ({ (attributeBulkDelete); const attributeDelete = gql` - ${productErrorFragment} mutation AttributeDelete($id: ID!) { attributeDelete(id: $id) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } } } @@ -74,15 +67,15 @@ export const AttributeDeleteMutation = TypedMutation< export const attributeUpdateMutation = gql` ${attributeDetailsFragment} - ${productErrorFragment} mutation AttributeUpdate($id: ID!, $input: AttributeUpdateInput!) { attributeUpdate(id: $id, input: $input) { + errors { + field + message + } attribute { ...AttributeDetailsFragment } - errors: productErrors { - ...ProductErrorFragment - } } } `; @@ -93,15 +86,15 @@ export const AttributeUpdateMutation = TypedMutation< const attributeValueDelete = gql` ${attributeDetailsFragment} - ${productErrorFragment} mutation AttributeValueDelete($id: ID!) { attributeValueDelete(id: $id) { + errors { + field + message + } attribute { ...AttributeDetailsFragment } - errors: productErrors { - ...ProductErrorFragment - } } } `; @@ -112,15 +105,15 @@ export const AttributeValueDeleteMutation = TypedMutation< export const attributeValueUpdateMutation = gql` ${attributeDetailsFragment} - ${productErrorFragment} mutation AttributeValueUpdate($id: ID!, $input: AttributeValueCreateInput!) { attributeValueUpdate(id: $id, input: $input) { + errors { + field + message + } attribute { ...AttributeDetailsFragment } - errors: productErrors { - ...ProductErrorFragment - } } } `; @@ -131,15 +124,15 @@ export const AttributeValueUpdateMutation = TypedMutation< export const attributeValueCreateMutation = gql` ${attributeDetailsFragment} - ${productErrorFragment} mutation AttributeValueCreate($id: ID!, $input: AttributeValueCreateInput!) { attributeValueCreate(attribute: $id, input: $input) { + errors { + field + message + } attribute { ...AttributeDetailsFragment } - errors: productErrors { - ...ProductErrorFragment - } } } `; @@ -150,15 +143,15 @@ export const AttributeValueCreateMutation = TypedMutation< export const attributeCreateMutation = gql` ${attributeDetailsFragment} - ${productErrorFragment} mutation AttributeCreate($input: AttributeCreateInput!) { attributeCreate(input: $input) { + errors { + field + message + } attribute { ...AttributeDetailsFragment } - errors: productErrors { - ...ProductErrorFragment - } } } `; @@ -168,18 +161,18 @@ export const AttributeCreateMutation = TypedMutation< >(attributeCreateMutation); const attributeValueReorderMutation = gql` - ${productErrorFragment} mutation AttributeValueReorder($id: ID!, $move: ReorderInput!) { attributeReorderValues(attributeId: $id, moves: [$move]) { + errors { + field + message + } attribute { id values { id } } - errors: productErrors { - ...ProductErrorFragment - } } } `; diff --git a/src/attributes/types/AttributeBulkDelete.ts b/src/attributes/types/AttributeBulkDelete.ts index 259901950..6d910e56c 100644 --- a/src/attributes/types/AttributeBulkDelete.ts +++ b/src/attributes/types/AttributeBulkDelete.ts @@ -2,16 +2,14 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; - // ==================================================== // GraphQL mutation operation: AttributeBulkDelete // ==================================================== export interface AttributeBulkDelete_attributeBulkDelete_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface AttributeBulkDelete_attributeBulkDelete { diff --git a/src/attributes/types/AttributeCreate.ts b/src/attributes/types/AttributeCreate.ts index 3c7db619b..5db772935 100644 --- a/src/attributes/types/AttributeCreate.ts +++ b/src/attributes/types/AttributeCreate.ts @@ -2,12 +2,18 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeCreateInput, AttributeInputTypeEnum, AttributeValueType, ProductErrorCode } from "./../../types/globalTypes"; +import { AttributeCreateInput, AttributeInputTypeEnum, AttributeValueType } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AttributeCreate // ==================================================== +export interface AttributeCreate_attributeCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + export interface AttributeCreate_attributeCreate_attribute_values { __typename: "AttributeValue"; id: string; @@ -31,16 +37,10 @@ export interface AttributeCreate_attributeCreate_attribute { values: (AttributeCreate_attributeCreate_attribute_values | null)[] | null; } -export interface AttributeCreate_attributeCreate_errors { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} - export interface AttributeCreate_attributeCreate { __typename: "AttributeCreate"; - attribute: AttributeCreate_attributeCreate_attribute | null; errors: AttributeCreate_attributeCreate_errors[]; + attribute: AttributeCreate_attributeCreate_attribute | null; } export interface AttributeCreate { diff --git a/src/attributes/types/AttributeDelete.ts b/src/attributes/types/AttributeDelete.ts index a0273fdac..e2cd94ff7 100644 --- a/src/attributes/types/AttributeDelete.ts +++ b/src/attributes/types/AttributeDelete.ts @@ -2,16 +2,14 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; - // ==================================================== // GraphQL mutation operation: AttributeDelete // ==================================================== export interface AttributeDelete_attributeDelete_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface AttributeDelete_attributeDelete { diff --git a/src/attributes/types/AttributeUpdate.ts b/src/attributes/types/AttributeUpdate.ts index 51dedb082..3529454ca 100644 --- a/src/attributes/types/AttributeUpdate.ts +++ b/src/attributes/types/AttributeUpdate.ts @@ -2,12 +2,18 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeUpdateInput, AttributeInputTypeEnum, AttributeValueType, ProductErrorCode } from "./../../types/globalTypes"; +import { AttributeUpdateInput, AttributeInputTypeEnum, AttributeValueType } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AttributeUpdate // ==================================================== +export interface AttributeUpdate_attributeUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + export interface AttributeUpdate_attributeUpdate_attribute_values { __typename: "AttributeValue"; id: string; @@ -31,16 +37,10 @@ export interface AttributeUpdate_attributeUpdate_attribute { values: (AttributeUpdate_attributeUpdate_attribute_values | null)[] | null; } -export interface AttributeUpdate_attributeUpdate_errors { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} - export interface AttributeUpdate_attributeUpdate { __typename: "AttributeUpdate"; - attribute: AttributeUpdate_attributeUpdate_attribute | null; errors: AttributeUpdate_attributeUpdate_errors[]; + attribute: AttributeUpdate_attributeUpdate_attribute | null; } export interface AttributeUpdate { diff --git a/src/attributes/types/AttributeValueCreate.ts b/src/attributes/types/AttributeValueCreate.ts index 9f02505d2..c11325fb3 100644 --- a/src/attributes/types/AttributeValueCreate.ts +++ b/src/attributes/types/AttributeValueCreate.ts @@ -2,12 +2,18 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeValueCreateInput, AttributeInputTypeEnum, AttributeValueType, ProductErrorCode } from "./../../types/globalTypes"; +import { AttributeValueCreateInput, AttributeInputTypeEnum, AttributeValueType } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AttributeValueCreate // ==================================================== +export interface AttributeValueCreate_attributeValueCreate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + export interface AttributeValueCreate_attributeValueCreate_attribute_values { __typename: "AttributeValue"; id: string; @@ -31,16 +37,10 @@ export interface AttributeValueCreate_attributeValueCreate_attribute { values: (AttributeValueCreate_attributeValueCreate_attribute_values | null)[] | null; } -export interface AttributeValueCreate_attributeValueCreate_errors { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} - export interface AttributeValueCreate_attributeValueCreate { __typename: "AttributeValueCreate"; - attribute: AttributeValueCreate_attributeValueCreate_attribute | null; errors: AttributeValueCreate_attributeValueCreate_errors[]; + attribute: AttributeValueCreate_attributeValueCreate_attribute | null; } export interface AttributeValueCreate { diff --git a/src/attributes/types/AttributeValueDelete.ts b/src/attributes/types/AttributeValueDelete.ts index 978e938b3..8737ed336 100644 --- a/src/attributes/types/AttributeValueDelete.ts +++ b/src/attributes/types/AttributeValueDelete.ts @@ -2,12 +2,18 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeInputTypeEnum, AttributeValueType, ProductErrorCode } from "./../../types/globalTypes"; +import { AttributeInputTypeEnum, AttributeValueType } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AttributeValueDelete // ==================================================== +export interface AttributeValueDelete_attributeValueDelete_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + export interface AttributeValueDelete_attributeValueDelete_attribute_values { __typename: "AttributeValue"; id: string; @@ -31,16 +37,10 @@ export interface AttributeValueDelete_attributeValueDelete_attribute { values: (AttributeValueDelete_attributeValueDelete_attribute_values | null)[] | null; } -export interface AttributeValueDelete_attributeValueDelete_errors { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} - export interface AttributeValueDelete_attributeValueDelete { __typename: "AttributeValueDelete"; - attribute: AttributeValueDelete_attributeValueDelete_attribute | null; errors: AttributeValueDelete_attributeValueDelete_errors[]; + attribute: AttributeValueDelete_attributeValueDelete_attribute | null; } export interface AttributeValueDelete { diff --git a/src/attributes/types/AttributeValueReorder.ts b/src/attributes/types/AttributeValueReorder.ts index e33438c50..31a50ba08 100644 --- a/src/attributes/types/AttributeValueReorder.ts +++ b/src/attributes/types/AttributeValueReorder.ts @@ -2,12 +2,18 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ReorderInput, ProductErrorCode } from "./../../types/globalTypes"; +import { ReorderInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AttributeValueReorder // ==================================================== +export interface AttributeValueReorder_attributeReorderValues_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + export interface AttributeValueReorder_attributeReorderValues_attribute_values { __typename: "AttributeValue"; id: string; @@ -19,16 +25,10 @@ export interface AttributeValueReorder_attributeReorderValues_attribute { values: (AttributeValueReorder_attributeReorderValues_attribute_values | null)[] | null; } -export interface AttributeValueReorder_attributeReorderValues_errors { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} - export interface AttributeValueReorder_attributeReorderValues { __typename: "AttributeReorderValues"; - attribute: AttributeValueReorder_attributeReorderValues_attribute | null; errors: AttributeValueReorder_attributeReorderValues_errors[]; + attribute: AttributeValueReorder_attributeReorderValues_attribute | null; } export interface AttributeValueReorder { diff --git a/src/attributes/types/AttributeValueUpdate.ts b/src/attributes/types/AttributeValueUpdate.ts index 564f7a691..90bd6561d 100644 --- a/src/attributes/types/AttributeValueUpdate.ts +++ b/src/attributes/types/AttributeValueUpdate.ts @@ -2,12 +2,18 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeValueCreateInput, AttributeInputTypeEnum, AttributeValueType, ProductErrorCode } from "./../../types/globalTypes"; +import { AttributeValueCreateInput, AttributeInputTypeEnum, AttributeValueType } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AttributeValueUpdate // ==================================================== +export interface AttributeValueUpdate_attributeValueUpdate_errors { + __typename: "Error"; + field: string | null; + message: string | null; +} + export interface AttributeValueUpdate_attributeValueUpdate_attribute_values { __typename: "AttributeValue"; id: string; @@ -31,16 +37,10 @@ export interface AttributeValueUpdate_attributeValueUpdate_attribute { values: (AttributeValueUpdate_attributeValueUpdate_attribute_values | null)[] | null; } -export interface AttributeValueUpdate_attributeValueUpdate_errors { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} - export interface AttributeValueUpdate_attributeValueUpdate { __typename: "AttributeValueUpdate"; - attribute: AttributeValueUpdate_attributeValueUpdate_attribute | null; errors: AttributeValueUpdate_attributeValueUpdate_errors[]; + attribute: AttributeValueUpdate_attributeValueUpdate_attribute | null; } export interface AttributeValueUpdate { diff --git a/src/attributes/types/ProductErrorFragment.ts b/src/attributes/types/ProductErrorFragment.ts deleted file mode 100644 index 2f4d1fccb..000000000 --- a/src/attributes/types/ProductErrorFragment.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ProductErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL fragment: ProductErrorFragment -// ==================================================== - -export interface ProductErrorFragment { - __typename: "ProductError"; - code: ProductErrorCode; - field: string | null; -} diff --git a/src/attributes/views/AttributeCreate/AttributeCreate.tsx b/src/attributes/views/AttributeCreate/AttributeCreate.tsx index 7ece9730e..cf700c858 100644 --- a/src/attributes/views/AttributeCreate/AttributeCreate.tsx +++ b/src/attributes/views/AttributeCreate/AttributeCreate.tsx @@ -5,7 +5,7 @@ import slugify from "slugify"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import { maybe } from "@saleor/misc"; -import { ReorderEvent } from "@saleor/types"; +import { ReorderEvent, UserError } from "@saleor/types"; import { add, isSelected, @@ -14,8 +14,6 @@ import { updateAtIndex } from "@saleor/utils/lists"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { ProductErrorCode } from "@saleor/types/globalTypes"; import AttributePage from "../../components/AttributePage"; import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog"; import AttributeValueEditDialog, { @@ -35,12 +33,6 @@ interface AttributeDetailsProps { params: AttributeAddUrlQueryParams; } -const attributeValueAlreadyExistsError: ProductErrorFragment = { - __typename: "ProductError", - code: ProductErrorCode.ALREADY_EXISTS, - field: "name" -}; - function areValuesEqual( a: AttributeValueEditDialogFormData, b: AttributeValueEditDialogFormData @@ -56,9 +48,7 @@ const AttributeDetails: React.FC = ({ params }) => { const [values, setValues] = React.useState< AttributeValueEditDialogFormData[] >([]); - const [valueErrors, setValueErrors] = React.useState( - [] - ); + const [valueErrors, setValueErrors] = React.useState([]); const id = params.id ? parseInt(params.id, 0) : undefined; @@ -67,8 +57,6 @@ const AttributeDetails: React.FC = ({ params }) => { AttributeAddUrlQueryParams >(navigate, attributeAddUrl, params); - React.useEffect(() => setValueErrors([]), [params.action]); - const handleValueDelete = () => { setValues(remove(values[params.id], values, areValuesEqual)); closeModal(); @@ -85,7 +73,20 @@ const AttributeDetails: React.FC = ({ params }) => { }; const handleValueUpdate = (input: AttributeValueEditDialogFormData) => { if (isSelected(input, values, areValuesEqual)) { - setValueErrors([attributeValueAlreadyExistsError]); + setValueErrors([ + { + field: "name", + message: intl.formatMessage( + { + defaultMessage: "A value named {name} already exists", + description: "attribute value edit error" + }, + { + name: input.name + } + ) + } + ]); } else { setValues(updateAtIndex(input, values, id)); closeModal(); @@ -93,7 +94,20 @@ const AttributeDetails: React.FC = ({ params }) => { }; const handleValueCreate = (input: AttributeValueEditDialogFormData) => { if (isSelected(input, values, areValuesEqual)) { - setValueErrors([attributeValueAlreadyExistsError]); + setValueErrors([ + { + field: "name", + message: intl.formatMessage( + { + defaultMessage: "A value named {name} already exists", + description: "attribute value edit error" + }, + { + name: input.name + } + ) + } + ]); } else { setValues(add(input, values)); closeModal(); @@ -109,7 +123,10 @@ const AttributeDetails: React.FC = ({ params }) => { attributeCreateOpts.data.attributeCreate.errors, + [] + )} onBack={() => navigate(attributeListUrl())} onDelete={undefined} onSubmit={input => diff --git a/src/attributes/views/AttributeDetails/AttributeDetails.tsx b/src/attributes/views/AttributeDetails/AttributeDetails.tsx index 2c00bb10d..3dcc9c8a4 100644 --- a/src/attributes/views/AttributeDetails/AttributeDetails.tsx +++ b/src/attributes/views/AttributeDetails/AttributeDetails.tsx @@ -8,7 +8,6 @@ import { maybe } from "@saleor/misc"; import { ReorderEvent } from "@saleor/types"; import { move } from "@saleor/utils/lists"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import { getProductErrorMessage } from "@saleor/utils/errors"; import AttributeDeleteDialog from "../../components/AttributeDeleteDialog"; import AttributePage from "../../components/AttributePage"; import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog"; @@ -96,10 +95,7 @@ const AttributeDetails: React.FC = ({ id, params }) => { const handleValueReorderMutation = (data: AttributeValueReorder) => { if (data.attributeReorderValues.errors.length !== 0) { notify({ - text: getProductErrorMessage( - data.attributeReorderValues.errors[0], - intl - ) + text: data.attributeReorderValues.errors[0].message }); } }; @@ -159,10 +155,12 @@ const AttributeDetails: React.FC = ({ id, params }) => { data.attribute)} disabled={loading} - errors={ - attributeUpdateOpts.data - ?.attributeUpdate.errors || [] - } + errors={maybe( + () => + attributeUpdateOpts.data + .attributeUpdate.errors, + [] + )} onBack={() => navigate(attributeListUrl()) } @@ -255,10 +253,12 @@ const AttributeDetails: React.FC = ({ id, params }) => { attributeValueCreateOpts.status } disabled={loading} - errors={ - attributeValueCreateOpts.data - ?.attributeValueCreate.errors || [] - } + errors={maybe( + () => + attributeValueCreateOpts.data + .attributeValueCreate.errors, + [] + )} open={params.action === "add-value"} onClose={closeModal} onSubmit={input => @@ -280,10 +280,12 @@ const AttributeDetails: React.FC = ({ id, params }) => { attributeValueUpdateOpts.status } disabled={loading} - errors={ - attributeValueUpdateOpts.data - ?.attributeValueUpdate.errors || [] - } + errors={maybe( + () => + attributeValueUpdateOpts.data + .attributeValueUpdate.errors, + [] + )} open={params.action === "edit-value"} onClose={closeModal} onSubmit={input => diff --git a/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx b/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx index 6398d6d84..96f392455 100644 --- a/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx +++ b/src/productTypes/components/AssignAttributeDialog/AssignAttributeDialog.tsx @@ -30,8 +30,6 @@ import useSearchQuery from "@saleor/hooks/useSearchQuery"; import { buttonMessages } from "@saleor/intl"; import { maybe, renderCollection } from "@saleor/misc"; 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"; const useStyles = makeStyles( @@ -63,7 +61,7 @@ const useStyles = makeStyles( export interface AssignAttributeDialogProps extends FetchMoreProps { confirmButtonState: ConfirmButtonTransitionState; - errors: ProductErrorFragment[]; + errors: string[]; open: boolean; attributes: SearchAttributes_productType_availableAttributes_edges_node[]; selected: string[]; @@ -190,7 +188,7 @@ const AssignAttributeDialog: React.FC = ({ {errors.map((error, errorIndex) => ( - {getProductErrorMessage(error, intl)} + {error} ))} diff --git a/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx b/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx new file mode 100644 index 000000000..6a444d2f8 --- /dev/null +++ b/src/productTypes/components/ProductTypeAttributeEditDialog/ProductTypeAttributeEditDialog.tsx @@ -0,0 +1,112 @@ +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 = ({ + disabled, + errors, + name, + opened, + title, + values, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + const initialForm: FormData = { + name: name || "", + values: values || [] + }; + return ( + +
+ {({ change, data }) => ( + <> + {title} + + + + + + + + + + + )} +
+
+ ); +}; +ProductTypeAttributeEditDialog.displayName = "ProductTypeAttributeEditDialog"; +export default ProductTypeAttributeEditDialog; diff --git a/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts b/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts new file mode 100644 index 000000000..6344b380f --- /dev/null +++ b/src/productTypes/components/ProductTypeAttributeEditDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./ProductTypeAttributeEditDialog"; +export * from "./ProductTypeAttributeEditDialog"; diff --git a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx index 9d9220f29..6616baebd 100644 --- a/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx +++ b/src/productTypes/components/ProductTypeCreatePage/ProductTypeCreatePage.tsx @@ -13,8 +13,8 @@ import { ChangeEvent, FormChange } from "@saleor/hooks/useForm"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import { sectionNames } from "@saleor/intl"; import { ProductTypeDetails_taxTypes } from "@saleor/productTypes/types/ProductTypeDetails"; +import { UserError } from "@saleor/types"; import { WeightUnitsEnum } from "@saleor/types/globalTypes"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; import ProductTypeDetails from "../ProductTypeDetails/ProductTypeDetails"; import ProductTypeShipping from "../ProductTypeShipping/ProductTypeShipping"; import ProductTypeTaxes from "../ProductTypeTaxes/ProductTypeTaxes"; @@ -27,7 +27,7 @@ export interface ProductTypeForm { } export interface ProductTypeCreatePageProps { - errors: ProductErrorFragment[]; + errors: UserError[]; defaultWeightUnit: WeightUnitsEnum; disabled: boolean; pageTitle: string; @@ -106,7 +106,6 @@ const ProductTypeCreatePage: React.FC = ({ disabled={disabled} data={data} defaultWeightUnit={defaultWeightUnit} - errors={errors} onChange={change} /> diff --git a/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx b/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx index 515e8f2de..758fd36e6 100644 --- a/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx +++ b/src/productTypes/components/ProductTypeDetails/ProductTypeDetails.tsx @@ -7,8 +7,8 @@ import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; import { commonMessages } from "@saleor/intl"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { getFormErrors, getProductErrorMessage } from "@saleor/utils/errors"; +import { UserError } from "@saleor/types"; +import { getFieldError } from "@saleor/utils/errors"; const useStyles = makeStyles( { @@ -24,17 +24,15 @@ interface ProductTypeDetailsProps { name: string; }; disabled: boolean; - errors: ProductErrorFragment[]; + errors: UserError[]; onChange: (event: React.ChangeEvent) => void; } const ProductTypeDetails: React.FC = props => { const { data, disabled, errors, onChange } = props; - const classes = useStyles(props); - const intl = useIntl(); - const formErrors = getFormErrors(["name"], errors); + const intl = useIntl(); return ( @@ -44,9 +42,9 @@ const ProductTypeDetails: React.FC = props => { = ({ disabled={disabled} data={data} defaultWeightUnit={defaultWeightUnit} - errors={errors} onChange={change} /> diff --git a/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx b/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx index 0e5ea818e..afb146aca 100644 --- a/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx +++ b/src/productTypes/components/ProductTypeShipping/ProductTypeShipping.tsx @@ -6,8 +6,6 @@ import { useIntl } from "react-intl"; import CardTitle from "@saleor/components/CardTitle"; 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"; interface ProductTypeShippingProps { @@ -17,7 +15,6 @@ interface ProductTypeShippingProps { }; defaultWeightUnit: WeightUnitsEnum; disabled: boolean; - errors: ProductErrorFragment[]; onChange: (event: React.ChangeEvent) => void; } @@ -25,13 +22,10 @@ const ProductTypeShipping: React.FC = ({ data, defaultWeightUnit, disabled, - errors, onChange }) => { const intl = useIntl(); - const formErrors = getFormErrors(["weight"], errors); - return ( = ({ {data.isShippingRequired && ( (productTypeDeleteMutation); export const productTypeBulkDeleteMutation = gql` - ${productErrorFragment} mutation ProductTypeBulkDelete($ids: [ID]!) { productTypeBulkDelete(ids: $ids) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } } } @@ -66,12 +65,12 @@ export const TypedProductTypeBulkDeleteMutation = TypedMutation< >(productTypeBulkDeleteMutation); export const productTypeUpdateMutation = gql` - ${productErrorFragment} ${productTypeDetailsFragment} mutation ProductTypeUpdate($id: ID!, $input: ProductTypeInput!) { productTypeUpdate(id: $id, input: $input) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } productType { ...ProductTypeDetailsFragment @@ -85,12 +84,12 @@ export const TypedProductTypeUpdateMutation = TypedMutation< >(productTypeUpdateMutation); export const assignAttributeMutation = gql` - ${productErrorFragment} ${productTypeDetailsFragment} mutation AssignAttribute($id: ID!, $operations: [AttributeAssignInput!]!) { attributeAssign(productTypeId: $id, operations: $operations) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } productType { ...ProductTypeDetailsFragment @@ -104,12 +103,12 @@ export const TypedAssignAttributeMutation = TypedMutation< >(assignAttributeMutation); export const unassignAttributeMutation = gql` - ${productErrorFragment} ${productTypeDetailsFragment} mutation UnassignAttribute($id: ID!, $ids: [ID]!) { attributeUnassign(productTypeId: $id, attributeIds: $ids) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } productType { ...ProductTypeDetailsFragment @@ -123,12 +122,12 @@ export const TypedUnassignAttributeMutation = TypedMutation< >(unassignAttributeMutation); export const productTypeCreateMutation = gql` - ${productErrorFragment} ${productTypeDetailsFragment} mutation ProductTypeCreate($input: ProductTypeInput!) { productTypeCreate(input: $input) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } productType { ...ProductTypeDetailsFragment @@ -142,7 +141,6 @@ export const TypedProductTypeCreateMutation = TypedMutation< >(productTypeCreateMutation); const productTypeAttributeReorder = gql` - ${productErrorFragment} ${productTypeDetailsFragment} mutation ProductTypeAttributeReorder( $move: ReorderInput! @@ -154,8 +152,9 @@ const productTypeAttributeReorder = gql` productTypeId: $productTypeId type: $type ) { - errors: productErrors { - ...ProductErrorFragment + errors { + field + message } productType { ...ProductTypeDetailsFragment diff --git a/src/productTypes/types/AssignAttribute.ts b/src/productTypes/types/AssignAttribute.ts index 2f24d922a..2e9d3fb4a 100644 --- a/src/productTypes/types/AssignAttribute.ts +++ b/src/productTypes/types/AssignAttribute.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { AttributeAssignInput, ProductErrorCode } from "./../../types/globalTypes"; +import { AttributeAssignInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: AssignAttribute // ==================================================== export interface AssignAttribute_attributeAssign_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface AssignAttribute_attributeAssign_productType_taxType { diff --git a/src/productTypes/types/ProductTypeAttributeReorder.ts b/src/productTypes/types/ProductTypeAttributeReorder.ts index 7d765230d..6d4ca443d 100644 --- a/src/productTypes/types/ProductTypeAttributeReorder.ts +++ b/src/productTypes/types/ProductTypeAttributeReorder.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ReorderInput, AttributeTypeEnum, ProductErrorCode } from "./../../types/globalTypes"; +import { ReorderInput, AttributeTypeEnum } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductTypeAttributeReorder // ==================================================== export interface ProductTypeAttributeReorder_productTypeReorderAttributes_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface ProductTypeAttributeReorder_productTypeReorderAttributes_productType_taxType { diff --git a/src/productTypes/types/ProductTypeBulkDelete.ts b/src/productTypes/types/ProductTypeBulkDelete.ts index 7727f11a3..034d3e909 100644 --- a/src/productTypes/types/ProductTypeBulkDelete.ts +++ b/src/productTypes/types/ProductTypeBulkDelete.ts @@ -2,16 +2,14 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; - // ==================================================== // GraphQL mutation operation: ProductTypeBulkDelete // ==================================================== export interface ProductTypeBulkDelete_productTypeBulkDelete_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface ProductTypeBulkDelete_productTypeBulkDelete { diff --git a/src/productTypes/types/ProductTypeCreate.ts b/src/productTypes/types/ProductTypeCreate.ts index d95f672f1..5993bbb02 100644 --- a/src/productTypes/types/ProductTypeCreate.ts +++ b/src/productTypes/types/ProductTypeCreate.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductTypeInput, ProductErrorCode } from "./../../types/globalTypes"; +import { ProductTypeInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductTypeCreate // ==================================================== export interface ProductTypeCreate_productTypeCreate_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface ProductTypeCreate_productTypeCreate_productType_taxType { diff --git a/src/productTypes/types/ProductTypeDelete.ts b/src/productTypes/types/ProductTypeDelete.ts index b3e87d735..ea5c2a1b0 100644 --- a/src/productTypes/types/ProductTypeDelete.ts +++ b/src/productTypes/types/ProductTypeDelete.ts @@ -2,16 +2,14 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; - // ==================================================== // GraphQL mutation operation: ProductTypeDelete // ==================================================== export interface ProductTypeDelete_productTypeDelete_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface ProductTypeDelete_productTypeDelete_productType { diff --git a/src/productTypes/types/ProductTypeUpdate.ts b/src/productTypes/types/ProductTypeUpdate.ts index bd1156234..58c66afe2 100644 --- a/src/productTypes/types/ProductTypeUpdate.ts +++ b/src/productTypes/types/ProductTypeUpdate.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductTypeInput, ProductErrorCode } from "./../../types/globalTypes"; +import { ProductTypeInput } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: ProductTypeUpdate // ==================================================== export interface ProductTypeUpdate_productTypeUpdate_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface ProductTypeUpdate_productTypeUpdate_productType_taxType { diff --git a/src/productTypes/types/UnassignAttribute.ts b/src/productTypes/types/UnassignAttribute.ts index 631052cbe..b042fc6e3 100644 --- a/src/productTypes/types/UnassignAttribute.ts +++ b/src/productTypes/types/UnassignAttribute.ts @@ -2,16 +2,14 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { ProductErrorCode } from "./../../types/globalTypes"; - // ==================================================== // GraphQL mutation operation: UnassignAttribute // ==================================================== export interface UnassignAttribute_attributeUnassign_errors { - __typename: "ProductError"; - code: ProductErrorCode; + __typename: "Error"; field: string | null; + message: string | null; } export interface UnassignAttribute_attributeUnassign_productType_taxType { diff --git a/src/productTypes/views/ProductTypeCreate.tsx b/src/productTypes/views/ProductTypeCreate.tsx index 3355ac13f..f116699ca 100644 --- a/src/productTypes/views/ProductTypeCreate.tsx +++ b/src/productTypes/views/ProductTypeCreate.tsx @@ -57,9 +57,10 @@ export const ProductTypeCreate: React.FC = () => { data.shop.defaultWeightUnit)} disabled={loading} - errors={ - createProductTypeOpts.data?.productTypeCreate.errors || [] - } + errors={maybe( + () => createProductTypeOpts.data.productTypeCreate.errors, + [] + )} pageTitle={intl.formatMessage({ defaultMessage: "Create Product Type", description: "header", diff --git a/src/productTypes/views/ProductTypeUpdate/errors.tsx b/src/productTypes/views/ProductTypeUpdate/errors.tsx index 4eaa4ab40..5e2c83535 100644 --- a/src/productTypes/views/ProductTypeUpdate/errors.tsx +++ b/src/productTypes/views/ProductTypeUpdate/errors.tsx @@ -1,19 +1,19 @@ import React from "react"; -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; +import { UserError } from "../../../types"; interface ProductTypeUpdateErrorsState { - addAttributeErrors: ProductErrorFragment[]; - editAttributeErrors: ProductErrorFragment[]; - formErrors: ProductErrorFragment[]; + addAttributeErrors: UserError[]; + editAttributeErrors: UserError[]; + formErrors: UserError[]; } interface ProductTypeUpdateErrorsProps { children: (props: { errors: ProductTypeUpdateErrorsState; set: { - addAttributeErrors: (errors: ProductErrorFragment[]) => void; - editAttributeErrors: (errors: ProductErrorFragment[]) => void; - formErrors: (errors: ProductErrorFragment[]) => void; + addAttributeErrors: (errors: UserError[]) => void; + editAttributeErrors: (errors: UserError[]) => void; + formErrors: (errors: UserError[]) => void; }; }) => React.ReactNode; } @@ -32,12 +32,11 @@ export class ProductTypeUpdateErrors extends React.Component< return this.props.children({ errors: this.state, set: { - addAttributeErrors: (addAttributeErrors: ProductErrorFragment[]) => + addAttributeErrors: (addAttributeErrors: UserError[]) => this.setState({ addAttributeErrors }), - editAttributeErrors: (editAttributeErrors: ProductErrorFragment[]) => + editAttributeErrors: (editAttributeErrors: UserError[]) => this.setState({ editAttributeErrors }), - formErrors: (formErrors: ProductErrorFragment[]) => - this.setState({ formErrors }) + formErrors: (formErrors: UserError[]) => this.setState({ formErrors }) } }); } diff --git a/src/productTypes/views/ProductTypeUpdate/index.tsx b/src/productTypes/views/ProductTypeUpdate/index.tsx index eaa9f99f2..492320261 100644 --- a/src/productTypes/views/ProductTypeUpdate/index.tsx +++ b/src/productTypes/views/ProductTypeUpdate/index.tsx @@ -319,10 +319,13 @@ export const ProductTypeUpdate: React.FC = ({ ) )} confirmButtonState={assignAttribute.opts.status} - errors={ - assignAttribute.opts.data?.attributeAssign - .errors || [] - } + errors={maybe( + () => + assignAttribute.opts.data.attributeAssign.errors.map( + err => err.message + ), + [] + )} loading={result.loading} onClose={closeModal} onSubmit={handleAssignAttribute} diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 208db9898..5ced1da26 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -10012,7 +10012,7 @@ exports[`Storyshots Views / Attributes / Attribute details form errors 1`] = `

- This field is required + Generic form error

- This field is required + Generic form error

- API error + Generic form error

- Unknown error + Generic form error

@@ -85147,7 +85147,7 @@ exports[`Storyshots Views / Product types / Product type details form errors 1`]

- Unknown error + Generic form error

diff --git a/src/storybook/stories/attributes/AttributePage.tsx b/src/storybook/stories/attributes/AttributePage.tsx index a7e806031..e2d8f5b68 100644 --- a/src/storybook/stories/attributes/AttributePage.tsx +++ b/src/storybook/stories/attributes/AttributePage.tsx @@ -5,10 +5,8 @@ import AttributePage, { AttributePageProps } from "@saleor/attributes/components/AttributePage"; import { attribute } from "@saleor/attributes/fixtures"; -import { - AttributeInputTypeEnum, - ProductErrorCode -} from "@saleor/types/globalTypes"; +import { formError } from "@saleor/storybook/misc"; +import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; import Decorator from "../../Decorator"; const props: AttributePageProps = { @@ -41,23 +39,7 @@ storiesOf("Views / Attributes / Attribute details", module) .add("form errors", () => ( ({ - __typename: "ProductError", - ...err - }))} + errors={["name", "slug", "storefrontSearchPosition"].map(formError)} /> )) .add("multiple select input", () => ( diff --git a/src/storybook/stories/attributes/AttributeValueEditDialog.tsx b/src/storybook/stories/attributes/AttributeValueEditDialog.tsx index b072aece1..77d5d6821 100644 --- a/src/storybook/stories/attributes/AttributeValueEditDialog.tsx +++ b/src/storybook/stories/attributes/AttributeValueEditDialog.tsx @@ -2,10 +2,8 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import { attribute } from "@saleor/attributes/fixtures"; -import { - AttributeValueType, - ProductErrorCode -} from "@saleor/types/globalTypes"; +import { formError } from "@saleor/storybook/misc"; +import { AttributeValueType } from "@saleor/types/globalTypes"; import AttributeValueEditDialog, { AttributeValueEditDialogProps } from "../../../attributes/components/AttributeValueEditDialog"; @@ -28,14 +26,5 @@ storiesOf("Attributes / Attribute value edit", module) .addDecorator(Decorator) .add("default", () => ) .add("form errors", () => ( - + )); diff --git a/src/storybook/stories/components/AssignAttributeDialog.tsx b/src/storybook/stories/components/AssignAttributeDialog.tsx index 2d75970fc..9cb0462e5 100644 --- a/src/storybook/stories/components/AssignAttributeDialog.tsx +++ b/src/storybook/stories/components/AssignAttributeDialog.tsx @@ -6,7 +6,7 @@ import { fetchMoreProps } from "@saleor/fixtures"; import AssignAttributeDialog, { AssignAttributeDialogProps } from "@saleor/productTypes/components/AssignAttributeDialog"; -import { ProductErrorCode } from "@saleor/types/globalTypes"; +import { formError } from "@saleor/storybook/misc"; import Decorator from "../../Decorator"; const props: AssignAttributeDialogProps = { @@ -30,14 +30,5 @@ storiesOf("Generics / Assign attributes dialog", module) )) .add("errors", () => ( - + )); diff --git a/src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx b/src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx new file mode 100644 index 000000000..8da8e9d68 --- /dev/null +++ b/src/storybook/stories/productTypes/ProductTypeAttributeEditDialog.tsx @@ -0,0 +1,38 @@ +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", () => ) + .add("loading", () => ( + + )) + .add("form errors", () => ( + formError(field))} + /> + )); diff --git a/src/storybook/stories/productTypes/ProductTypeCreatePage.tsx b/src/storybook/stories/productTypes/ProductTypeCreatePage.tsx index e2cbe7064..e4e2b6ac0 100644 --- a/src/storybook/stories/productTypes/ProductTypeCreatePage.tsx +++ b/src/storybook/stories/productTypes/ProductTypeCreatePage.tsx @@ -2,11 +2,12 @@ import { Omit } from "@material-ui/core"; import { storiesOf } from "@storybook/react"; import React from "react"; +import { formError } from "@saleor/storybook/misc"; import ProductTypeCreatePage, { ProductTypeCreatePageProps, ProductTypeForm } from "../../../productTypes/components/ProductTypeCreatePage"; -import { WeightUnitsEnum, ProductErrorCode } from "../../../types/globalTypes"; +import { WeightUnitsEnum } from "../../../types/globalTypes"; import Decorator from "../../Decorator"; const props: Omit = { @@ -29,10 +30,6 @@ storiesOf("Views / Product types / Create product type", module) .add("form errors", () => ( ).map(field => ({ - __typename: "ProductError", - code: ProductErrorCode.INVALID, - field - }))} + errors={(["name"] as Array).map(formError)} /> )); diff --git a/src/storybook/stories/productTypes/ProductTypeDetailsPage.tsx b/src/storybook/stories/productTypes/ProductTypeDetailsPage.tsx index 1a2065ba1..da2c83493 100644 --- a/src/storybook/stories/productTypes/ProductTypeDetailsPage.tsx +++ b/src/storybook/stories/productTypes/ProductTypeDetailsPage.tsx @@ -3,12 +3,13 @@ import { storiesOf } from "@storybook/react"; import React from "react"; import { listActionsProps } from "@saleor/fixtures"; +import { formError } from "@saleor/storybook/misc"; import ProductTypeDetailsPage, { ProductTypeDetailsPageProps, ProductTypeForm } from "../../../productTypes/components/ProductTypeDetailsPage"; import { productType } from "../../../productTypes/fixtures"; -import { WeightUnitsEnum, ProductErrorCode } from "../../../types/globalTypes"; +import { WeightUnitsEnum } from "../../../types/globalTypes"; import Decorator from "../../Decorator"; const props: Omit = { @@ -54,12 +55,6 @@ storiesOf("Views / Product types / Product type details", module) .add("form errors", () => ( ).map( - field => ({ - __typename: "ProductError", - code: ProductErrorCode.INVALID, - field - }) - )} + errors={(["name"] as Array).map(formError)} /> )); diff --git a/src/types.ts b/src/types.ts index 4ba92d2e5..66d345229 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,7 +7,7 @@ import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelec export interface UserError { field: string | null; - message?: string; + message: string; } export interface DialogProps { diff --git a/src/utils/errors.ts b/src/utils/errors.ts new file mode 100644 index 000000000..9f8669d28 --- /dev/null +++ b/src/utils/errors.ts @@ -0,0 +1,11 @@ +import { UserError } from "@saleor/types"; + +export function getFieldError(errors: UserError[], field: string): UserError { + return errors.find(err => err.field === field); +} + +export function getErrors(errors: UserError[]): string[] { + return errors + .filter(err => ["", null].includes(err.field)) + .map(err => err.message); +} diff --git a/src/utils/errors/common.ts b/src/utils/errors/common.ts deleted file mode 100644 index cac94f7c4..000000000 --- a/src/utils/errors/common.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineMessages } from "react-intl"; - -const commonErrorMessages = defineMessages({ - graphqlError: { - defaultMessage: "API error" - }, - unknownError: { - defaultMessage: "Unknown error" - } -}); - -export default commonErrorMessages; diff --git a/src/utils/errors/index.ts b/src/utils/errors/index.ts deleted file mode 100644 index fc37f31bf..000000000 --- a/src/utils/errors/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { UserError } from "@saleor/types"; - -export function getFieldError( - errors: T[], - field: string -): T { - return errors.find(err => err.field === field); -} - -export function getErrors(errors: UserError[]): string[] { - return errors - .filter(err => ["", null].includes(err.field)) - .map(err => err.message); -} - -export function getFormErrors( - fields: TField[], - errors: TError[] -): Record { - return fields.reduce((errs, field) => { - errs[field] = getFieldError(errors, field); - return errs; - }, ({} as unknown) as Record); -} - -export { default as getProductErrorMessage } from "./product"; diff --git a/src/utils/errors/product.ts b/src/utils/errors/product.ts deleted file mode 100644 index a220bb591..000000000 --- a/src/utils/errors/product.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { IntlShape, defineMessages } from "react-intl"; - -import { ProductErrorFragment } from "@saleor/attributes/types/ProductErrorFragment"; -import { ProductErrorCode } from "@saleor/types/globalTypes"; -import { commonMessages } from "@saleor/intl"; -import commonErrorMessages from "./common"; - -const messages = defineMessages({ - attributeAlreadyAssigned: { - defaultMessage: - "This attribute has already been assigned to this product type" - }, - attributeCannotBeAssigned: { - defaultMessage: "This attribute cannot be assigned to this product type" - }, - attributeVariantsDisabled: { - defaultMessage: "Variants are disabled in this product type" - }, - variantNoDigitalContent: { - defaultMessage: "This variant does not have any digital content" - } -}); - -function getProductErrorMessage( - err: ProductErrorFragment, - intl: IntlShape -): string { - if (err) { - switch (err.code) { - case ProductErrorCode.ATTRIBUTE_ALREADY_ASSIGNED: - return intl.formatMessage(messages.attributeAlreadyAssigned); - case ProductErrorCode.ATTRIBUTE_CANNOT_BE_ASSIGNED: - return intl.formatMessage(messages.attributeCannotBeAssigned); - case ProductErrorCode.ATTRIBUTE_VARIANTS_DISABLED: - return intl.formatMessage(messages.attributeVariantsDisabled); - case ProductErrorCode.GRAPHQL_ERROR: - return intl.formatMessage(commonErrorMessages.graphqlError); - case ProductErrorCode.REQUIRED: - return intl.formatMessage(commonMessages.requiredField); - case ProductErrorCode.VARIANT_NO_DIGITAL_CONTENT: - return intl.formatMessage(messages.variantNoDigitalContent); - default: - return intl.formatMessage(commonErrorMessages.unknownError); - } - } - - return undefined; -} - -export default getProductErrorMessage;