From e1f1a217da0c1368ac56820671b378c9006c9964 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Tue, 17 Mar 2020 11:57:02 +0100 Subject: [PATCH] Use error formatting in page views --- .../PageDetailsPage/PageDetailsPage.tsx | 4 +-- src/pages/components/PageInfo/PageInfo.tsx | 19 +++++++------ src/pages/components/PageSlug/PageSlug.tsx | 13 +++++---- src/pages/mutations.ts | 25 +++++++++++------ src/pages/types/PageCreate.ts | 6 ++-- src/pages/types/PageErrorFragment.ts | 15 ++++++++++ src/pages/types/PageRemove.ts | 6 ++-- src/pages/types/PageUpdate.ts | 6 ++-- src/pages/views/PageCreate.tsx | 3 +- src/pages/views/PageDetails.tsx | 18 ++++++------ src/types/globalTypes.ts | 8 ++++++ src/utils/errors/page.ts | 28 +++++++++++++++++++ 12 files changed, 107 insertions(+), 44 deletions(-) create mode 100644 src/pages/types/PageErrorFragment.ts create mode 100644 src/utils/errors/page.ts diff --git a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx index c00740470..2682e24df 100644 --- a/src/pages/components/PageDetailsPage/PageDetailsPage.tsx +++ b/src/pages/components/PageDetailsPage/PageDetailsPage.tsx @@ -19,8 +19,8 @@ import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import { sectionNames } from "@saleor/intl"; +import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; import { maybe } from "../../../misc"; -import { UserError } from "../../../types"; import { PageDetails_page } from "../../types/PageDetails"; import PageInfo from "../PageInfo"; import PageSlug from "../PageSlug"; @@ -37,7 +37,7 @@ export interface FormData { export interface PageDetailsPageProps { disabled: boolean; - errors: UserError[]; + errors: PageErrorFragment[]; page: PageDetails_page; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; diff --git a/src/pages/components/PageInfo/PageInfo.tsx b/src/pages/components/PageInfo/PageInfo.tsx index e5415b2ae..d6467cb4f 100644 --- a/src/pages/components/PageInfo/PageInfo.tsx +++ b/src/pages/components/PageInfo/PageInfo.tsx @@ -9,16 +9,17 @@ import CardTitle from "@saleor/components/CardTitle"; import FormSpacer from "@saleor/components/FormSpacer"; import RichTextEditor from "@saleor/components/RichTextEditor"; import { commonMessages } from "@saleor/intl"; -import { getFieldError } from "@saleor/utils/errors"; +import { getFormErrors } from "@saleor/utils/errors"; +import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; +import getPageErrorMessage from "@saleor/utils/errors/page"; import { maybe } from "../../../misc"; -import { UserError } from "../../../types"; import { PageDetails_page } from "../../types/PageDetails"; import { FormData } from "../PageDetailsPage"; export interface PageInfoProps { data: FormData; disabled: boolean; - errors: UserError[]; + errors: PageErrorFragment[]; page: PageDetails_page; onChange: (event: React.ChangeEvent) => void; } @@ -34,10 +35,12 @@ const useStyles = makeStyles( const PageInfo: React.FC = props => { const { data, disabled, errors, page, onChange } = props; - const classes = useStyles(props); + const classes = useStyles(props); const intl = useIntl(); + const formErrors = getFormErrors(["title", "contentJson"], errors); + return ( = props => { = props => { JSON.parse(page.contentJson))} label={intl.formatMessage({ defaultMessage: "Content", diff --git a/src/pages/components/PageSlug/PageSlug.tsx b/src/pages/components/PageSlug/PageSlug.tsx index 660adadd9..9cd191c5b 100644 --- a/src/pages/components/PageSlug/PageSlug.tsx +++ b/src/pages/components/PageSlug/PageSlug.tsx @@ -6,14 +6,15 @@ import { useIntl } from "react-intl"; import slugify from "slugify"; import CardTitle from "@saleor/components/CardTitle"; -import { UserError } from "@saleor/types"; -import { getFieldError } from "@saleor/utils/errors"; +import { getFormErrors } from "@saleor/utils/errors"; +import getPageErrorMessage from "@saleor/utils/errors/page"; +import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; import { FormData } from "../PageDetailsPage"; export interface PageSlugProps { data: FormData; disabled: boolean; - errors: UserError[]; + errors: PageErrorFragment[]; onChange: (event: React.ChangeEvent) => void; } @@ -25,6 +26,8 @@ const PageSlug: React.FC = ({ }) => { const intl = useIntl(); + const formErrors = getFormErrors(["slug"], errors); + return ( = ({ ( const pageUpdate = gql` ${pageDetailsFragment} + ${pageErrorFragment} mutation PageUpdate($id: ID!, $input: PageInput!) { pageUpdate(id: $id, input: $input) { - errors { - field - message + errors: pageErrors { + ...PageErrorFragment } page { ...PageDetailsFragment @@ -51,11 +58,11 @@ export const TypedPageUpdate = TypedMutation( ); const pageRemove = gql` + ${pageErrorFragment} mutation PageRemove($id: ID!) { pageDelete(id: $id) { - errors { - field - message + errors: pageErrors { + ...PageErrorFragment } } } diff --git a/src/pages/types/PageCreate.ts b/src/pages/types/PageCreate.ts index 6a450bb9a..2101f6a48 100644 --- a/src/pages/types/PageCreate.ts +++ b/src/pages/types/PageCreate.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { PageInput } from "./../../types/globalTypes"; +import { PageInput, PageErrorCode } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: PageCreate // ==================================================== export interface PageCreate_pageCreate_errors { - __typename: "Error"; + __typename: "PageError"; + code: PageErrorCode; field: string | null; - message: string | null; } export interface PageCreate_pageCreate_page { diff --git a/src/pages/types/PageErrorFragment.ts b/src/pages/types/PageErrorFragment.ts new file mode 100644 index 000000000..a61010897 --- /dev/null +++ b/src/pages/types/PageErrorFragment.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PageErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: PageErrorFragment +// ==================================================== + +export interface PageErrorFragment { + __typename: "PageError"; + code: PageErrorCode; + field: string | null; +} diff --git a/src/pages/types/PageRemove.ts b/src/pages/types/PageRemove.ts index 721864afc..6cbce1def 100644 --- a/src/pages/types/PageRemove.ts +++ b/src/pages/types/PageRemove.ts @@ -2,14 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. +import { PageErrorCode } from "./../../types/globalTypes"; + // ==================================================== // GraphQL mutation operation: PageRemove // ==================================================== export interface PageRemove_pageDelete_errors { - __typename: "Error"; + __typename: "PageError"; + code: PageErrorCode; field: string | null; - message: string | null; } export interface PageRemove_pageDelete { diff --git a/src/pages/types/PageUpdate.ts b/src/pages/types/PageUpdate.ts index 4933d8eb7..ae022c75a 100644 --- a/src/pages/types/PageUpdate.ts +++ b/src/pages/types/PageUpdate.ts @@ -2,16 +2,16 @@ /* eslint-disable */ // This file was automatically generated and should not be edited. -import { PageInput } from "./../../types/globalTypes"; +import { PageInput, PageErrorCode } from "./../../types/globalTypes"; // ==================================================== // GraphQL mutation operation: PageUpdate // ==================================================== export interface PageUpdate_pageUpdate_errors { - __typename: "Error"; + __typename: "PageError"; + code: PageErrorCode; field: string | null; - message: string | null; } export interface PageUpdate_pageUpdate_page { diff --git a/src/pages/views/PageCreate.tsx b/src/pages/views/PageCreate.tsx index 1acdf2e15..d9f95a34f 100644 --- a/src/pages/views/PageCreate.tsx +++ b/src/pages/views/PageCreate.tsx @@ -4,7 +4,6 @@ import { useIntl } from "react-intl"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; -import { maybe } from "../../misc"; import PageDetailsPage from "../components/PageDetailsPage"; import { TypedPageCreate } from "../mutations"; import { PageCreate as PageCreateData } from "../types/PageCreate"; @@ -42,7 +41,7 @@ export const PageCreate: React.FC = () => { /> pageCreateOpts.data.pageCreate.errors, [])} + errors={pageCreateOpts.data?.pageCreate.errors || []} saveButtonBarState={pageCreateOpts.status} page={null} onBack={() => navigate(pageListUrl())} diff --git a/src/pages/views/PageDetails.tsx b/src/pages/views/PageDetails.tsx index 8e3658127..1d02ee9e0 100644 --- a/src/pages/views/PageDetails.tsx +++ b/src/pages/views/PageDetails.tsx @@ -6,7 +6,8 @@ import ActionDialog from "@saleor/components/ActionDialog"; import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; -import { maybe } from "../../misc"; +import { commonMessages } from "@saleor/intl"; +import { maybe, getStringOrPlaceholder } from "../../misc"; import { PageInput } from "../../types/globalTypes"; import PageDetailsPage, { FormData } from "../components/PageDetailsPage"; import { TypedPageRemove, TypedPageUpdate } from "../mutations"; @@ -43,9 +44,7 @@ export const PageDetails: React.FC = ({ id, params }) => { const handlePageRemove = (data: PageRemove) => { if (data.pageDelete.errors.length === 0) { notify({ - text: intl.formatMessage({ - defaultMessage: "Removed page" - }) + text: intl.formatMessage(commonMessages.savedChanges) }); navigate(pageListUrl()); } @@ -63,12 +62,9 @@ export const PageDetails: React.FC = ({ id, params }) => { /> pageUpdateOpts.data.pageUpdate.errors, - [] - )} + errors={pageUpdateOpts.data?.pageUpdate.errors || []} saveButtonBarState={pageUpdateOpts.status} - page={maybe(() => pageDetails.data.page)} + page={pageDetails.data?.page} onBack={() => navigate(pageListUrl())} onRemove={() => navigate( @@ -104,7 +100,9 @@ export const PageDetails: React.FC = ({ id, params }) => { values={{ title: ( - {maybe(() => pageDetails.data.page.title, "...")} + {getStringOrPlaceholder( + pageDetails.data?.page?.title + )} ) }} diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts index 120fce37e..5fe8d94e5 100644 --- a/src/types/globalTypes.ts +++ b/src/types/globalTypes.ts @@ -519,6 +519,14 @@ export enum OrderStatusFilter { UNFULFILLED = "UNFULFILLED", } +export enum PageErrorCode { + GRAPHQL_ERROR = "GRAPHQL_ERROR", + INVALID = "INVALID", + NOT_FOUND = "NOT_FOUND", + REQUIRED = "REQUIRED", + UNIQUE = "UNIQUE", +} + export enum PageSortField { CREATION_DATE = "CREATION_DATE", PUBLICATION_DATE = "PUBLICATION_DATE", diff --git a/src/utils/errors/page.ts b/src/utils/errors/page.ts new file mode 100644 index 000000000..01cda4817 --- /dev/null +++ b/src/utils/errors/page.ts @@ -0,0 +1,28 @@ +import { IntlShape } from "react-intl"; + +import { PageErrorFragment } from "@saleor/pages/types/PageErrorFragment"; +import { PageErrorCode } from "@saleor/types/globalTypes"; +import { commonMessages } from "@saleor/intl"; +import commonErrorMessages from "./common"; + +function getPageErrorMessage( + err: Omit | undefined, + intl: IntlShape +): string { + if (err) { + switch (err.code) { + case PageErrorCode.GRAPHQL_ERROR: + return intl.formatMessage(commonErrorMessages.graphqlError); + case PageErrorCode.REQUIRED: + return intl.formatMessage(commonMessages.requiredField); + case PageErrorCode.INVALID: + return intl.formatMessage(commonErrorMessages.invalid); + default: + return intl.formatMessage(commonErrorMessages.unknownError); + } + } + + return undefined; +} + +export default getPageErrorMessage;