Use error formatting in page views
This commit is contained in:
parent
78b3feb656
commit
e1f1a217da
12 changed files with 107 additions and 44 deletions
|
@ -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;
|
||||
|
|
|
@ -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<any>) => void;
|
||||
}
|
||||
|
@ -34,10 +35,12 @@ const useStyles = makeStyles(
|
|||
|
||||
const PageInfo: React.FC<PageInfoProps> = 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 (
|
||||
<Card className={classes.root}>
|
||||
<CardTitle
|
||||
|
@ -46,9 +49,9 @@ const PageInfo: React.FC<PageInfoProps> = props => {
|
|||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!getFieldError(errors, "title")}
|
||||
error={!!formErrors.title}
|
||||
fullWidth
|
||||
helperText={getFieldError(errors, "title")?.message}
|
||||
helperText={getPageErrorMessage(formErrors.title, intl)}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Title",
|
||||
description: "page title"
|
||||
|
@ -60,8 +63,8 @@ const PageInfo: React.FC<PageInfoProps> = props => {
|
|||
<FormSpacer />
|
||||
<RichTextEditor
|
||||
disabled={disabled}
|
||||
error={!!getFieldError(errors, "contentJson")}
|
||||
helperText={getFieldError(errors, "contentJson")?.message}
|
||||
error={!!formErrors.contentJson}
|
||||
helperText={getPageErrorMessage(formErrors.contentJson, intl)}
|
||||
initial={maybe(() => JSON.parse(page.contentJson))}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Content",
|
||||
|
|
|
@ -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<any>) => void;
|
||||
}
|
||||
|
||||
|
@ -25,6 +26,8 @@ const PageSlug: React.FC<PageSlugProps> = ({
|
|||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const formErrors = getFormErrors(["slug"], errors);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
|
@ -36,13 +39,13 @@ const PageSlug: React.FC<PageSlugProps> = ({
|
|||
<TextField
|
||||
name={"slug" as keyof FormData}
|
||||
disabled={disabled}
|
||||
error={!!getFieldError(errors, "slug")}
|
||||
error={!!formErrors.slug}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Slug",
|
||||
description: "page internal name"
|
||||
})}
|
||||
helperText={
|
||||
getFieldError(errors, "slug")?.message ||
|
||||
getPageErrorMessage(formErrors.slug, intl) ||
|
||||
intl.formatMessage({
|
||||
defaultMessage:
|
||||
"If empty, URL will be autogenerated from Page Name"
|
||||
|
|
|
@ -14,13 +14,20 @@ import { PageCreate, PageCreateVariables } from "./types/PageCreate";
|
|||
import { PageRemove, PageRemoveVariables } from "./types/PageRemove";
|
||||
import { PageUpdate, PageUpdateVariables } from "./types/PageUpdate";
|
||||
|
||||
const pageErrorFragment = gql`
|
||||
fragment PageErrorFragment on PageError {
|
||||
code
|
||||
field
|
||||
}
|
||||
`;
|
||||
|
||||
const pageCreate = gql`
|
||||
${pageDetailsFragment}
|
||||
${pageErrorFragment}
|
||||
mutation PageCreate($input: PageInput!) {
|
||||
pageCreate(input: $input) {
|
||||
errors {
|
||||
field
|
||||
message
|
||||
errors: pageErrors {
|
||||
...PageErrorFragment
|
||||
}
|
||||
page {
|
||||
...PageDetailsFragment
|
||||
|
@ -34,11 +41,11 @@ export const TypedPageCreate = TypedMutation<PageCreate, PageCreateVariables>(
|
|||
|
||||
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<PageUpdate, PageUpdateVariables>(
|
|||
);
|
||||
|
||||
const pageRemove = gql`
|
||||
${pageErrorFragment}
|
||||
mutation PageRemove($id: ID!) {
|
||||
pageDelete(id: $id) {
|
||||
errors {
|
||||
field
|
||||
message
|
||||
errors: pageErrors {
|
||||
...PageErrorFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
15
src/pages/types/PageErrorFragment.ts
Normal file
15
src/pages/types/PageErrorFragment.ts
Normal file
|
@ -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;
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<PageCreateProps> = () => {
|
|||
/>
|
||||
<PageDetailsPage
|
||||
disabled={pageCreateOpts.loading}
|
||||
errors={maybe(() => pageCreateOpts.data.pageCreate.errors, [])}
|
||||
errors={pageCreateOpts.data?.pageCreate.errors || []}
|
||||
saveButtonBarState={pageCreateOpts.status}
|
||||
page={null}
|
||||
onBack={() => navigate(pageListUrl())}
|
||||
|
|
|
@ -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<PageDetailsProps> = ({ 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<PageDetailsProps> = ({ id, params }) => {
|
|||
/>
|
||||
<PageDetailsPage
|
||||
disabled={pageDetails.loading}
|
||||
errors={maybe(
|
||||
() => 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<PageDetailsProps> = ({ id, params }) => {
|
|||
values={{
|
||||
title: (
|
||||
<strong>
|
||||
{maybe(() => pageDetails.data.page.title, "...")}
|
||||
{getStringOrPlaceholder(
|
||||
pageDetails.data?.page?.title
|
||||
)}
|
||||
</strong>
|
||||
)
|
||||
}}
|
||||
|
|
|
@ -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",
|
||||
|
|
28
src/utils/errors/page.ts
Normal file
28
src/utils/errors/page.ts
Normal file
|
@ -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<PageErrorFragment, "__typename"> | 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;
|
Loading…
Reference in a new issue