Add error translations

This commit is contained in:
dominik-zeglen 2020-03-27 13:21:34 +01:00
parent d38fa42462
commit d0e082dc21
11 changed files with 161 additions and 34 deletions

View file

@ -15,12 +15,16 @@ import { getFormErrors } from "@saleor/utils/errors";
import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"; import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment"; import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import getAccountErrorMessage from "@saleor/utils/errors/account"; import getAccountErrorMessage from "@saleor/utils/errors/account";
import getWarehouseErrorMessage from "@saleor/utils/errors/warehouse";
import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment";
export interface CompanyAddressFormProps { export interface CompanyAddressFormProps {
countries: SingleAutocompleteChoiceType[]; countries: SingleAutocompleteChoiceType[];
data: AddressTypeInput; data: AddressTypeInput;
displayCountry: string; displayCountry: string;
errors: Array<AccountErrorFragment | ShopErrorFragment>; errors: Array<
AccountErrorFragment | ShopErrorFragment | WarehouseErrorFragment
>;
disabled: boolean; disabled: boolean;
onChange: (event: ChangeEvent) => void; onChange: (event: ChangeEvent) => void;
onCountryChange: (event: ChangeEvent) => void; onCountryChange: (event: ChangeEvent) => void;
@ -34,14 +38,17 @@ const useStyles = makeStyles(
); );
function getErrorMessage( function getErrorMessage(
err: AccountErrorFragment | ShopErrorFragment, err: AccountErrorFragment | ShopErrorFragment | WarehouseErrorFragment,
intl: IntlShape intl: IntlShape
): string { ): string {
if (err?.__typename === "AccountError") { switch (err?.__typename) {
return getAccountErrorMessage(err, intl); case "AccountError":
return getAccountErrorMessage(err, intl);
case "WarehouseError":
return getWarehouseErrorMessage(err, intl);
default:
return getShopErrorMessage(err, intl);
} }
return getShopErrorMessage(err, intl);
} }
const CompanyAddressForm: React.FC<CompanyAddressFormProps> = props => { const CompanyAddressForm: React.FC<CompanyAddressFormProps> = props => {

View file

@ -5,7 +5,7 @@ import DialogContent from "@material-ui/core/DialogContent";
import DialogTitle from "@material-ui/core/DialogTitle"; import DialogTitle from "@material-ui/core/DialogTitle";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl, IntlShape } from "react-intl";
import makeStyles from "@material-ui/core/styles/makeStyles"; import makeStyles from "@material-ui/core/styles/makeStyles";
import { diff, DiffData } from "fast-array-diff"; import { diff, DiffData } from "fast-array-diff";
@ -20,6 +20,9 @@ import { isSelected, toggle } from "@saleor/utils/lists";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { BulkStockErrorFragment } from "@saleor/products/types/BulkStockErrorFragment"; import { BulkStockErrorFragment } from "@saleor/products/types/BulkStockErrorFragment";
import { StockErrorFragment } from "@saleor/products/types/StockErrorFragment"; import { StockErrorFragment } from "@saleor/products/types/StockErrorFragment";
import getStockErrorMessage, {
getBulkStockErrorMessage
} from "@saleor/utils/errors/stock";
const useStyles = makeStyles( const useStyles = makeStyles(
theme => ({ theme => ({
@ -49,6 +52,18 @@ export interface ProductWarehousesDialogProps {
onConfirm: (data: DiffData<string>) => void; onConfirm: (data: DiffData<string>) => void;
} }
function getErrorMessage(
err: BulkStockErrorFragment | StockErrorFragment,
intl: IntlShape
): string {
switch (err?.__typename) {
case "BulkStockError":
return getBulkStockErrorMessage(err, intl);
default:
getStockErrorMessage(err, intl);
}
}
const ProductWarehousesDialog: React.FC<ProductWarehousesDialogProps> = ({ const ProductWarehousesDialog: React.FC<ProductWarehousesDialogProps> = ({
confirmButtonState, confirmButtonState,
disabled, disabled,
@ -112,7 +127,9 @@ const ProductWarehousesDialog: React.FC<ProductWarehousesDialogProps> = ({
</DialogContent> </DialogContent>
{errors.length > 0 && ( {errors.length > 0 && (
<DialogContent className={classes.errorParagraph}> <DialogContent className={classes.errorParagraph}>
<Typography color="error">{errors[0]?.message}</Typography> <Typography color="error">
{getErrorMessage(errors[0], intl)}
</Typography>
</DialogContent> </DialogContent>
)} )}
<DialogActions> <DialogActions>

47
src/utils/errors/stock.ts Normal file
View file

@ -0,0 +1,47 @@
import { IntlShape, defineMessages } from "react-intl";
import { StockErrorFragment } from "@saleor/products/types/StockErrorFragment";
import { StockErrorCode } from "@saleor/types/globalTypes";
import { commonMessages } from "@saleor/intl";
import { BulkStockErrorFragment } from "@saleor/products/types/BulkStockErrorFragment";
import commonErrorMessages from "./common";
import getProductErrorMessage from "./product";
const messages = defineMessages({
slugUnique: {
defaultMessage:
"Stock for this warehouse already exists for this product variant",
description: "error message"
}
});
function getStockErrorMessage(
err: Omit<StockErrorFragment, "__typename"> | undefined,
intl: IntlShape
): string {
if (err) {
switch (err.code) {
case StockErrorCode.UNIQUE:
return intl.formatMessage(messages.slugUnique);
case StockErrorCode.GRAPHQL_ERROR:
return intl.formatMessage(commonErrorMessages.graphqlError);
case StockErrorCode.REQUIRED:
return intl.formatMessage(commonMessages.requiredField);
case StockErrorCode.INVALID:
return intl.formatMessage(commonErrorMessages.invalid);
default:
return intl.formatMessage(commonErrorMessages.unknownError);
}
}
return undefined;
}
export function getBulkStockErrorMessage(
err: Omit<BulkStockErrorFragment, "__typename"> | undefined,
intl: IntlShape
): string {
return getProductErrorMessage(err, intl);
}
export default getStockErrorMessage;

View file

@ -0,0 +1,51 @@
import { IntlShape, defineMessages } from "react-intl";
import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment";
import { WarehouseErrorCode } from "@saleor/types/globalTypes";
import { commonMessages } from "@saleor/intl";
import commonErrorMessages from "./common";
const messages = defineMessages({
slugUnique: {
defaultMessage: "Slug must be unique for each warehouse",
description: "error message"
}
});
function getWarehouseErrorMessage(
err: Omit<WarehouseErrorFragment, "__typename"> | undefined,
intl: IntlShape
): string {
if (err) {
switch (err.code) {
case WarehouseErrorCode.GRAPHQL_ERROR:
return intl.formatMessage(commonErrorMessages.graphqlError);
case WarehouseErrorCode.REQUIRED:
return intl.formatMessage(commonMessages.requiredField);
case WarehouseErrorCode.INVALID:
return intl.formatMessage(commonErrorMessages.invalid);
default:
return intl.formatMessage(commonErrorMessages.unknownError);
}
}
return undefined;
}
export function getWarehouseSlugErrorMessage(
err: Omit<WarehouseErrorFragment, "__typename"> | undefined,
intl: IntlShape
): string {
if (err) {
switch (err.code) {
case WarehouseErrorCode.UNIQUE:
return intl.formatMessage(messages.slugUnique);
default:
return getWarehouseErrorMessage(err, intl);
}
}
return undefined;
}
export default getWarehouseErrorMessage;

View file

@ -5,7 +5,6 @@ import Container from "@saleor/components/Container";
import Form from "@saleor/components/Form"; import Form from "@saleor/components/Form";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
import { UserError } from "@saleor/types";
import Grid from "@saleor/components/Grid"; import Grid from "@saleor/components/Grid";
import CardSpacer from "@saleor/components/CardSpacer"; import CardSpacer from "@saleor/components/CardSpacer";
import CompanyAddressInput from "@saleor/components/CompanyAddressInput"; import CompanyAddressInput from "@saleor/components/CompanyAddressInput";
@ -18,6 +17,7 @@ import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment";
import WarehouseInfo from "../WarehouseInfo"; import WarehouseInfo from "../WarehouseInfo";
export interface WarehouseCreatePageFormData extends AddressTypeInput { export interface WarehouseCreatePageFormData extends AddressTypeInput {
@ -26,7 +26,7 @@ export interface WarehouseCreatePageFormData extends AddressTypeInput {
export interface WarehouseCreatePageProps { export interface WarehouseCreatePageProps {
countries: ShopInfo_shop_countries[]; countries: ShopInfo_shop_countries[];
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: WarehouseErrorFragment[];
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
onBack: () => void; onBack: () => void;
onSubmit: (data: WarehouseCreatePageFormData) => void; onSubmit: (data: WarehouseCreatePageFormData) => void;

View file

@ -5,7 +5,6 @@ import Container from "@saleor/components/Container";
import Form from "@saleor/components/Form"; import Form from "@saleor/components/Form";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
import { UserError } from "@saleor/types";
import Grid from "@saleor/components/Grid"; import Grid from "@saleor/components/Grid";
import CardSpacer from "@saleor/components/CardSpacer"; import CardSpacer from "@saleor/components/CardSpacer";
import CompanyAddressInput from "@saleor/components/CompanyAddressInput"; import CompanyAddressInput from "@saleor/components/CompanyAddressInput";
@ -20,6 +19,7 @@ import AppHeader from "@saleor/components/AppHeader";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { CountryCode } from "@saleor/types/globalTypes"; import { CountryCode } from "@saleor/types/globalTypes";
import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment";
import WarehouseInfo from "../WarehouseInfo"; import WarehouseInfo from "../WarehouseInfo";
import WarehouseZones from "../WarehouseZones"; import WarehouseZones from "../WarehouseZones";
import { WarehouseDetails_warehouse } from "../../types/WarehouseDetails"; import { WarehouseDetails_warehouse } from "../../types/WarehouseDetails";
@ -30,7 +30,7 @@ export interface WarehouseDetailsPageFormData extends AddressTypeInput {
export interface WarehouseDetailsPageProps { export interface WarehouseDetailsPageProps {
countries: ShopInfo_shop_countries[]; countries: ShopInfo_shop_countries[];
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: WarehouseErrorFragment[];
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
warehouse: WarehouseDetails_warehouse; warehouse: WarehouseDetails_warehouse;
onBack: () => void; onBack: () => void;

View file

@ -7,13 +7,14 @@ 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 { FormChange } from "@saleor/hooks/useForm"; import { FormChange } from "@saleor/hooks/useForm";
import { UserError } from "@saleor/types"; import { getFormErrors } from "@saleor/utils/errors";
import { getFieldError } from "@saleor/utils/errors"; import { WarehouseErrorFragment } from "@saleor/warehouses/types/WarehouseErrorFragment";
import getWarehouseErrorMessage from "@saleor/utils/errors/warehouse";
export interface WarehouseInfoProps { export interface WarehouseInfoProps {
data: Record<"name", string>; data: Record<"name", string>;
disabled: boolean; disabled: boolean;
errors: UserError[]; errors: WarehouseErrorFragment[];
onChange: FormChange; onChange: FormChange;
} }
@ -25,6 +26,8 @@ const WarehouseInfo: React.FC<WarehouseInfoProps> = ({
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const formErrors = getFormErrors(["name"], errors);
return ( return (
<Card> <Card>
<CardTitle <CardTitle
@ -33,9 +36,9 @@ const WarehouseInfo: React.FC<WarehouseInfoProps> = ({
<CardContent> <CardContent>
<TextField <TextField
disabled={disabled} disabled={disabled}
error={!!getFieldError(errors, "name")} error={!!formErrors.name}
fullWidth fullWidth
helperText={getFieldError(errors, "name")?.message} helperText={getWarehouseErrorMessage(formErrors.name, intl)}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Warehouse Name" defaultMessage: "Warehouse Name"
})} })}

View file

@ -23,11 +23,11 @@ export const warehouseErrorFragment = gql`
`; `;
const deleteWarehouse = gql` const deleteWarehouse = gql`
${warehouseErrorFragment}
mutation WarehouseDelete($id: ID!) { mutation WarehouseDelete($id: ID!) {
deleteWarehouse(id: $id) { deleteWarehouse(id: $id) {
errors { errors: warehouseErrors {
field ...WarehouseErrorFragment
message
} }
} }
} }
@ -39,11 +39,11 @@ export const useWarehouseDelete = makeMutation<
const createWarehouse = gql` const createWarehouse = gql`
${warehouseDetailsFragment} ${warehouseDetailsFragment}
${warehouseErrorFragment}
mutation WarehouseCreate($input: WarehouseCreateInput!) { mutation WarehouseCreate($input: WarehouseCreateInput!) {
createWarehouse(input: $input) { createWarehouse(input: $input) {
errors { errors: warehouseErrors {
field ...WarehouseErrorFragment
message
} }
warehouse { warehouse {
...WarehouseDetailsFragment ...WarehouseDetailsFragment
@ -58,11 +58,11 @@ export const useWarehouseCreate = makeMutation<
const updateWarehouse = gql` const updateWarehouse = gql`
${warehouseDetailsFragment} ${warehouseDetailsFragment}
${warehouseErrorFragment}
mutation WarehouseUpdate($id: ID!, $input: WarehouseUpdateInput!) { mutation WarehouseUpdate($id: ID!, $input: WarehouseUpdateInput!) {
updateWarehouse(id: $id, input: $input) { updateWarehouse(id: $id, input: $input) {
errors { errors: warehouseErrors {
field ...WarehouseErrorFragment
message
} }
warehouse { warehouse {
...WarehouseDetailsFragment ...WarehouseDetailsFragment

View file

@ -2,16 +2,16 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { WarehouseCreateInput } from "./../../types/globalTypes"; import { WarehouseCreateInput, WarehouseErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: WarehouseCreate // GraphQL mutation operation: WarehouseCreate
// ==================================================== // ====================================================
export interface WarehouseCreate_createWarehouse_errors { export interface WarehouseCreate_createWarehouse_errors {
__typename: "Error"; __typename: "WarehouseError";
code: WarehouseErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface WarehouseCreate_createWarehouse_warehouse_shippingZones_edges_node { export interface WarehouseCreate_createWarehouse_warehouse_shippingZones_edges_node {

View file

@ -2,14 +2,16 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { WarehouseErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: WarehouseDelete // GraphQL mutation operation: WarehouseDelete
// ==================================================== // ====================================================
export interface WarehouseDelete_deleteWarehouse_errors { export interface WarehouseDelete_deleteWarehouse_errors {
__typename: "Error"; __typename: "WarehouseError";
code: WarehouseErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface WarehouseDelete_deleteWarehouse { export interface WarehouseDelete_deleteWarehouse {

View file

@ -2,16 +2,16 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { WarehouseUpdateInput } from "./../../types/globalTypes"; import { WarehouseUpdateInput, WarehouseErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: WarehouseUpdate // GraphQL mutation operation: WarehouseUpdate
// ==================================================== // ====================================================
export interface WarehouseUpdate_updateWarehouse_errors { export interface WarehouseUpdate_updateWarehouse_errors {
__typename: "Error"; __typename: "WarehouseError";
code: WarehouseErrorCode;
field: string | null; field: string | null;
message: string | null;
} }
export interface WarehouseUpdate_updateWarehouse_warehouse_shippingZones_edges_node { export interface WarehouseUpdate_updateWarehouse_warehouse_shippingZones_edges_node {