Merge pull request #410 from mirumee/ref/do-not-format-errors-in-forms
Do not store errors in form component
This commit is contained in:
commit
16291446a0
85 changed files with 2242 additions and 778 deletions
|
@ -35,6 +35,7 @@ All notable, unreleased changes to this project will be documented in this file.
|
||||||
- Use structurized JSON files instead of PO - #403 by @dominik-zeglen
|
- Use structurized JSON files instead of PO - #403 by @dominik-zeglen
|
||||||
- Remove PO files from repo and update translations #409 by @dominik-zeglen
|
- Remove PO files from repo and update translations #409 by @dominik-zeglen
|
||||||
- Add optional chaining and explicitely return "Not found" page - #408 by @dominik-zeglen
|
- Add optional chaining and explicitely return "Not found" page - #408 by @dominik-zeglen
|
||||||
|
- Do not store errors in form component - #410 by @dominik-zeglen
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,16 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import SingleSelectField from "@saleor/components/SingleSelectField";
|
import SingleSelectField from "@saleor/components/SingleSelectField";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
import { AttributeInputTypeEnum } from "@saleor/types/globalTypes";
|
import { AttributeInputTypeEnum } from "@saleor/types/globalTypes";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { AttributePageFormData } from "../AttributePage";
|
import { AttributePageFormData } from "../AttributePage";
|
||||||
|
|
||||||
export interface AttributeDetailsProps {
|
export interface AttributeDetailsProps {
|
||||||
canChangeType: boolean;
|
canChangeType: boolean;
|
||||||
data: AttributePageFormData;
|
data: AttributePageFormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"name" | "slug" | "inputType">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,21 +56,21 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Default Label",
|
defaultMessage: "Default Label",
|
||||||
description: "attribute's label"
|
description: "attribute's label"
|
||||||
})}
|
})}
|
||||||
name={"name" as keyof AttributePageFormData}
|
name={"name" as keyof AttributePageFormData}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
value={data.name}
|
value={data.name}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.slug}
|
error={!!getFieldError(errors, "slug")}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Attribute Code",
|
defaultMessage: "Attribute Code",
|
||||||
description: "attribute's slug short code label"
|
description: "attribute's slug short code label"
|
||||||
|
@ -78,7 +79,7 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({
|
||||||
placeholder={slugify(data.name).toLowerCase()}
|
placeholder={slugify(data.name).toLowerCase()}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={
|
helperText={
|
||||||
errors.slug ||
|
getFieldError(errors, "slug")?.message ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"This is used internally. Make sure you don’t use spaces",
|
"This is used internally. Make sure you don’t use spaces",
|
||||||
|
@ -92,8 +93,8 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = ({
|
||||||
<SingleSelectField
|
<SingleSelectField
|
||||||
choices={inputTypeChoices}
|
choices={inputTypeChoices}
|
||||||
disabled={disabled || !canChangeType}
|
disabled={disabled || !canChangeType}
|
||||||
error={!!errors.inputType}
|
error={!!getFieldError(errors, "inputType")}
|
||||||
hint={errors.inputType}
|
hint={getFieldError(errors, "inputType")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Catalog Input type for Store Owner",
|
defaultMessage: "Catalog Input type for Store Owner",
|
||||||
description: "attribute's editor component"
|
description: "attribute's editor component"
|
||||||
|
|
|
@ -108,8 +108,8 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={handleSubmit}>
|
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||||
{({ change, errors: formErrors, data, submit }) => (
|
{({ change, data, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.attributes)}
|
{intl.formatMessage(sectionNames.attributes)}
|
||||||
|
@ -130,7 +130,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
||||||
canChangeType={attribute === null}
|
canChangeType={attribute === null}
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -146,7 +146,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
|
||||||
<div>
|
<div>
|
||||||
<AttributeProperties
|
<AttributeProperties
|
||||||
data={data}
|
data={data}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -11,13 +11,14 @@ import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import Hr from "@saleor/components/Hr";
|
import Hr from "@saleor/components/Hr";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { AttributePageFormData } from "../AttributePage";
|
import { AttributePageFormData } from "../AttributePage";
|
||||||
|
|
||||||
export interface AttributePropertiesProps {
|
export interface AttributePropertiesProps {
|
||||||
data: AttributePageFormData;
|
data: AttributePageFormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"storefrontSearchPosition">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +86,11 @@ const AttributeProperties: React.FC<AttributePropertiesProps> = ({
|
||||||
{data.filterableInStorefront && (
|
{data.filterableInStorefront && (
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.storefrontSearchPosition}
|
error={!!getFieldError(errors, "storefrontSearchPosition")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.storefrontSearchPosition}
|
helperText={
|
||||||
|
getFieldError(errors, "storefrontSearchPosition")?.message
|
||||||
|
}
|
||||||
name={"storefrontSearchPosition" as keyof AttributePageFormData}
|
name={"storefrontSearchPosition" as keyof AttributePageFormData}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Position in faceted navigation",
|
defaultMessage: "Position in faceted navigation",
|
||||||
|
|
|
@ -15,6 +15,7 @@ import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
import { UserError } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { AttributeDetails_attribute_values } from "../../types/AttributeDetails";
|
import { AttributeDetails_attribute_values } from "../../types/AttributeDetails";
|
||||||
|
|
||||||
export interface AttributeValueEditDialogFormData {
|
export interface AttributeValueEditDialogFormData {
|
||||||
|
@ -60,16 +61,16 @@ const AttributeValueEditDialog: React.FC<AttributeValueEditDialogProps> = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, submit }) => (
|
{({ change, data, submit }) => (
|
||||||
<>
|
<>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<TextField
|
<TextField
|
||||||
autoFocus
|
autoFocus
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!formErrors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={formErrors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
name={"name" as keyof AttributeValueEditDialogFormData}
|
name={"name" as keyof AttributeValueEditDialogFormData}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Name",
|
defaultMessage: "Name",
|
||||||
|
|
|
@ -40,18 +40,13 @@ export const CategoryCreatePage: React.FC<CategoryCreatePageProps> = ({
|
||||||
disabled,
|
disabled,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onBack,
|
onBack,
|
||||||
errors: userErrors,
|
errors,
|
||||||
saveButtonBarState
|
saveButtonBarState
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form onSubmit={onSubmit} initial={initialData} confirmLeave>
|
||||||
onSubmit={onSubmit}
|
{({ data, change, submit, hasChanged }) => (
|
||||||
initial={initialData}
|
|
||||||
errors={userErrors}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ data, change, errors, submit, hasChanged }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.categories)}
|
{intl.formatMessage(sectionNames.categories)}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { CategoryDetails_category } from "../../types/CategoryDetails";
|
import { CategoryDetails_category } from "../../types/CategoryDetails";
|
||||||
|
|
||||||
|
@ -19,7 +21,7 @@ interface CategoryDetailsFormProps {
|
||||||
description: RawDraftContentState;
|
description: RawDraftContentState;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: { [key: string]: string };
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,16 +49,16 @@ export const CategoryDetailsForm: React.FC<CategoryDetailsFormProps> = ({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data && data.name}
|
value={data && data.name}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<RichTextEditor
|
<RichTextEditor
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.descriptionJson}
|
error={!!getFieldError(errors, "descriptionJson")}
|
||||||
helperText={errors.descriptionJson}
|
helperText={getFieldError(errors, "descriptionJson")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Category Description"
|
defaultMessage: "Category Description"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -75,7 +75,7 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
|
||||||
currentTab,
|
currentTab,
|
||||||
category,
|
category,
|
||||||
disabled,
|
disabled,
|
||||||
errors: userErrors,
|
errors,
|
||||||
pageInfo,
|
pageInfo,
|
||||||
products,
|
products,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
|
@ -115,13 +115,8 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
|
||||||
seoTitle: ""
|
seoTitle: ""
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form onSubmit={onSubmit} initial={initialData} confirmLeave>
|
||||||
onSubmit={onSubmit}
|
{({ data, change, submit, hasChanged }) => (
|
||||||
initial={initialData}
|
|
||||||
errors={userErrors}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ data, change, errors, submit, hasChanged }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.categories)}
|
{intl.formatMessage(sectionNames.categories)}
|
||||||
|
|
|
@ -68,8 +68,8 @@ const CollectionCreatePage: React.FC<CollectionCreatePageProps> = ({
|
||||||
const localizeDate = useDateLocalize();
|
const localizeDate = useDateLocalize();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.collections)}
|
{intl.formatMessage(sectionNames.collections)}
|
||||||
|
@ -85,7 +85,7 @@ const CollectionCreatePage: React.FC<CollectionCreatePageProps> = ({
|
||||||
<CollectionDetails
|
<CollectionDetails
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -147,7 +147,7 @@ const CollectionCreatePage: React.FC<CollectionCreatePageProps> = ({
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<VisibilityCard
|
<VisibilityCard
|
||||||
data={data}
|
data={data}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
hiddenMessage={intl.formatMessage(
|
hiddenMessage={intl.formatMessage(
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,8 @@ import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
||||||
|
|
||||||
export interface CollectionDetailsProps {
|
export interface CollectionDetailsProps {
|
||||||
|
@ -20,7 +21,7 @@ export interface CollectionDetailsProps {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"descriptionJson" | "name">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,14 +49,14 @@ const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.name}
|
value={data.name}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<RichTextEditor
|
<RichTextEditor
|
||||||
error={!!errors.descriptionJson}
|
error={!!getFieldError(errors, "descriptionJson")}
|
||||||
helperText={errors.descriptionJson}
|
helperText={getFieldError(errors, "descriptionJson")?.message}
|
||||||
initial={maybe(() => JSON.parse(collection.descriptionJson))}
|
initial={maybe(() => JSON.parse(collection.descriptionJson))}
|
||||||
label={intl.formatMessage(commonMessages.description)}
|
label={intl.formatMessage(commonMessages.description)}
|
||||||
name="description"
|
name="description"
|
||||||
|
|
|
@ -18,7 +18,7 @@ import VisibilityCard from "@saleor/components/VisibilityCard";
|
||||||
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
import useDateLocalize from "@saleor/hooks/useDateLocalize";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { ListActions, PageListProps } from "../../../types";
|
import { ListActions, PageListProps, UserError } from "../../../types";
|
||||||
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
import { CollectionDetails_collection } from "../../types/CollectionDetails";
|
||||||
import CollectionDetails from "../CollectionDetails/CollectionDetails";
|
import CollectionDetails from "../CollectionDetails/CollectionDetails";
|
||||||
import { CollectionImage } from "../CollectionImage/CollectionImage";
|
import { CollectionImage } from "../CollectionImage/CollectionImage";
|
||||||
|
@ -37,6 +37,7 @@ export interface CollectionDetailsPageFormData {
|
||||||
|
|
||||||
export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
||||||
collection: CollectionDetails_collection;
|
collection: CollectionDetails_collection;
|
||||||
|
errors: UserError[];
|
||||||
isFeatured: boolean;
|
isFeatured: boolean;
|
||||||
saveButtonBarState: ConfirmButtonTransitionState;
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
|
@ -50,6 +51,7 @@ export interface CollectionDetailsPageProps extends PageListProps, ListActions {
|
||||||
const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
||||||
collection,
|
collection,
|
||||||
disabled,
|
disabled,
|
||||||
|
errors,
|
||||||
isFeatured,
|
isFeatured,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
onBack,
|
onBack,
|
||||||
|
@ -77,7 +79,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
confirmLeave
|
confirmLeave
|
||||||
>
|
>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.collections)}
|
{intl.formatMessage(sectionNames.collections)}
|
||||||
|
@ -89,7 +91,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
||||||
collection={collection}
|
collection={collection}
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -124,7 +126,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
|
||||||
<div>
|
<div>
|
||||||
<VisibilityCard
|
<VisibilityCard
|
||||||
data={data}
|
data={data}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
hiddenMessage={intl.formatMessage(
|
hiddenMessage={intl.formatMessage(
|
||||||
{
|
{
|
||||||
|
|
|
@ -205,6 +205,9 @@ export const CollectionDetails: React.FC<CollectionDetailsProps> = ({
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
collection={maybe(() => data.collection)}
|
collection={maybe(() => data.collection)}
|
||||||
|
errors={
|
||||||
|
updateCollection.opts?.data?.collectionUpdate.errors || []
|
||||||
|
}
|
||||||
isFeatured={maybe(
|
isFeatured={maybe(
|
||||||
() =>
|
() =>
|
||||||
data.shop.homepageCollection.id === data.collection.id,
|
data.shop.homepageCollection.id === data.collection.id,
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import { AddressTypeInput } from "@saleor/customers/types";
|
import { AddressTypeInput } from "@saleor/customers/types";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import FormSpacer from "../FormSpacer";
|
import FormSpacer from "../FormSpacer";
|
||||||
import SingleAutocompleteSelectField, {
|
import SingleAutocompleteSelectField, {
|
||||||
SingleAutocompleteChoiceType
|
SingleAutocompleteChoiceType
|
||||||
|
@ -27,7 +28,7 @@ interface AddressEditProps {
|
||||||
countryDisplayValue: string;
|
countryDisplayValue: string;
|
||||||
data: AddressTypeInput;
|
data: AddressTypeInput;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
errors: FormErrors<keyof AddressTypeInput>;
|
errors: UserError[];
|
||||||
onChange(event: React.ChangeEvent<any>);
|
onChange(event: React.ChangeEvent<any>);
|
||||||
onCountryChange(event: React.ChangeEvent<any>);
|
onCountryChange(event: React.ChangeEvent<any>);
|
||||||
}
|
}
|
||||||
|
@ -52,8 +53,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.firstName}
|
error={!!getFieldError(errors, "firstName")}
|
||||||
helperText={errors.firstName}
|
helperText={getFieldError(errors, "firstName")?.message}
|
||||||
label={intl.formatMessage(commonMessages.firstName)}
|
label={intl.formatMessage(commonMessages.firstName)}
|
||||||
name="firstName"
|
name="firstName"
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
@ -64,8 +65,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.lastName}
|
error={!!getFieldError(errors, "lastName")}
|
||||||
helperText={errors.lastName}
|
helperText={getFieldError(errors, "lastName")?.message}
|
||||||
label={intl.formatMessage(commonMessages.lastName)}
|
label={intl.formatMessage(commonMessages.lastName)}
|
||||||
name="lastName"
|
name="lastName"
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
@ -79,8 +80,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.companyName}
|
error={!!getFieldError(errors, "companyName")}
|
||||||
helperText={errors.companyName}
|
helperText={getFieldError(errors, "companyName")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Company"
|
defaultMessage: "Company"
|
||||||
})}
|
})}
|
||||||
|
@ -93,9 +94,9 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.phone}
|
error={!!getFieldError(errors, "phone")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.phone}
|
helperText={getFieldError(errors, "phone")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Phone"
|
defaultMessage: "Phone"
|
||||||
})}
|
})}
|
||||||
|
@ -108,8 +109,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.streetAddress1}
|
error={!!getFieldError(errors, "streetAddress1")}
|
||||||
helperText={errors.streetAddress1}
|
helperText={getFieldError(errors, "streetAddress1")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Address line 1"
|
defaultMessage: "Address line 1"
|
||||||
})}
|
})}
|
||||||
|
@ -121,8 +122,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.streetAddress2}
|
error={!!getFieldError(errors, "streetAddress2")}
|
||||||
helperText={errors.streetAddress2}
|
helperText={getFieldError(errors, "streetAddress2")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Address line 2"
|
defaultMessage: "Address line 2"
|
||||||
})}
|
})}
|
||||||
|
@ -136,8 +137,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.city}
|
error={!!getFieldError(errors, "city")}
|
||||||
helperText={errors.city}
|
helperText={getFieldError(errors, "city")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "City"
|
defaultMessage: "City"
|
||||||
})}
|
})}
|
||||||
|
@ -150,8 +151,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.postalCode}
|
error={!!getFieldError(errors, "postalCode")}
|
||||||
helperText={errors.postalCode}
|
helperText={getFieldError(errors, "postalCode")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "ZIP / Postal code"
|
defaultMessage: "ZIP / Postal code"
|
||||||
})}
|
})}
|
||||||
|
@ -169,8 +170,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
displayValue={countryDisplayValue}
|
displayValue={countryDisplayValue}
|
||||||
error={!!errors.country}
|
error={!!getFieldError(errors, "country")}
|
||||||
helperText={errors.country}
|
helperText={getFieldError(errors, "country")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Country"
|
defaultMessage: "Country"
|
||||||
})}
|
})}
|
||||||
|
@ -186,8 +187,8 @@ const AddressEdit: React.FC<AddressEditProps> = props => {
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.countryArea}
|
error={!!getFieldError(errors, "countryArea")}
|
||||||
helperText={errors.countryArea}
|
helperText={getFieldError(errors, "countryArea")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Country area"
|
defaultMessage: "Country area"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -68,7 +68,7 @@ export const EditableTableCell: React.FC<EditableTableCellProps> = props => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const [opened, setOpenStatus] = React.useState(focused);
|
const [opened, setOpenStatus] = React.useState(focused);
|
||||||
const { change, data } = useForm({ value }, [], handleConfirm);
|
const { change, data } = useForm({ value }, handleConfirm);
|
||||||
const enable = () => setOpenStatus(true);
|
const enable = () => setOpenStatus(true);
|
||||||
const disable = () => setOpenStatus(false);
|
const disable = () => setOpenStatus(false);
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import useForm, { UseFormResult } from "@saleor/hooks/useForm";
|
import useForm, { UseFormResult } from "@saleor/hooks/useForm";
|
||||||
import { UserError } from "@saleor/types";
|
|
||||||
|
|
||||||
export interface FormProps<T> {
|
export interface FormProps<T> {
|
||||||
children: (props: UseFormResult<T>) => React.ReactNode;
|
children: (props: UseFormResult<T>) => React.ReactNode;
|
||||||
confirmLeave?: boolean;
|
confirmLeave?: boolean;
|
||||||
errors?: UserError[];
|
|
||||||
initial?: T;
|
initial?: T;
|
||||||
resetOnSubmit?: boolean;
|
resetOnSubmit?: boolean;
|
||||||
onSubmit?: (data: T) => void;
|
onSubmit?: (data: T) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Form<T>(props: FormProps<T>) {
|
function Form<T>(props: FormProps<T>) {
|
||||||
const { children, errors, initial, resetOnSubmit, onSubmit } = props;
|
const { children, initial, resetOnSubmit, onSubmit } = props;
|
||||||
const renderProps = useForm(initial, errors, onSubmit);
|
const renderProps = useForm(initial, onSubmit);
|
||||||
|
|
||||||
function handleSubmit(event?: React.FormEvent<any>, cb?: () => void) {
|
function handleSubmit(event?: React.FormEvent<any>, cb?: () => void) {
|
||||||
const { reset, submit } = renderProps;
|
const { reset, submit } = renderProps;
|
||||||
|
|
|
@ -8,7 +8,8 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import RadioSwitchField from "@saleor/components/RadioSwitchField";
|
import RadioSwitchField from "@saleor/components/RadioSwitchField";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { DateContext } from "../Date/DateContext";
|
import { DateContext } from "../Date/DateContext";
|
||||||
import FormSpacer from "../FormSpacer";
|
import FormSpacer from "../FormSpacer";
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ interface VisibilityCardProps {
|
||||||
isPublished: boolean;
|
isPublished: boolean;
|
||||||
publicationDate: string;
|
publicationDate: string;
|
||||||
};
|
};
|
||||||
errors: FormErrors<"isPublished" | "publicationDate">;
|
errors: UserError[];
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
hiddenMessage: string;
|
hiddenMessage: string;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
|
@ -62,7 +63,6 @@ interface VisibilityCardProps {
|
||||||
export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
||||||
const {
|
const {
|
||||||
children,
|
children,
|
||||||
|
|
||||||
data: { isPublished, publicationDate },
|
data: { isPublished, publicationDate },
|
||||||
errors,
|
errors,
|
||||||
disabled,
|
disabled,
|
||||||
|
@ -101,7 +101,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<RadioSwitchField
|
<RadioSwitchField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.isPublished}
|
error={!!getFieldError(errors, "isPublished")}
|
||||||
firstOptionLabel={
|
firstOptionLabel={
|
||||||
<>
|
<>
|
||||||
<p className={classes.label}>
|
<p className={classes.label}>
|
||||||
|
@ -140,7 +140,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
||||||
)}
|
)}
|
||||||
{isPublicationDate && (
|
{isPublicationDate && (
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.publicationDate}
|
error={!!getFieldError(errors, "publicationDate")}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Publish on",
|
defaultMessage: "Publish on",
|
||||||
|
@ -149,7 +149,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
||||||
name="publicationDate"
|
name="publicationDate"
|
||||||
type="date"
|
type="date"
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
helperText={errors.publicationDate}
|
helperText={getFieldError(errors, "publicationDate")?.message}
|
||||||
value={publicationDate ? publicationDate : ""}
|
value={publicationDate ? publicationDate : ""}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className={classes.date}
|
className={classes.date}
|
||||||
|
@ -160,10 +160,12 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{errors.isPublished && (
|
{getFieldError(errors, "isPublished") && (
|
||||||
<>
|
<>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<Typography color="error">{errors.isPublished}</Typography>
|
<Typography color="error">
|
||||||
|
{getFieldError(errors, "isPublished")?.message}
|
||||||
|
</Typography>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div className={classes.children}>{children}</div>
|
<div className={classes.children}>{children}</div>
|
||||||
|
|
|
@ -43,7 +43,10 @@ const styles = createStyles({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const CustomerAddressDialog = withStyles(styles, {})(
|
const CustomerAddressDialog = withStyles(
|
||||||
|
styles,
|
||||||
|
{}
|
||||||
|
)(
|
||||||
({
|
({
|
||||||
address,
|
address,
|
||||||
classes,
|
classes,
|
||||||
|
@ -98,12 +101,8 @@ const CustomerAddressDialog = withStyles(styles, {})(
|
||||||
fullWidth
|
fullWidth
|
||||||
maxWidth="sm"
|
maxWidth="sm"
|
||||||
>
|
>
|
||||||
<Form
|
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||||
initial={initialForm}
|
{({ change, data }) => {
|
||||||
errors={dialogErrors}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
>
|
|
||||||
{({ change, data, errors: formErrors }) => {
|
|
||||||
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
||||||
change,
|
change,
|
||||||
setCountryDisplayName,
|
setCountryDisplayName,
|
||||||
|
@ -130,7 +129,7 @@ const CustomerAddressDialog = withStyles(styles, {})(
|
||||||
countries={countryChoices}
|
countries={countryChoices}
|
||||||
data={data}
|
data={data}
|
||||||
countryDisplayValue={countryDisplayName}
|
countryDisplayValue={countryDisplayName}
|
||||||
errors={formErrors}
|
errors={dialogErrors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
onCountryChange={handleCountrySelect}
|
onCountryChange={handleCountrySelect}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -9,7 +9,7 @@ import AddressEdit from "@saleor/components/AddressEdit";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||||
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
|
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import { FormErrors } from "../../../types";
|
import { UserError } from "../../../types";
|
||||||
import { AddressTypeInput } from "../../types";
|
import { AddressTypeInput } from "../../types";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
|
@ -26,7 +26,7 @@ export interface CustomerCreateAddressProps {
|
||||||
countryDisplayName: string;
|
countryDisplayName: string;
|
||||||
data: AddressTypeInput;
|
data: AddressTypeInput;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<keyof AddressTypeInput>;
|
errors: UserError[];
|
||||||
onChange(event: React.ChangeEvent<any>);
|
onChange(event: React.ChangeEvent<any>);
|
||||||
onCountryChange(event: React.ChangeEvent<any>);
|
onCountryChange(event: React.ChangeEvent<any>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
import { CustomerCreatePageFormData } from "../CustomerCreatePage";
|
import { CustomerCreatePageFormData } from "../CustomerCreatePage";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
|
@ -25,7 +26,7 @@ const useStyles = makeStyles(
|
||||||
export interface CustomerCreateDetailsProps {
|
export interface CustomerCreateDetailsProps {
|
||||||
data: CustomerCreatePageFormData;
|
data: CustomerCreatePageFormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"customerFirstName" | "customerLastName" | "email">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,33 +48,33 @@ const CustomerCreateDetails: React.FC<CustomerCreateDetailsProps> = props => {
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.customerFirstName}
|
error={!!getFieldError(errors, "customerFirstName")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="customerFirstName"
|
name="customerFirstName"
|
||||||
label={intl.formatMessage(commonMessages.firstName)}
|
label={intl.formatMessage(commonMessages.firstName)}
|
||||||
helperText={errors.customerFirstName}
|
helperText={getFieldError(errors, "customerFirstName")?.message}
|
||||||
type="text"
|
type="text"
|
||||||
value={data.customerFirstName}
|
value={data.customerFirstName}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.customerLastName}
|
error={!!getFieldError(errors, "customerLastName")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="customerLastName"
|
name="customerLastName"
|
||||||
label={intl.formatMessage(commonMessages.lastName)}
|
label={intl.formatMessage(commonMessages.lastName)}
|
||||||
helperText={errors.customerLastName}
|
helperText={getFieldError(errors, "customerLastName")?.message}
|
||||||
type="text"
|
type="text"
|
||||||
value={data.customerLastName}
|
value={data.customerLastName}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.email}
|
error={!!getFieldError(errors, "email")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="email"
|
name="email"
|
||||||
label={intl.formatMessage(commonMessages.email)}
|
label={intl.formatMessage(commonMessages.email)}
|
||||||
helperText={errors.email}
|
helperText={getFieldError(errors, "email")?.message}
|
||||||
type="email"
|
type="email"
|
||||||
value={data.email}
|
value={data.email}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
|
@ -7,15 +7,15 @@ import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
export interface CustomerCreateNoteProps {
|
export interface CustomerCreateNoteProps {
|
||||||
data: {
|
data: {
|
||||||
note: string;
|
note: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: Partial<{
|
errors: UserError[];
|
||||||
note: string;
|
|
||||||
}>;
|
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ const CustomerCreateNote: React.FC<CustomerCreateNoteProps> = ({
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.note}
|
error={!!getFieldError(errors, "note")}
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
multiline
|
||||||
name="note"
|
name="note"
|
||||||
helperText={errors.note}
|
helperText={getFieldError(errors, "note")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Note",
|
defaultMessage: "Note",
|
||||||
description: "note about customer"
|
description: "note about customer"
|
||||||
|
|
|
@ -61,7 +61,7 @@ export interface CustomerCreatePageProps {
|
||||||
const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||||
countries,
|
countries,
|
||||||
disabled,
|
disabled,
|
||||||
errors,
|
errors: apiErrors,
|
||||||
saveButtonBar,
|
saveButtonBar,
|
||||||
onBack,
|
onBack,
|
||||||
onSubmit
|
onSubmit
|
||||||
|
@ -98,6 +98,8 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const errors = [...apiErrors, ...validationErrors];
|
||||||
|
|
||||||
const handleSubmit = (
|
const handleSubmit = (
|
||||||
formData: CustomerCreatePageFormData & AddressTypeInput
|
formData: CustomerCreatePageFormData & AddressTypeInput
|
||||||
) => {
|
) => {
|
||||||
|
@ -130,13 +132,8 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form initial={initialForm} onSubmit={handleSubmit} confirmLeave>
|
||||||
initial={initialForm}
|
{({ change, data, hasChanged, submit }) => {
|
||||||
onSubmit={handleSubmit}
|
|
||||||
errors={[...errors, ...validationErrors]}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => {
|
|
||||||
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
||||||
change,
|
change,
|
||||||
setCountryDisplayName,
|
setCountryDisplayName,
|
||||||
|
@ -159,7 +156,7 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||||
<CustomerCreateDetails
|
<CustomerCreateDetails
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -168,7 +165,7 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||||
countryDisplayName={countryDisplayName}
|
countryDisplayName={countryDisplayName}
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
onCountryChange={handleCountrySelect}
|
onCountryChange={handleCountrySelect}
|
||||||
/>
|
/>
|
||||||
|
@ -176,7 +173,7 @@ const CustomerCreatePage: React.FC<CustomerCreatePageProps> = ({
|
||||||
<CustomerCreateNote
|
<CustomerCreateNote
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { CustomerDetails_user } from "../../types/CustomerDetails";
|
import { CustomerDetails_user } from "../../types/CustomerDetails";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
|
@ -39,7 +40,7 @@ export interface CustomerDetailsProps {
|
||||||
note: string;
|
note: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"isActive" | "note">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +91,10 @@ const CustomerDetails: React.FC<CustomerDetailsProps> = props => {
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.note}
|
error={!!getFieldError(errors, "note")}
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
multiline
|
||||||
helperText={errors.note}
|
helperText={getFieldError(errors, "note")?.message}
|
||||||
name="note"
|
name="note"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Note",
|
defaultMessage: "Note",
|
||||||
|
|
|
@ -56,7 +56,6 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
errors={errors}
|
|
||||||
initial={{
|
initial={{
|
||||||
email: maybe(() => customer.email, ""),
|
email: maybe(() => customer.email, ""),
|
||||||
firstName: maybe(() => customer.firstName, ""),
|
firstName: maybe(() => customer.firstName, ""),
|
||||||
|
@ -67,7 +66,7 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
confirmLeave
|
confirmLeave
|
||||||
>
|
>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.customers)}
|
{intl.formatMessage(sectionNames.customers)}
|
||||||
|
@ -79,14 +78,14 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
||||||
customer={customer}
|
customer={customer}
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<CustomerInfo
|
<CustomerInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -10,6 +10,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import Hr from "@saleor/components/Hr";
|
import Hr from "@saleor/components/Hr";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
|
@ -33,11 +35,7 @@ export interface CustomerInfoProps {
|
||||||
email: string;
|
email: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: {
|
errors: UserError[];
|
||||||
firstName?: string;
|
|
||||||
lastName?: string;
|
|
||||||
email?: string;
|
|
||||||
};
|
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +62,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
|
||||||
<Grid variant="uniform">
|
<Grid variant="uniform">
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.firstName}
|
error={!!getFieldError(errors, "firstName")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.firstName}
|
helperText={getFieldError(errors, "firstName")?.message}
|
||||||
name="firstName"
|
name="firstName"
|
||||||
type="text"
|
type="text"
|
||||||
label={intl.formatMessage(commonMessages.firstName)}
|
label={intl.formatMessage(commonMessages.firstName)}
|
||||||
|
@ -75,9 +73,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.lastName}
|
error={!!getFieldError(errors, "lastName")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.lastName}
|
helperText={getFieldError(errors, "lastName")?.message}
|
||||||
name="lastName"
|
name="lastName"
|
||||||
type="text"
|
type="text"
|
||||||
label={intl.formatMessage(commonMessages.lastName)}
|
label={intl.formatMessage(commonMessages.lastName)}
|
||||||
|
@ -94,9 +92,9 @@ const CustomerInfo: React.FC<CustomerInfoProps> = props => {
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.email}
|
error={!!getFieldError(errors, "email")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.email}
|
helperText={getFieldError(errors, "email")?.message}
|
||||||
name="email"
|
name="email"
|
||||||
type="email"
|
type="email"
|
||||||
label={intl.formatMessage(commonMessages.email)}
|
label={intl.formatMessage(commonMessages.email)}
|
||||||
|
|
|
@ -8,7 +8,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
|
|
||||||
interface DiscountDatesProps {
|
interface DiscountDatesProps {
|
||||||
data: {
|
data: {
|
||||||
|
@ -20,7 +21,7 @@ interface DiscountDatesProps {
|
||||||
};
|
};
|
||||||
defaultCurrency: string;
|
defaultCurrency: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"endDate" | "startDate">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +45,8 @@ const DiscountDates = ({
|
||||||
<Grid variant="uniform">
|
<Grid variant="uniform">
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.startDate}
|
error={!!getFieldError(errors, "startDate")}
|
||||||
helperText={errors.startDate}
|
helperText={getFieldError(errors, "startDate")?.message}
|
||||||
name={"startDate" as keyof FormData}
|
name={"startDate" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.startDate)}
|
label={intl.formatMessage(commonMessages.startDate)}
|
||||||
|
@ -58,8 +59,8 @@ const DiscountDates = ({
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.startDate}
|
error={!!getFieldError(errors, "startDate")}
|
||||||
helperText={errors.startDate}
|
helperText={getFieldError(errors, "startDate")?.message}
|
||||||
name={"startTime" as keyof FormData}
|
name={"startTime" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.startHour)}
|
label={intl.formatMessage(commonMessages.startHour)}
|
||||||
|
@ -84,8 +85,8 @@ const DiscountDates = ({
|
||||||
<Grid variant="uniform">
|
<Grid variant="uniform">
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.endDate}
|
error={!!getFieldError(errors, "endDate")}
|
||||||
helperText={errors.endDate}
|
helperText={getFieldError(errors, "endDate")?.message}
|
||||||
name={"endDate" as keyof FormData}
|
name={"endDate" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.endDate)}
|
label={intl.formatMessage(commonMessages.endDate)}
|
||||||
|
@ -98,8 +99,8 @@ const DiscountDates = ({
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.endDate}
|
error={!!getFieldError(errors, "endDate")}
|
||||||
helperText={errors.endDate}
|
helperText={getFieldError(errors, "endDate")?.message}
|
||||||
name={"endTime" as keyof FormData}
|
name={"endTime" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.endHour)}
|
label={intl.formatMessage(commonMessages.endHour)}
|
||||||
|
|
|
@ -57,8 +57,8 @@ const SaleCreatePage: React.FC<SaleCreatePageProps> = ({
|
||||||
value: ""
|
value: ""
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.sales)}
|
{intl.formatMessage(sectionNames.sales)}
|
||||||
|
@ -74,7 +74,7 @@ const SaleCreatePage: React.FC<SaleCreatePageProps> = ({
|
||||||
<SaleInfo
|
<SaleInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -84,7 +84,7 @@ const SaleCreatePage: React.FC<SaleCreatePageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -121,8 +121,8 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
||||||
value: maybe(() => sale.value.toString(), "")
|
value: maybe(() => sale.value.toString(), "")
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.sales)}
|
{intl.formatMessage(sectionNames.sales)}
|
||||||
|
@ -133,7 +133,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
||||||
<SaleInfo
|
<SaleInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -143,7 +143,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
||||||
currencySymbol={defaultCurrency}
|
currencySymbol={defaultCurrency}
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -258,7 +258,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,14 +6,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 { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { FormData } from "../SaleDetailsPage";
|
import { FormData } from "../SaleDetailsPage";
|
||||||
|
|
||||||
export interface SaleInfoProps {
|
export interface SaleInfoProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: {
|
errors: UserError[];
|
||||||
name?: string;
|
|
||||||
};
|
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ const SaleInfo: React.FC<SaleInfoProps> = ({
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
name={"name" as keyof FormData}
|
name={"name" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
|
|
@ -6,15 +6,16 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { FormChange } from "@saleor/hooks/useForm";
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
import { SaleType } from "@saleor/types/globalTypes";
|
import { SaleType } from "@saleor/types/globalTypes";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { FormData } from "../SaleDetailsPage";
|
import { FormData } from "../SaleDetailsPage";
|
||||||
|
|
||||||
export interface SaleValueProps {
|
export interface SaleValueProps {
|
||||||
currencySymbol: string;
|
currencySymbol: string;
|
||||||
data: FormData;
|
data: FormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"value">;
|
errors: UserError[];
|
||||||
onChange: FormChange;
|
onChange: FormChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,12 +44,12 @@ const SaleValue: React.FC<SaleValueProps> = ({
|
||||||
defaultMessage: "Discount Value",
|
defaultMessage: "Discount Value",
|
||||||
description: "sale discount"
|
description: "sale discount"
|
||||||
})}
|
})}
|
||||||
error={!!errors.value}
|
error={!!getFieldError(errors, "value")}
|
||||||
name="value"
|
name="value"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: data.type === SaleType.FIXED ? currencySymbol : "%"
|
endAdornment: data.type === SaleType.FIXED ? currencySymbol : "%"
|
||||||
}}
|
}}
|
||||||
helperText={errors.value}
|
helperText={getFieldError(errors, "value")?.message}
|
||||||
value={data.value}
|
value={data.value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -81,8 +81,8 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.vouchers)}
|
{intl.formatMessage(sectionNames.vouchers)}
|
||||||
|
@ -97,7 +97,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
<div>
|
<div>
|
||||||
<VoucherInfo
|
<VoucherInfo
|
||||||
data={data}
|
data={data}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
variant="create"
|
variant="create"
|
||||||
|
@ -106,7 +106,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
<VoucherTypes
|
<VoucherTypes
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
{data.discountType.toString() !== "SHIPPING" ? (
|
{data.discountType.toString() !== "SHIPPING" ? (
|
||||||
|
@ -114,7 +114,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
variant="create"
|
variant="create"
|
||||||
/>
|
/>
|
||||||
|
@ -124,7 +124,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -132,7 +132,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -140,7 +140,7 @@ const VoucherCreatePage: React.FC<VoucherCreatePageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,14 +8,15 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
import { FormData } from "../VoucherDetailsPage";
|
import { FormData } from "../VoucherDetailsPage";
|
||||||
|
|
||||||
interface VoucherDatesProps {
|
interface VoucherDatesProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
defaultCurrency: string;
|
defaultCurrency: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"endDate" | "startDate">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +40,8 @@ const VoucherDates = ({
|
||||||
<Grid variant="uniform">
|
<Grid variant="uniform">
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.startDate}
|
error={!!getFieldError(errors, "startDate")}
|
||||||
helperText={errors.startDate}
|
helperText={getFieldError(errors, "startDate")?.message}
|
||||||
name={"startDate" as keyof FormData}
|
name={"startDate" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.startDate)}
|
label={intl.formatMessage(commonMessages.startDate)}
|
||||||
|
@ -53,8 +54,8 @@ const VoucherDates = ({
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.startDate}
|
error={!!getFieldError(errors, "startDate")}
|
||||||
helperText={errors.startDate}
|
helperText={getFieldError(errors, "startDate")?.message}
|
||||||
name={"startTime" as keyof FormData}
|
name={"startTime" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.startHour)}
|
label={intl.formatMessage(commonMessages.startHour)}
|
||||||
|
@ -79,8 +80,8 @@ const VoucherDates = ({
|
||||||
<Grid variant="uniform">
|
<Grid variant="uniform">
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.endDate}
|
error={!!getFieldError(errors, "endDate")}
|
||||||
helperText={errors.endDate}
|
helperText={getFieldError(errors, "endDate")?.message}
|
||||||
name={"endDate" as keyof FormData}
|
name={"endDate" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.endDate)}
|
label={intl.formatMessage(commonMessages.endDate)}
|
||||||
|
@ -93,8 +94,8 @@ const VoucherDates = ({
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.endDate}
|
error={!!getFieldError(errors, "endDate")}
|
||||||
helperText={errors.endDate}
|
helperText={getFieldError(errors, "endDate")?.message}
|
||||||
name={"endTime" as keyof FormData}
|
name={"endTime" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage(commonMessages.endHour)}
|
label={intl.formatMessage(commonMessages.endHour)}
|
||||||
|
|
|
@ -166,8 +166,8 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.vouchers)}
|
{intl.formatMessage(sectionNames.vouchers)}
|
||||||
|
@ -178,7 +178,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
<VoucherInfo
|
<VoucherInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
variant="update"
|
variant="update"
|
||||||
/>
|
/>
|
||||||
|
@ -186,7 +186,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
<VoucherTypes
|
<VoucherTypes
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -195,7 +195,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
variant="update"
|
variant="update"
|
||||||
/>
|
/>
|
||||||
|
@ -337,7 +337,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -345,7 +345,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
@ -353,7 +353,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
defaultCurrency={defaultCurrency}
|
defaultCurrency={defaultCurrency}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,13 +7,14 @@ import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { generateCode } from "../../../misc";
|
import { generateCode } from "../../../misc";
|
||||||
import { FormErrors } from "../../../types";
|
import { UserError } from "../../../types";
|
||||||
import { FormData } from "../VoucherDetailsPage";
|
import { FormData } from "../VoucherDetailsPage";
|
||||||
|
|
||||||
interface VoucherInfoProps {
|
interface VoucherInfoProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
errors: FormErrors<"code">;
|
errors: UserError[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
variant: "create" | "update";
|
variant: "create" | "update";
|
||||||
onChange: (event: any) => void;
|
onChange: (event: any) => void;
|
||||||
|
@ -54,9 +55,9 @@ const VoucherInfo = ({
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={variant === "update" || disabled}
|
disabled={variant === "update" || disabled}
|
||||||
error={!!errors.code}
|
error={!!getFieldError(errors, "code")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.code}
|
helperText={getFieldError(errors, "code")?.message}
|
||||||
name={"code" as keyof FormData}
|
name={"code" as keyof FormData}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Discount Code"
|
defaultMessage: "Discount Code"
|
||||||
|
|
|
@ -6,14 +6,15 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||||
import { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
import { FormData } from "../VoucherDetailsPage";
|
import { FormData } from "../VoucherDetailsPage";
|
||||||
|
|
||||||
interface VoucherLimitsProps {
|
interface VoucherLimitsProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
defaultCurrency: string;
|
defaultCurrency: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"usageLimit">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +47,8 @@ const VoucherLimits = ({
|
||||||
{data.hasUsageLimit && (
|
{data.hasUsageLimit && (
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.usageLimit}
|
error={!!getFieldError(errors, "usageLimit")}
|
||||||
helperText={errors.usageLimit}
|
helperText={getFieldError(errors, "usageLimit")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Limit of Uses",
|
defaultMessage: "Limit of Uses",
|
||||||
description: "voucher"
|
description: "voucher"
|
||||||
|
|
|
@ -8,14 +8,15 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||||
import { RequirementsPicker } from "@saleor/discounts/types";
|
import { RequirementsPicker } from "@saleor/discounts/types";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { FormData } from "../VoucherDetailsPage";
|
import { FormData } from "../VoucherDetailsPage";
|
||||||
|
|
||||||
interface VoucherRequirementsProps {
|
interface VoucherRequirementsProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
defaultCurrency: string;
|
defaultCurrency: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"minSpent" | "minCheckoutItemsQuantity">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +77,8 @@ const VoucherRequirements = ({
|
||||||
{data.requirementsPicker === RequirementsPicker.ORDER ? (
|
{data.requirementsPicker === RequirementsPicker.ORDER ? (
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.minSpent}
|
error={!!getFieldError(errors, "minSpent")}
|
||||||
helperText={errors.minSpent}
|
helperText={getFieldError(errors, "minSpent")?.message}
|
||||||
label={minimalOrderValueText}
|
label={minimalOrderValueText}
|
||||||
name={"minSpent" as keyof FormData}
|
name={"minSpent" as keyof FormData}
|
||||||
value={data.minSpent}
|
value={data.minSpent}
|
||||||
|
@ -87,8 +88,10 @@ const VoucherRequirements = ({
|
||||||
) : data.requirementsPicker === RequirementsPicker.ITEM ? (
|
) : data.requirementsPicker === RequirementsPicker.ITEM ? (
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.minCheckoutItemsQuantity}
|
error={!!getFieldError(errors, "minCheckoutItemsQuantity")}
|
||||||
helperText={errors.minCheckoutItemsQuantity}
|
helperText={
|
||||||
|
getFieldError(errors, "minCheckoutItemsQuantity")?.message
|
||||||
|
}
|
||||||
label={minimalQuantityText}
|
label={minimalQuantityText}
|
||||||
name={"minCheckoutItemsQuantity" as keyof FormData}
|
name={"minCheckoutItemsQuantity" as keyof FormData}
|
||||||
value={data.minCheckoutItemsQuantity}
|
value={data.minCheckoutItemsQuantity}
|
||||||
|
|
|
@ -6,13 +6,14 @@ import { useIntl } from "react-intl";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||||
import { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
||||||
import { FormData } from "../VoucherDetailsPage";
|
import { FormData } from "../VoucherDetailsPage";
|
||||||
|
|
||||||
interface VoucherTypesProps {
|
interface VoucherTypesProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
errors: FormErrors<"discountType">;
|
errors: UserError[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
@ -62,8 +63,8 @@ const VoucherTypes = ({
|
||||||
<RadioGroupField
|
<RadioGroupField
|
||||||
choices={voucherTypeChoices}
|
choices={voucherTypeChoices}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.discountType}
|
error={!!getFieldError(errors, "discountType")}
|
||||||
hint={errors.discountType}
|
hint={getFieldError(errors, "discountType")?.message}
|
||||||
name={"discountType" as keyof FormData}
|
name={"discountType" as keyof FormData}
|
||||||
value={data.discountType}
|
value={data.discountType}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
|
@ -11,7 +11,8 @@ import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||||
import Hr from "@saleor/components/Hr";
|
import Hr from "@saleor/components/Hr";
|
||||||
import RadioGroupField from "@saleor/components/RadioGroupField";
|
import RadioGroupField from "@saleor/components/RadioGroupField";
|
||||||
import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice";
|
import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice";
|
||||||
import { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
|
||||||
import { translateVoucherTypes } from "../../translations";
|
import { translateVoucherTypes } from "../../translations";
|
||||||
import { FormData } from "../VoucherDetailsPage";
|
import { FormData } from "../VoucherDetailsPage";
|
||||||
|
@ -19,7 +20,7 @@ import { FormData } from "../VoucherDetailsPage";
|
||||||
interface VoucherValueProps {
|
interface VoucherValueProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
defaultCurrency: string;
|
defaultCurrency: string;
|
||||||
errors: FormErrors<"discountValue" | "type">;
|
errors: UserError[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
variant: string;
|
variant: string;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
|
@ -64,7 +65,7 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextFieldWithChoice
|
<TextFieldWithChoice
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.discountValue}
|
error={!!getFieldError(errors, "discountValue")}
|
||||||
ChoiceProps={{
|
ChoiceProps={{
|
||||||
label:
|
label:
|
||||||
data.discountType === DiscountValueTypeEnum.FIXED
|
data.discountType === DiscountValueTypeEnum.FIXED
|
||||||
|
@ -73,7 +74,7 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
|
||||||
name: "discountType" as keyof FormData,
|
name: "discountType" as keyof FormData,
|
||||||
values: null
|
values: null
|
||||||
}}
|
}}
|
||||||
helperText={errors.discountValue}
|
helperText={getFieldError(errors, "discountValue")?.message}
|
||||||
name={"value" as keyof FormData}
|
name={"value" as keyof FormData}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
@ -93,8 +94,8 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
|
||||||
<RadioGroupField
|
<RadioGroupField
|
||||||
choices={voucherTypeChoices}
|
choices={voucherTypeChoices}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.type}
|
error={!!getFieldError(errors, "type")}
|
||||||
hint={errors.type}
|
hint={getFieldError(errors, "type")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Voucher Specific Information"
|
defaultMessage: "Voucher Specific Information"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import isEqual from "lodash-es/isEqual";
|
import isEqual from "lodash-es/isEqual";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { UserError } from "@saleor/types";
|
|
||||||
import { toggle } from "@saleor/utils/lists";
|
import { toggle } from "@saleor/utils/lists";
|
||||||
import useStateFromProps from "./useStateFromProps";
|
import useStateFromProps from "./useStateFromProps";
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ export type FormChange = (event: ChangeEvent, cb?: () => void) => void;
|
||||||
export interface UseFormResult<T> {
|
export interface UseFormResult<T> {
|
||||||
change: FormChange;
|
change: FormChange;
|
||||||
data: T;
|
data: T;
|
||||||
errors: Record<string, string>;
|
|
||||||
hasChanged: boolean;
|
hasChanged: boolean;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
set: (data: T) => void;
|
set: (data: T) => void;
|
||||||
|
@ -26,21 +24,6 @@ export interface UseFormResult<T> {
|
||||||
toggleValue: FormChange;
|
toggleValue: FormChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseErrors(errors: UserError[]): Record<string, string> {
|
|
||||||
return errors
|
|
||||||
? errors.reduce(
|
|
||||||
(acc, curr) =>
|
|
||||||
curr.field
|
|
||||||
? {
|
|
||||||
...acc,
|
|
||||||
[curr.field.split(":")[0]]: curr.message
|
|
||||||
}
|
|
||||||
: acc,
|
|
||||||
{}
|
|
||||||
)
|
|
||||||
: {};
|
|
||||||
}
|
|
||||||
|
|
||||||
type FormData = Record<string, any | any[]>;
|
type FormData = Record<string, any | any[]>;
|
||||||
|
|
||||||
function merge<T extends FormData>(prevData: T, prevState: T, data: T): T {
|
function merge<T extends FormData>(prevData: T, prevState: T, data: T): T {
|
||||||
|
@ -68,7 +51,6 @@ function handleRefresh<T extends FormData>(
|
||||||
|
|
||||||
function useForm<T extends FormData>(
|
function useForm<T extends FormData>(
|
||||||
initial: T,
|
initial: T,
|
||||||
errors: UserError[],
|
|
||||||
onSubmit: (data: T) => void
|
onSubmit: (data: T) => void
|
||||||
): UseFormResult<T> {
|
): UseFormResult<T> {
|
||||||
const [hasChanged, setChanged] = useState(false);
|
const [hasChanged, setChanged] = useState(false);
|
||||||
|
@ -135,7 +117,6 @@ function useForm<T extends FormData>(
|
||||||
return {
|
return {
|
||||||
change,
|
change,
|
||||||
data,
|
data,
|
||||||
errors: parseErrors(errors),
|
|
||||||
hasChanged,
|
hasChanged,
|
||||||
reset,
|
reset,
|
||||||
set,
|
set,
|
||||||
|
|
|
@ -12,6 +12,8 @@ import ConfirmButton, {
|
||||||
} from "@saleor/components/ConfirmButton";
|
} from "@saleor/components/ConfirmButton";
|
||||||
import Form from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
|
||||||
export interface MenuCreateDialogFormData {
|
export interface MenuCreateDialogFormData {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -20,6 +22,7 @@ export interface MenuCreateDialogFormData {
|
||||||
export interface MenuCreateDialogProps {
|
export interface MenuCreateDialogProps {
|
||||||
confirmButtonState: ConfirmButtonTransitionState;
|
confirmButtonState: ConfirmButtonTransitionState;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
errors: UserError[];
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onConfirm: (data: MenuCreateDialogFormData) => void;
|
onConfirm: (data: MenuCreateDialogFormData) => void;
|
||||||
|
@ -32,6 +35,7 @@ const initialForm: MenuCreateDialogFormData = {
|
||||||
const MenuCreateDialog: React.FC<MenuCreateDialogProps> = ({
|
const MenuCreateDialog: React.FC<MenuCreateDialogProps> = ({
|
||||||
confirmButtonState,
|
confirmButtonState,
|
||||||
disabled,
|
disabled,
|
||||||
|
errors,
|
||||||
onClose,
|
onClose,
|
||||||
onConfirm,
|
onConfirm,
|
||||||
open
|
open
|
||||||
|
@ -48,14 +52,14 @@ const MenuCreateDialog: React.FC<MenuCreateDialogProps> = ({
|
||||||
/>
|
/>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<Form initial={initialForm} onSubmit={onConfirm}>
|
<Form initial={initialForm} onSubmit={onConfirm}>
|
||||||
{({ change, data, errors: formErrors, submit }) => (
|
{({ change, data, submit }) => (
|
||||||
<>
|
<>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!formErrors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={formErrors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Menu Title",
|
defaultMessage: "Menu Title",
|
||||||
id: "menuCreateDialogMenuTitleLabel"
|
id: "menuCreateDialogMenuTitleLabel"
|
||||||
|
|
|
@ -253,7 +253,7 @@ const MenuItemDialog: React.FC<MenuItemDialogProps> = ({
|
||||||
}
|
}
|
||||||
name="name"
|
name="name"
|
||||||
error={!!getFieldError(errors, "name")}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={getFieldError(errors, "name")}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<AutocompleteSelectMenu
|
<AutocompleteSelectMenu
|
||||||
|
@ -269,7 +269,7 @@ const MenuItemDialog: React.FC<MenuItemDialogProps> = ({
|
||||||
loading={loading}
|
loading={loading}
|
||||||
options={options}
|
options={options}
|
||||||
error={!!idError}
|
error={!!idError}
|
||||||
helperText={idError}
|
helperText={idError?.message}
|
||||||
placeholder={intl.formatMessage({
|
placeholder={intl.formatMessage({
|
||||||
defaultMessage: "Start typing to begin search...",
|
defaultMessage: "Start typing to begin search...",
|
||||||
id: "menuItemDialogLinkPlaceholder"
|
id: "menuItemDialogLinkPlaceholder"
|
||||||
|
|
|
@ -174,6 +174,7 @@ const MenuList: React.FC<MenuListProps> = ({ params }) => {
|
||||||
open={params.action === "add"}
|
open={params.action === "add"}
|
||||||
confirmButtonState={menuCreateOpts.status}
|
confirmButtonState={menuCreateOpts.status}
|
||||||
disabled={menuCreateOpts.loading}
|
disabled={menuCreateOpts.loading}
|
||||||
|
errors={menuCreateOpts?.data?.menuCreate.errors || []}
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
onConfirm={formData =>
|
onConfirm={formData =>
|
||||||
menuCreate({
|
menuCreate({
|
||||||
|
|
|
@ -80,8 +80,8 @@ const OrderAddressEditDialog: React.FC<OrderAddressEditDialogProps> = props => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} open={open} classes={{ paper: classes.overflow }}>
|
<Dialog onClose={onClose} open={open} classes={{ paper: classes.overflow }}>
|
||||||
<Form initial={address} errors={dialogErrors} onSubmit={handleSubmit}>
|
<Form initial={address} onSubmit={handleSubmit}>
|
||||||
{({ change, data, errors, submit }) => {
|
{({ change, data, submit }) => {
|
||||||
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
const handleCountrySelect = createSingleAutocompleteSelectHandler(
|
||||||
change,
|
change,
|
||||||
setCountryDisplayName,
|
setCountryDisplayName,
|
||||||
|
@ -106,7 +106,7 @@ const OrderAddressEditDialog: React.FC<OrderAddressEditDialogProps> = props => {
|
||||||
countries={countryChoices}
|
countries={countryChoices}
|
||||||
countryDisplayValue={countryDisplayName}
|
countryDisplayValue={countryDisplayName}
|
||||||
data={data}
|
data={data}
|
||||||
errors={errors}
|
errors={dialogErrors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
onCountryChange={handleCountrySelect}
|
onCountryChange={handleCountrySelect}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -70,8 +70,8 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
||||||
title: maybe(() => page.title, "")
|
title: maybe(() => page.title, "")
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.pages)}
|
{intl.formatMessage(sectionNames.pages)}
|
||||||
|
@ -91,7 +91,7 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
||||||
<PageInfo
|
<PageInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
page={page}
|
page={page}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
|
@ -119,13 +119,13 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
||||||
<PageSlug
|
<PageSlug
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<VisibilityCard
|
<VisibilityCard
|
||||||
data={data}
|
data={data}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
hiddenMessage={intl.formatMessage(
|
hiddenMessage={intl.formatMessage(
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,15 +9,16 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { FormErrors } from "../../../types";
|
import { UserError } from "../../../types";
|
||||||
import { PageDetails_page } from "../../types/PageDetails";
|
import { PageDetails_page } from "../../types/PageDetails";
|
||||||
import { FormData } from "../PageDetailsPage";
|
import { FormData } from "../PageDetailsPage";
|
||||||
|
|
||||||
export interface PageInfoProps {
|
export interface PageInfoProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"contentJson" | "title">;
|
errors: UserError[];
|
||||||
page: PageDetails_page;
|
page: PageDetails_page;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
@ -45,9 +46,9 @@ const PageInfo: React.FC<PageInfoProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.title}
|
error={!!getFieldError(errors, "title")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.title}
|
helperText={getFieldError(errors, "title")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Title",
|
defaultMessage: "Title",
|
||||||
description: "page title"
|
description: "page title"
|
||||||
|
@ -59,8 +60,8 @@ const PageInfo: React.FC<PageInfoProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<RichTextEditor
|
<RichTextEditor
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.contentJson}
|
error={!!getFieldError(errors, "contentJson")}
|
||||||
helperText={errors.contentJson}
|
helperText={getFieldError(errors, "contentJson")?.message}
|
||||||
initial={maybe(() => JSON.parse(page.contentJson))}
|
initial={maybe(() => JSON.parse(page.contentJson))}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Content",
|
defaultMessage: "Content",
|
||||||
|
|
|
@ -6,12 +6,14 @@ import { useIntl } from "react-intl";
|
||||||
import slugify from "slugify";
|
import slugify from "slugify";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { FormData } from "../PageDetailsPage";
|
import { FormData } from "../PageDetailsPage";
|
||||||
|
|
||||||
export interface PageSlugProps {
|
export interface PageSlugProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: Partial<Record<"slug", string>>;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +36,13 @@ const PageSlug: React.FC<PageSlugProps> = ({
|
||||||
<TextField
|
<TextField
|
||||||
name={"slug" as keyof FormData}
|
name={"slug" as keyof FormData}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.slug}
|
error={!!getFieldError(errors, "slug")}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Slug",
|
defaultMessage: "Slug",
|
||||||
description: "page internal name"
|
description: "page internal name"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
errors.slug ||
|
getFieldError(errors, "slug")?.message ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"If empty, URL will be autogenerated from Page Name"
|
"If empty, URL will be autogenerated from Page Name"
|
||||||
|
|
|
@ -4,17 +4,18 @@ import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||||
import TextField from "@material-ui/core/TextField";
|
import TextField from "@material-ui/core/TextField";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
|
import { ConfigurationTypeFieldEnum } from "@saleor/types/globalTypes";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin";
|
import { Plugin_plugin_configuration } from "@saleor/plugins/types/Plugin";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { FormData } from "../PluginsDetailsPage";
|
import { FormData } from "../PluginsDetailsPage";
|
||||||
|
|
||||||
interface PluginSettingsProps {
|
interface PluginSettingsProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
errors: FormErrors<"name" | "configuration">;
|
errors: UserError[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
fields: Plugin_plugin_configuration[];
|
fields: Plugin_plugin_configuration[];
|
||||||
|
@ -84,7 +85,7 @@ const PluginSettings: React.FC<PluginSettingsProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={fieldData.helpText}
|
helperText={fieldData.helpText}
|
||||||
label={fieldData.label}
|
label={fieldData.label}
|
||||||
name={field.name}
|
name={field.name}
|
||||||
|
|
|
@ -77,8 +77,8 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = props => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ data, errors, hasChanged, submit, set, triggerChange }) => {
|
{({ data, hasChanged, submit, set, triggerChange }) => {
|
||||||
const onChange = (event: ChangeEvent) => {
|
const onChange = (event: ChangeEvent) => {
|
||||||
const { name, value } = event.target;
|
const { name, value } = event.target;
|
||||||
const newData = {
|
const newData = {
|
||||||
|
|
|
@ -11,6 +11,8 @@ import Form from "@saleor/components/Form";
|
||||||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||||
import ListField from "@saleor/components/ListField";
|
import ListField from "@saleor/components/ListField";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
export interface FormData {
|
export interface FormData {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -22,10 +24,7 @@ export interface FormData {
|
||||||
|
|
||||||
export interface ProductTypeAttributeEditDialogProps {
|
export interface ProductTypeAttributeEditDialogProps {
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: Array<{
|
errors: UserError[];
|
||||||
field: string;
|
|
||||||
message: string;
|
|
||||||
}>;
|
|
||||||
name: string;
|
name: string;
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -37,9 +36,16 @@ export interface ProductTypeAttributeEditDialogProps {
|
||||||
onConfirm: (data: FormData) => void;
|
onConfirm: (data: FormData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductTypeAttributeEditDialog: React.FC<
|
const ProductTypeAttributeEditDialog: React.FC<ProductTypeAttributeEditDialogProps> = ({
|
||||||
ProductTypeAttributeEditDialogProps
|
disabled,
|
||||||
> = ({ disabled, errors, name, opened, title, values, onClose, onConfirm }) => {
|
errors,
|
||||||
|
name,
|
||||||
|
opened,
|
||||||
|
title,
|
||||||
|
values,
|
||||||
|
onClose,
|
||||||
|
onConfirm
|
||||||
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const initialForm: FormData = {
|
const initialForm: FormData = {
|
||||||
|
@ -48,19 +54,19 @@ const ProductTypeAttributeEditDialog: React.FC<
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} open={opened}>
|
<Dialog onClose={onClose} open={opened}>
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onConfirm}>
|
<Form initial={initialForm} onSubmit={onConfirm}>
|
||||||
{({ change, data, errors: formErrors }) => (
|
{({ change, data }) => (
|
||||||
<>
|
<>
|
||||||
<DialogTitle>{title}</DialogTitle>
|
<DialogTitle>{title}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!formErrors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
fullWidth
|
fullWidth
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Attribute name"
|
defaultMessage: "Attribute name"
|
||||||
})}
|
})}
|
||||||
helperText={formErrors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
name="name"
|
name="name"
|
||||||
value={data.name}
|
value={data.name}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
|
@ -70,9 +76,9 @@ const ProductTypeAttributeEditDialog: React.FC<
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={
|
error={
|
||||||
!!formErrors.values ||
|
!!getFieldError(errors, "values") ||
|
||||||
!!formErrors.addValues ||
|
!!getFieldError(errors, "addValues") ||
|
||||||
!!formErrors.removeValues
|
!!getFieldError(errors, "removeValues")
|
||||||
}
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="values"
|
name="values"
|
||||||
|
@ -80,9 +86,9 @@ const ProductTypeAttributeEditDialog: React.FC<
|
||||||
defaultMessage: "Attribute values"
|
defaultMessage: "Attribute values"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
formErrors.values ||
|
getFieldError(errors, "values") ||
|
||||||
formErrors.addValues ||
|
getFieldError(errors, "addValues") ||
|
||||||
formErrors.removeValues
|
getFieldError(errors, "removeValues")
|
||||||
}
|
}
|
||||||
values={data.values}
|
values={data.values}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
|
|
|
@ -70,13 +70,8 @@ const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
||||||
const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps("");
|
const [taxTypeDisplayName, setTaxTypeDisplayName] = useStateFromProps("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form initial={formInitialData} onSubmit={onSubmit} confirmLeave>
|
||||||
errors={errors}
|
{({ change, data, hasChanged, submit }) => (
|
||||||
initial={formInitialData}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.productTypes)}
|
{intl.formatMessage(sectionNames.productTypes)}
|
||||||
|
@ -87,7 +82,7 @@ const ProductTypeCreatePage: React.FC<ProductTypeCreatePageProps> = ({
|
||||||
<ProductTypeDetails
|
<ProductTypeDetails
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -7,7 +7,8 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
{
|
{
|
||||||
|
@ -23,7 +24,7 @@ interface ProductTypeDetailsProps {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"name">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +42,9 @@ const ProductTypeDetails: React.FC<ProductTypeDetailsProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Product Type Name"
|
defaultMessage: "Product Type Name"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -123,13 +123,8 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
weight: maybe(() => productType.weight.value)
|
weight: maybe(() => productType.weight.value)
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form initial={formInitialData} onSubmit={onSubmit} confirmLeave>
|
||||||
errors={errors}
|
{({ change, data, hasChanged, submit }) => (
|
||||||
initial={formInitialData}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.productTypes)}
|
{intl.formatMessage(sectionNames.productTypes)}
|
||||||
|
@ -140,7 +135,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
|
||||||
<ProductTypeDetails
|
<ProductTypeDetails
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -90,7 +90,7 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
disabled,
|
disabled,
|
||||||
categories: categoryChoiceList,
|
categories: categoryChoiceList,
|
||||||
collections: collectionChoiceList,
|
collections: collectionChoiceList,
|
||||||
errors: userErrors,
|
errors,
|
||||||
fetchCategories,
|
fetchCategories,
|
||||||
fetchCollections,
|
fetchCollections,
|
||||||
fetchMoreCategories,
|
fetchMoreCategories,
|
||||||
|
@ -162,21 +162,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
|
||||||
onSubmit={handleSubmit}
|
{({ change, data, hasChanged, submit, triggerChange, toggleValue }) => {
|
||||||
errors={userErrors}
|
|
||||||
initial={initialData}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({
|
|
||||||
change,
|
|
||||||
data,
|
|
||||||
errors,
|
|
||||||
hasChanged,
|
|
||||||
submit,
|
|
||||||
triggerChange,
|
|
||||||
toggleValue
|
|
||||||
}) => {
|
|
||||||
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
|
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
|
||||||
toggleValue,
|
toggleValue,
|
||||||
setSelectedCollections,
|
setSelectedCollections,
|
||||||
|
|
|
@ -9,6 +9,8 @@ import CardTitle from "@saleor/components/CardTitle";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import RichTextEditor from "@saleor/components/RichTextEditor";
|
import RichTextEditor from "@saleor/components/RichTextEditor";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
interface ProductDetailsFormProps {
|
interface ProductDetailsFormProps {
|
||||||
data: {
|
data: {
|
||||||
|
@ -16,7 +18,7 @@ interface ProductDetailsFormProps {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
errors: { [key: string]: string };
|
errors: UserError[];
|
||||||
// Draftail isn't controlled - it needs only initial input
|
// Draftail isn't controlled - it needs only initial input
|
||||||
// because it's autosaving on its own.
|
// because it's autosaving on its own.
|
||||||
// Ref https://github.com/mirumee/saleor/issues/4470
|
// Ref https://github.com/mirumee/saleor/issues/4470
|
||||||
|
@ -40,8 +42,8 @@ export const ProductDetailsForm: React.FC<ProductDetailsFormProps> = ({
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
@ -55,8 +57,8 @@ export const ProductDetailsForm: React.FC<ProductDetailsFormProps> = ({
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<RichTextEditor
|
<RichTextEditor
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.descriptionJson}
|
error={!!getFieldError(errors, "descriptionJson")}
|
||||||
helperText={errors.descriptionJson}
|
helperText={getFieldError(errors, "descriptionJson")?.message}
|
||||||
initial={initialDescription}
|
initial={initialDescription}
|
||||||
label={intl.formatMessage(commonMessages.description)}
|
label={intl.formatMessage(commonMessages.description)}
|
||||||
name="description"
|
name="description"
|
||||||
|
|
|
@ -17,7 +17,8 @@ import SingleAutocompleteSelectField, {
|
||||||
} from "@saleor/components/SingleAutocompleteSelectField";
|
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||||
import { maybe } from "@saleor/misc";
|
import { maybe } from "@saleor/misc";
|
||||||
import { FetchMoreProps, FormErrors } from "@saleor/types";
|
import { FetchMoreProps, UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
interface ProductType {
|
interface ProductType {
|
||||||
hasVariants: boolean;
|
hasVariants: boolean;
|
||||||
|
@ -53,7 +54,7 @@ interface ProductOrganizationProps {
|
||||||
productType?: string;
|
productType?: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"productType" | "category">;
|
errors: UserError[];
|
||||||
productType?: ProductType;
|
productType?: ProductType;
|
||||||
productTypeInputDisplayValue?: string;
|
productTypeInputDisplayValue?: string;
|
||||||
productTypes?: SingleAutocompleteChoiceType[];
|
productTypes?: SingleAutocompleteChoiceType[];
|
||||||
|
@ -73,7 +74,6 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
|
||||||
canChangeType,
|
canChangeType,
|
||||||
categories,
|
categories,
|
||||||
categoryInputDisplayValue,
|
categoryInputDisplayValue,
|
||||||
|
|
||||||
collections,
|
collections,
|
||||||
collectionsInputDisplayValue,
|
collectionsInputDisplayValue,
|
||||||
data,
|
data,
|
||||||
|
@ -108,8 +108,8 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
|
||||||
{canChangeType ? (
|
{canChangeType ? (
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
displayValue={productTypeInputDisplayValue}
|
displayValue={productTypeInputDisplayValue}
|
||||||
error={!!errors.productType}
|
error={!!getFieldError(errors, "productType")}
|
||||||
helperText={errors.productType}
|
helperText={getFieldError(errors, "productType")?.message}
|
||||||
name="productType"
|
name="productType"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
@ -154,8 +154,8 @@ const ProductOrganization: React.FC<ProductOrganizationProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
displayValue={categoryInputDisplayValue}
|
displayValue={categoryInputDisplayValue}
|
||||||
error={!!errors.category}
|
error={!!getFieldError(errors, "category")}
|
||||||
helperText={errors.category}
|
helperText={getFieldError(errors, "category")?.message}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Category"
|
defaultMessage: "Category"
|
||||||
|
|
|
@ -6,6 +6,8 @@ import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { ProductDetails_product } from "../../types/ProductDetails";
|
import { ProductDetails_product } from "../../types/ProductDetails";
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ interface ProductStockProps {
|
||||||
stockQuantity: number;
|
stockQuantity: number;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: { [key: string]: string };
|
errors: UserError[];
|
||||||
product: ProductDetails_product;
|
product: ProductDetails_product;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
@ -56,8 +58,8 @@ const ProductStock: React.FC<ProductStockProps> = props => {
|
||||||
})}
|
})}
|
||||||
value={data.sku}
|
value={data.sku}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
error={!!errors.sku}
|
error={!!getFieldError(errors, "sku")}
|
||||||
helperText={errors.sku}
|
helperText={getFieldError(errors, "sku")?.message}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
@ -85,7 +85,7 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||||
disabled,
|
disabled,
|
||||||
categories: categoryChoiceList,
|
categories: categoryChoiceList,
|
||||||
collections: collectionChoiceList,
|
collections: collectionChoiceList,
|
||||||
errors: userErrors,
|
errors,
|
||||||
fetchCategories,
|
fetchCategories,
|
||||||
fetchCollections,
|
fetchCollections,
|
||||||
fetchMoreCategories,
|
fetchMoreCategories,
|
||||||
|
@ -152,21 +152,8 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
|
||||||
onSubmit={handleSubmit}
|
{({ change, data, hasChanged, submit, triggerChange, toggleValue }) => {
|
||||||
errors={userErrors}
|
|
||||||
initial={initialData}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({
|
|
||||||
change,
|
|
||||||
data,
|
|
||||||
errors,
|
|
||||||
hasChanged,
|
|
||||||
submit,
|
|
||||||
triggerChange,
|
|
||||||
toggleValue
|
|
||||||
}) => {
|
|
||||||
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
|
const handleCollectionSelect = createMultiAutocompleteSelectHandler(
|
||||||
toggleValue,
|
toggleValue,
|
||||||
setSelectedCollections,
|
setSelectedCollections,
|
||||||
|
|
|
@ -51,7 +51,7 @@ interface ProductVariantCreatePageProps {
|
||||||
|
|
||||||
const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||||
currencySymbol,
|
currencySymbol,
|
||||||
errors: apiErrors,
|
errors,
|
||||||
loading,
|
loading,
|
||||||
header,
|
header,
|
||||||
product,
|
product,
|
||||||
|
@ -93,8 +93,8 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form initial={initialForm} errors={apiErrors} onSubmit={handleSubmit}>
|
<Form initial={initialForm} onSubmit={handleSubmit}>
|
||||||
{({ change, data, errors, hasChanged, submit, triggerChange }) => {
|
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||||
const handleAttributeChange: FormsetChange = (id, value) => {
|
const handleAttributeChange: FormsetChange = (id, value) => {
|
||||||
changeAttributeData(id, value);
|
changeAttributeData(id, value);
|
||||||
triggerChange();
|
triggerChange();
|
||||||
|
@ -120,7 +120,7 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
|
||||||
<ProductVariantAttributes
|
<ProductVariantAttributes
|
||||||
attributes={attributes}
|
attributes={attributes}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
errors={apiErrors}
|
errors={errors}
|
||||||
onChange={handleAttributeChange}
|
onChange={handleAttributeChange}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -53,7 +53,7 @@ interface ProductVariantPageProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||||
errors: apiErrors,
|
errors,
|
||||||
loading,
|
loading,
|
||||||
header,
|
header,
|
||||||
placeholderImage,
|
placeholderImage,
|
||||||
|
@ -109,13 +109,8 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||||
{maybe(() => variant.product.name)}
|
{maybe(() => variant.product.name)}
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
<PageHeader title={header} />
|
<PageHeader title={header} />
|
||||||
<Form
|
<Form initial={initialForm} onSubmit={handleSubmit} confirmLeave>
|
||||||
initial={initialForm}
|
{({ change, data, hasChanged, submit, triggerChange }) => {
|
||||||
errors={apiErrors}
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ change, data, errors, hasChanged, submit, triggerChange }) => {
|
|
||||||
const handleAttributeChange: FormsetChange = (id, value) => {
|
const handleAttributeChange: FormsetChange = (id, value) => {
|
||||||
changeAttributeData(id, value);
|
changeAttributeData(id, value);
|
||||||
triggerChange();
|
triggerChange();
|
||||||
|
@ -143,7 +138,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
|
||||||
<ProductVariantAttributes
|
<ProductVariantAttributes
|
||||||
attributes={attributes}
|
attributes={attributes}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
errors={apiErrors}
|
errors={errors}
|
||||||
onChange={handleAttributeChange}
|
onChange={handleAttributeChange}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import PriceField from "@saleor/components/PriceField";
|
import PriceField from "@saleor/components/PriceField";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
|
@ -22,7 +24,7 @@ interface ProductVariantPriceProps {
|
||||||
currencySymbol?: string;
|
currencySymbol?: string;
|
||||||
priceOverride?: string;
|
priceOverride?: string;
|
||||||
costPrice?: string;
|
costPrice?: string;
|
||||||
errors: { [key: string]: string };
|
errors: UserError[];
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
onChange(event: any);
|
onChange(event: any);
|
||||||
}
|
}
|
||||||
|
@ -52,19 +54,18 @@ const ProductVariantPrice: React.FC<ProductVariantPriceProps> = props => {
|
||||||
<div className={classes.grid}>
|
<div className={classes.grid}>
|
||||||
<div>
|
<div>
|
||||||
<PriceField
|
<PriceField
|
||||||
error={!!errors.price_override}
|
error={!!getFieldError(errors, "price_override")}
|
||||||
name="priceOverride"
|
name="priceOverride"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Selling price override"
|
defaultMessage: "Selling price override"
|
||||||
})}
|
})}
|
||||||
hint={
|
hint={
|
||||||
errors.price_override
|
getFieldError(errors, "price_override")?.message ||
|
||||||
? errors.price_override
|
intl.formatMessage({
|
||||||
: intl.formatMessage({
|
defaultMessage: "Optional",
|
||||||
defaultMessage: "Optional",
|
description: "optional field",
|
||||||
description: "optional field",
|
id: "productVariantPriceOptionalPriceOverrideField"
|
||||||
id: "productVariantPriceOptionalPriceOverrideField"
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
value={priceOverride}
|
value={priceOverride}
|
||||||
currencySymbol={currencySymbol}
|
currencySymbol={currencySymbol}
|
||||||
|
@ -74,19 +75,18 @@ const ProductVariantPrice: React.FC<ProductVariantPriceProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<PriceField
|
<PriceField
|
||||||
error={!!errors.cost_price}
|
error={!!getFieldError(errors, "cost_price")}
|
||||||
name="costPrice"
|
name="costPrice"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Cost price override"
|
defaultMessage: "Cost price override"
|
||||||
})}
|
})}
|
||||||
hint={
|
hint={
|
||||||
errors.cost_price
|
getFieldError(errors, "cost_price")?.message ||
|
||||||
? errors.cost_price
|
intl.formatMessage({
|
||||||
: intl.formatMessage({
|
defaultMessage: "Optional",
|
||||||
defaultMessage: "Optional",
|
description: "optional field",
|
||||||
description: "optional field",
|
id: "productVariantPriceOptionalCostPriceField"
|
||||||
id: "productVariantPriceOptionalCostPriceField"
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
value={costPrice}
|
value={costPrice}
|
||||||
currencySymbol={currencySymbol}
|
currencySymbol={currencySymbol}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
|
@ -19,10 +21,7 @@ const useStyles = makeStyles(
|
||||||
);
|
);
|
||||||
|
|
||||||
interface ProductVariantStockProps {
|
interface ProductVariantStockProps {
|
||||||
errors: {
|
errors: UserError[];
|
||||||
quantity?: string;
|
|
||||||
sku?: string;
|
|
||||||
};
|
|
||||||
sku: string;
|
sku: string;
|
||||||
quantity: string;
|
quantity: string;
|
||||||
stockAllocated?: number;
|
stockAllocated?: number;
|
||||||
|
@ -48,7 +47,7 @@ const ProductVariantStock: React.FC<ProductVariantStockProps> = props => {
|
||||||
<div className={classes.grid}>
|
<div className={classes.grid}>
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.quantity}
|
error={!!getFieldError(errors, "quantity")}
|
||||||
name="quantity"
|
name="quantity"
|
||||||
value={quantity}
|
value={quantity}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
@ -56,8 +55,8 @@ const ProductVariantStock: React.FC<ProductVariantStockProps> = props => {
|
||||||
description: "product variant stock"
|
description: "product variant stock"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
errors.quantity
|
getFieldError(errors, "quantity")
|
||||||
? errors.quantity
|
? getFieldError(errors, "quantity")
|
||||||
: !!stockAllocated
|
: !!stockAllocated
|
||||||
? intl.formatMessage(
|
? intl.formatMessage(
|
||||||
{
|
{
|
||||||
|
@ -77,8 +76,8 @@ const ProductVariantStock: React.FC<ProductVariantStockProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.sku}
|
error={!!getFieldError(errors, "sku")}
|
||||||
helperText={errors.sku}
|
helperText={getFieldError(errors, "sku")?.message}
|
||||||
name="sku"
|
name="sku"
|
||||||
value={sku}
|
value={sku}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
|
|
@ -35,7 +35,7 @@ export interface ServiceCreatePageProps {
|
||||||
const ServiceCreatePage: React.FC<ServiceCreatePageProps> = props => {
|
const ServiceCreatePage: React.FC<ServiceCreatePageProps> = props => {
|
||||||
const {
|
const {
|
||||||
disabled,
|
disabled,
|
||||||
errors: formErrors,
|
errors,
|
||||||
permissions,
|
permissions,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
onBack,
|
onBack,
|
||||||
|
@ -50,13 +50,8 @@ const ServiceCreatePage: React.FC<ServiceCreatePageProps> = props => {
|
||||||
permissions: []
|
permissions: []
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form initial={initialForm} onSubmit={onSubmit} confirmLeave>
|
||||||
errors={formErrors}
|
{({ data, change, hasChanged, submit }) => (
|
||||||
initial={initialForm}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ data, change, errors, hasChanged, submit }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.serviceAccounts)}
|
{intl.formatMessage(sectionNames.serviceAccounts)}
|
||||||
|
|
|
@ -48,7 +48,7 @@ const ServiceDetailsPage: React.FC<ServiceDetailsPageProps> = props => {
|
||||||
const {
|
const {
|
||||||
apiUri,
|
apiUri,
|
||||||
disabled,
|
disabled,
|
||||||
errors: formErrors,
|
errors,
|
||||||
permissions,
|
permissions,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
service,
|
service,
|
||||||
|
@ -79,13 +79,8 @@ const ServiceDetailsPage: React.FC<ServiceDetailsPageProps> = props => {
|
||||||
permissions: maybe(() => service.permissions, []).map(perm => perm.code)
|
permissions: maybe(() => service.permissions, []).map(perm => perm.code)
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form initial={initialForm} onSubmit={onSubmit} confirmLeave>
|
||||||
errors={formErrors}
|
{({ data, change, hasChanged, submit }) => (
|
||||||
initial={initialForm}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ data, change, errors, hasChanged, submit }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.serviceAccounts)}
|
{intl.formatMessage(sectionNames.serviceAccounts)}
|
||||||
|
|
|
@ -6,14 +6,15 @@ import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { FormChange } from "@saleor/hooks/useForm";
|
import { FormChange } from "@saleor/hooks/useForm";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
export interface ServiceInfoProps {
|
export interface ServiceInfoProps {
|
||||||
data: {
|
data: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: FormErrors<"name">;
|
errors: UserError[];
|
||||||
onChange: FormChange;
|
onChange: FormChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +33,12 @@ const ServiceInfo: React.FC<ServiceInfoProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Account Name",
|
defaultMessage: "Account Name",
|
||||||
description: "service account"
|
description: "service account"
|
||||||
})}
|
})}
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="name"
|
name="name"
|
||||||
value={data.name}
|
value={data.name}
|
||||||
|
|
|
@ -50,8 +50,8 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<>
|
<>
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
|
@ -67,7 +67,7 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
||||||
<div>
|
<div>
|
||||||
<ShippingZoneInfo
|
<ShippingZoneInfo
|
||||||
data={data}
|
data={data}
|
||||||
errors={formErrors}
|
errors={errors}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
|
|
|
@ -57,11 +57,11 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const initialForm: FormData = {
|
const initialForm: FormData = {
|
||||||
name: maybe(() => shippingZone.name, "")
|
name: shippingZone?.name || ""
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => (
|
{({ change, data, hasChanged, submit }) => (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
<FormattedMessage defaultMessage="Shipping" />
|
<FormattedMessage defaultMessage="Shipping" />
|
||||||
|
@ -69,11 +69,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
||||||
<PageHeader title={maybe(() => shippingZone.name)} />
|
<PageHeader title={maybe(() => shippingZone.name)} />
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<ShippingZoneInfo
|
<ShippingZoneInfo data={data} errors={errors} onChange={change} />
|
||||||
data={data}
|
|
||||||
errors={formErrors}
|
|
||||||
onChange={change}
|
|
||||||
/>
|
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<CountryList
|
<CountryList
|
||||||
countries={maybe(() => shippingZone.countries)}
|
countries={maybe(() => shippingZone.countries)}
|
||||||
|
|
|
@ -6,12 +6,13 @@ 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 { FormErrors } from "../../../types";
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
import { UserError } from "../../../types";
|
||||||
import { FormData } from "../ShippingZoneDetailsPage";
|
import { FormData } from "../ShippingZoneDetailsPage";
|
||||||
|
|
||||||
export interface ShippingZoneInfoProps {
|
export interface ShippingZoneInfoProps {
|
||||||
data: FormData;
|
data: FormData;
|
||||||
errors: FormErrors<"name">;
|
errors: UserError[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +30,9 @@ const ShippingZoneInfo: React.FC<ShippingZoneInfoProps> = ({
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Shipping Zone Name"
|
defaultMessage: "Shipping Zone Name"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -18,8 +18,9 @@ import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import Hr from "@saleor/components/Hr";
|
import Hr from "@saleor/components/Hr";
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { maybe } from "../../../misc";
|
import { maybe } from "../../../misc";
|
||||||
import { FormErrors, UserError } from "../../../types";
|
import { UserError } from "../../../types";
|
||||||
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
|
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
|
||||||
import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment";
|
import { ShippingZoneDetailsFragment_shippingMethods } from "../../types/ShippingZoneDetailsFragment";
|
||||||
|
|
||||||
|
@ -109,243 +110,233 @@ const ShippingZoneRateDialog: React.FC<ShippingZoneRateDialogProps> = props => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
|
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors: formErrors, hasChanged }) => {
|
{({ change, data, hasChanged }) => (
|
||||||
const typedFormErrors: FormErrors<
|
<>
|
||||||
| "minimumOrderPrice"
|
<DialogTitle>
|
||||||
| "minimumOrderWeight"
|
{variant === ShippingMethodTypeEnum.PRICE
|
||||||
| "maximumOrderPrice"
|
? action === "create"
|
||||||
| "maximumOrderWeight"
|
|
||||||
| "price"
|
|
||||||
| "name"
|
|
||||||
> = formErrors;
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DialogTitle>
|
|
||||||
{variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? action === "create"
|
|
||||||
? intl.formatMessage({
|
|
||||||
defaultMessage: "Add Price Rate",
|
|
||||||
description: "dialog header"
|
|
||||||
})
|
|
||||||
: intl.formatMessage({
|
|
||||||
defaultMessage: "Edit Price Rate",
|
|
||||||
description: "dialog header"
|
|
||||||
})
|
|
||||||
: action === "create"
|
|
||||||
? intl.formatMessage({
|
? intl.formatMessage({
|
||||||
defaultMessage: "Add Weight Rate",
|
defaultMessage: "Add Price Rate",
|
||||||
description:
|
description: "dialog header"
|
||||||
"add weight based shipping method, dialog header"
|
|
||||||
})
|
})
|
||||||
: intl.formatMessage({
|
: intl.formatMessage({
|
||||||
defaultMessage: "Edit Weight Rate",
|
defaultMessage: "Edit Price Rate",
|
||||||
description:
|
description: "dialog header"
|
||||||
"edit weight based shipping method, dialog header"
|
|
||||||
})}
|
|
||||||
</DialogTitle>
|
|
||||||
<DialogContent>
|
|
||||||
<TextField
|
|
||||||
disabled={disabled}
|
|
||||||
error={!!typedFormErrors.name}
|
|
||||||
fullWidth
|
|
||||||
helperText={
|
|
||||||
typedFormErrors.name ||
|
|
||||||
intl.formatMessage({
|
|
||||||
defaultMessage:
|
|
||||||
"This will be shown to customers at checkout"
|
|
||||||
})
|
})
|
||||||
}
|
: action === "create"
|
||||||
label={intl.formatMessage({
|
? intl.formatMessage({
|
||||||
defaultMessage: "Rate Name",
|
defaultMessage: "Add Weight Rate",
|
||||||
description: "shipping method name"
|
description:
|
||||||
|
"add weight based shipping method, dialog header"
|
||||||
|
})
|
||||||
|
: intl.formatMessage({
|
||||||
|
defaultMessage: "Edit Weight Rate",
|
||||||
|
description:
|
||||||
|
"edit weight based shipping method, dialog header"
|
||||||
})}
|
})}
|
||||||
name={"name" as keyof FormData}
|
</DialogTitle>
|
||||||
value={data.name}
|
<DialogContent>
|
||||||
onChange={change}
|
<TextField
|
||||||
/>
|
disabled={disabled}
|
||||||
</DialogContent>
|
error={!!getFieldError(errors, "name")}
|
||||||
<Hr />
|
fullWidth
|
||||||
<DialogContent>
|
helperText={
|
||||||
{!!variant ? (
|
getFieldError(errors, "name") ||
|
||||||
<>
|
intl.formatMessage({
|
||||||
<Typography
|
defaultMessage:
|
||||||
className={classes.subheading}
|
"This will be shown to customers at checkout"
|
||||||
variant="subtitle1"
|
})
|
||||||
>
|
}
|
||||||
{variant === ShippingMethodTypeEnum.PRICE
|
label={intl.formatMessage({
|
||||||
? intl.formatMessage({
|
defaultMessage: "Rate Name",
|
||||||
defaultMessage: "Value range",
|
description: "shipping method name"
|
||||||
description: "order price range"
|
})}
|
||||||
})
|
name={"name" as keyof FormData}
|
||||||
: intl.formatMessage({
|
value={data.name}
|
||||||
defaultMessage: "Weight range",
|
onChange={change}
|
||||||
description: "order weight range"
|
/>
|
||||||
})}
|
</DialogContent>
|
||||||
</Typography>
|
<Hr />
|
||||||
<ControlledCheckbox
|
<DialogContent>
|
||||||
name={"noLimits" as keyof FormData}
|
{!!variant ? (
|
||||||
label={
|
<>
|
||||||
<>
|
<Typography
|
||||||
<FormattedMessage
|
className={classes.subheading}
|
||||||
defaultMessage="There are no value limits"
|
variant="subtitle1"
|
||||||
description="shipping method has no value limits"
|
>
|
||||||
/>
|
{variant === ShippingMethodTypeEnum.PRICE
|
||||||
<Typography variant="caption">
|
? intl.formatMessage({
|
||||||
{variant === ShippingMethodTypeEnum.PRICE
|
defaultMessage: "Value range",
|
||||||
? intl.formatMessage({
|
description: "order price range"
|
||||||
defaultMessage:
|
})
|
||||||
"This rate will apply to all orders of all prices"
|
: intl.formatMessage({
|
||||||
})
|
defaultMessage: "Weight range",
|
||||||
: intl.formatMessage({
|
description: "order weight range"
|
||||||
defaultMessage:
|
|
||||||
"This rate will apply to all orders of all weights"
|
|
||||||
})}
|
|
||||||
</Typography>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
checked={data.noLimits}
|
|
||||||
onChange={change}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
{!data.noLimits && (
|
|
||||||
<>
|
|
||||||
<FormSpacer />
|
|
||||||
<div className={classes.grid}>
|
|
||||||
<TextField
|
|
||||||
disabled={disabled}
|
|
||||||
error={
|
|
||||||
variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? !!typedFormErrors.minimumOrderPrice
|
|
||||||
: !!typedFormErrors.minimumOrderWeight
|
|
||||||
}
|
|
||||||
fullWidth
|
|
||||||
helperText={
|
|
||||||
variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? typedFormErrors.minimumOrderPrice
|
|
||||||
: typedFormErrors.minimumOrderWeight
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? typedFormErrors.minimumOrderPrice ||
|
|
||||||
intl.formatMessage({
|
|
||||||
defaultMessage: "Minimal Order Value"
|
|
||||||
})
|
|
||||||
: typedFormErrors.minimumOrderWeight ||
|
|
||||||
intl.formatMessage({
|
|
||||||
defaultMessage: "Minimal Order Weight"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
name={"minValue" as keyof FormData}
|
|
||||||
type="number"
|
|
||||||
value={data.minValue}
|
|
||||||
onChange={change}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
disabled={disabled}
|
|
||||||
error={
|
|
||||||
variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? !!typedFormErrors.maximumOrderPrice
|
|
||||||
: !!typedFormErrors.maximumOrderWeight
|
|
||||||
}
|
|
||||||
fullWidth
|
|
||||||
helperText={
|
|
||||||
variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? typedFormErrors.maximumOrderPrice
|
|
||||||
: typedFormErrors.maximumOrderWeight
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
variant === ShippingMethodTypeEnum.PRICE
|
|
||||||
? typedFormErrors.maximumOrderPrice ||
|
|
||||||
intl.formatMessage({
|
|
||||||
defaultMessage: "Maximal Order Value"
|
|
||||||
})
|
|
||||||
: typedFormErrors.maximumOrderWeight ||
|
|
||||||
intl.formatMessage({
|
|
||||||
defaultMessage: "Maximal Order Weight"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
name={"maxValue" as keyof FormData}
|
|
||||||
type="number"
|
|
||||||
value={data.maxValue}
|
|
||||||
onChange={change}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Skeleton />
|
|
||||||
)}
|
|
||||||
</DialogContent>
|
|
||||||
<Hr />
|
|
||||||
<DialogContent>
|
|
||||||
<Typography className={classes.subheading} variant="subtitle1">
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Rate"
|
|
||||||
description="shipping method"
|
|
||||||
/>
|
|
||||||
</Typography>
|
|
||||||
<ControlledCheckbox
|
|
||||||
name={"isFree" as keyof FormData}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
defaultMessage: "This is free shipping",
|
|
||||||
description: "shipping method, switch button"
|
|
||||||
})}
|
|
||||||
checked={data.isFree}
|
|
||||||
onChange={change}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
{!data.isFree && (
|
|
||||||
<>
|
|
||||||
<FormSpacer />
|
|
||||||
<div className={classes.grid}>
|
|
||||||
<TextField
|
|
||||||
disabled={disabled}
|
|
||||||
error={!!typedFormErrors.price}
|
|
||||||
fullWidth
|
|
||||||
helperText={typedFormErrors.price}
|
|
||||||
label={intl.formatMessage({
|
|
||||||
defaultMessage: "Rate Price",
|
|
||||||
description: "shipping method price"
|
|
||||||
})}
|
})}
|
||||||
name={"price" as keyof FormData}
|
</Typography>
|
||||||
type="number"
|
<ControlledCheckbox
|
||||||
value={data.price}
|
name={"noLimits" as keyof FormData}
|
||||||
onChange={change}
|
label={
|
||||||
InputProps={{
|
<>
|
||||||
endAdornment: defaultCurrency
|
<FormattedMessage
|
||||||
}}
|
defaultMessage="There are no value limits"
|
||||||
/>
|
description="shipping method has no value limits"
|
||||||
</div>
|
/>
|
||||||
</>
|
<Typography variant="caption">
|
||||||
)}
|
{variant === ShippingMethodTypeEnum.PRICE
|
||||||
</DialogContent>
|
? intl.formatMessage({
|
||||||
<DialogActions>
|
defaultMessage:
|
||||||
<Button onClick={onClose}>
|
"This rate will apply to all orders of all prices"
|
||||||
<FormattedMessage {...buttonMessages.back} />
|
})
|
||||||
</Button>
|
: intl.formatMessage({
|
||||||
<ConfirmButton
|
defaultMessage:
|
||||||
disabled={disabled || !hasChanged}
|
"This rate will apply to all orders of all weights"
|
||||||
transitionState={confirmButtonState}
|
})}
|
||||||
color="primary"
|
</Typography>
|
||||||
variant="contained"
|
</>
|
||||||
type="submit"
|
}
|
||||||
>
|
checked={data.noLimits}
|
||||||
{action === "create"
|
onChange={change}
|
||||||
? intl.formatMessage({
|
disabled={disabled}
|
||||||
defaultMessage: "Create rate",
|
/>
|
||||||
description: "button"
|
{!data.noLimits && (
|
||||||
})
|
<>
|
||||||
: intl.formatMessage({
|
<FormSpacer />
|
||||||
defaultMessage: "Update rate",
|
<div className={classes.grid}>
|
||||||
description: "button"
|
<TextField
|
||||||
|
disabled={disabled}
|
||||||
|
error={
|
||||||
|
variant === ShippingMethodTypeEnum.PRICE
|
||||||
|
? !!getFieldError(errors, "minimumOrderPrice")
|
||||||
|
: !!getFieldError(errors, "minimumOrderWeight")
|
||||||
|
}
|
||||||
|
fullWidth
|
||||||
|
helperText={
|
||||||
|
variant === ShippingMethodTypeEnum.PRICE
|
||||||
|
? getFieldError(errors, "minimumOrderPrice")
|
||||||
|
: getFieldError(errors, "minimumOrderWeight")
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
variant === ShippingMethodTypeEnum.PRICE
|
||||||
|
? getFieldError(errors, "minimumOrderPrice") ||
|
||||||
|
intl.formatMessage({
|
||||||
|
defaultMessage: "Minimal Order Value"
|
||||||
|
})
|
||||||
|
: getFieldError(errors, "minimumOrderWeight") ||
|
||||||
|
intl.formatMessage({
|
||||||
|
defaultMessage: "Minimal Order Weight"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
name={"minValue" as keyof FormData}
|
||||||
|
type="number"
|
||||||
|
value={data.minValue}
|
||||||
|
onChange={change}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
disabled={disabled}
|
||||||
|
error={
|
||||||
|
variant === ShippingMethodTypeEnum.PRICE
|
||||||
|
? !!getFieldError(errors, "maximumOrderPrice")
|
||||||
|
: !!getFieldError(errors, "maximumOrderWeight")
|
||||||
|
}
|
||||||
|
fullWidth
|
||||||
|
helperText={
|
||||||
|
variant === ShippingMethodTypeEnum.PRICE
|
||||||
|
? getFieldError(errors, "maximumOrderPrice")
|
||||||
|
: getFieldError(errors, "maximumOrderWeight")
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
variant === ShippingMethodTypeEnum.PRICE
|
||||||
|
? getFieldError(errors, "maximumOrderPrice") ||
|
||||||
|
intl.formatMessage({
|
||||||
|
defaultMessage: "Maximal Order Value"
|
||||||
|
})
|
||||||
|
: getFieldError(errors, "maximumOrderWeight") ||
|
||||||
|
intl.formatMessage({
|
||||||
|
defaultMessage: "Maximal Order Weight"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
name={"maxValue" as keyof FormData}
|
||||||
|
type="number"
|
||||||
|
value={data.maxValue}
|
||||||
|
onChange={change}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Skeleton />
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<Hr />
|
||||||
|
<DialogContent>
|
||||||
|
<Typography className={classes.subheading} variant="subtitle1">
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Rate"
|
||||||
|
description="shipping method"
|
||||||
|
/>
|
||||||
|
</Typography>
|
||||||
|
<ControlledCheckbox
|
||||||
|
name={"isFree" as keyof FormData}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
defaultMessage: "This is free shipping",
|
||||||
|
description: "shipping method, switch button"
|
||||||
|
})}
|
||||||
|
checked={data.isFree}
|
||||||
|
onChange={change}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
{!data.isFree && (
|
||||||
|
<>
|
||||||
|
<FormSpacer />
|
||||||
|
<div className={classes.grid}>
|
||||||
|
<TextField
|
||||||
|
disabled={disabled}
|
||||||
|
error={!!getFieldError(errors, "price")}
|
||||||
|
fullWidth
|
||||||
|
helperText={getFieldError(errors, "price")?.message}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
defaultMessage: "Rate Price",
|
||||||
|
description: "shipping method price"
|
||||||
})}
|
})}
|
||||||
</ConfirmButton>
|
name={"price" as keyof FormData}
|
||||||
</DialogActions>
|
type="number"
|
||||||
</>
|
value={data.price}
|
||||||
);
|
onChange={change}
|
||||||
}}
|
InputProps={{
|
||||||
|
endAdornment: defaultCurrency
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={onClose}>
|
||||||
|
<FormattedMessage {...buttonMessages.back} />
|
||||||
|
</Button>
|
||||||
|
<ConfirmButton
|
||||||
|
disabled={disabled || !hasChanged}
|
||||||
|
transitionState={confirmButtonState}
|
||||||
|
color="primary"
|
||||||
|
variant="contained"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
{action === "create"
|
||||||
|
? intl.formatMessage({
|
||||||
|
defaultMessage: "Create rate",
|
||||||
|
description: "button"
|
||||||
|
})
|
||||||
|
: intl.formatMessage({
|
||||||
|
defaultMessage: "Update rate",
|
||||||
|
description: "button"
|
||||||
|
})}
|
||||||
|
</ConfirmButton>
|
||||||
|
</DialogActions>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,16 +11,16 @@ import Grid from "@saleor/components/Grid";
|
||||||
import SingleAutocompleteSelectField, {
|
import SingleAutocompleteSelectField, {
|
||||||
SingleAutocompleteChoiceType
|
SingleAutocompleteChoiceType
|
||||||
} from "@saleor/components/SingleAutocompleteSelectField";
|
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import { AddressTypeInput } from "@saleor/customers/types";
|
|
||||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { SiteSettingsPageFormData } from "../SiteSettingsPage";
|
import { SiteSettingsPageFormData } from "../SiteSettingsPage";
|
||||||
|
|
||||||
interface SiteSettingsAddressProps {
|
interface SiteSettingsAddressProps {
|
||||||
countries: SingleAutocompleteChoiceType[];
|
countries: SingleAutocompleteChoiceType[];
|
||||||
data: SiteSettingsPageFormData;
|
data: SiteSettingsPageFormData;
|
||||||
displayCountry: string;
|
displayCountry: string;
|
||||||
errors: FormErrors<keyof AddressTypeInput>;
|
errors: UserError[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (event: ChangeEvent) => void;
|
onChange: (event: ChangeEvent) => void;
|
||||||
onCountryChange: (event: ChangeEvent) => void;
|
onCountryChange: (event: ChangeEvent) => void;
|
||||||
|
@ -60,8 +60,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.companyName}
|
error={!!getFieldError(errors, "companyName")}
|
||||||
helperText={errors.companyName}
|
helperText={getFieldError(errors, "companyName")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Company"
|
defaultMessage: "Company"
|
||||||
})}
|
})}
|
||||||
|
@ -73,8 +73,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.streetAddress1}
|
error={!!getFieldError(errors, "streetAddress1")}
|
||||||
helperText={errors.streetAddress1}
|
helperText={getFieldError(errors, "streetAddress1")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Address line 1"
|
defaultMessage: "Address line 1"
|
||||||
})}
|
})}
|
||||||
|
@ -86,8 +86,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.streetAddress2}
|
error={!!getFieldError(errors, "streetAddress2")}
|
||||||
helperText={errors.streetAddress2}
|
helperText={getFieldError(errors, "streetAddress2")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Address line 2"
|
defaultMessage: "Address line 2"
|
||||||
})}
|
})}
|
||||||
|
@ -100,8 +100,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
<Grid>
|
<Grid>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.city}
|
error={!!getFieldError(errors, "city")}
|
||||||
helperText={errors.city}
|
helperText={getFieldError(errors, "city")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "City"
|
defaultMessage: "City"
|
||||||
})}
|
})}
|
||||||
|
@ -112,8 +112,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.postalCode}
|
error={!!getFieldError(errors, "postalCode")}
|
||||||
helperText={errors.postalCode}
|
helperText={getFieldError(errors, "postalCode")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "ZIP / Postal code"
|
defaultMessage: "ZIP / Postal code"
|
||||||
})}
|
})}
|
||||||
|
@ -128,8 +128,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
<SingleAutocompleteSelectField
|
<SingleAutocompleteSelectField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
displayValue={displayCountry}
|
displayValue={displayCountry}
|
||||||
error={!!errors.country}
|
error={!!getFieldError(errors, "country")}
|
||||||
helperText={errors.country}
|
helperText={getFieldError(errors, "country")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Country"
|
defaultMessage: "Country"
|
||||||
})}
|
})}
|
||||||
|
@ -143,8 +143,8 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.countryArea}
|
error={!!getFieldError(errors, "companyArea")}
|
||||||
helperText={errors.countryArea}
|
helperText={getFieldError(errors, "companyArea")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Country area"
|
defaultMessage: "Country area"
|
||||||
})}
|
})}
|
||||||
|
@ -157,9 +157,9 @@ const SiteSettingsAddress: React.FC<SiteSettingsAddressProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.phone}
|
error={!!getFieldError(errors, "phone")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.phone}
|
helperText={getFieldError(errors, "phone")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Phone"
|
defaultMessage: "Phone"
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -7,15 +7,13 @@ import { useIntl } from "react-intl";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { SiteSettingsPageFormData } from "../SiteSettingsPage";
|
import { SiteSettingsPageFormData } from "../SiteSettingsPage";
|
||||||
|
|
||||||
interface SiteSettingsDetailsProps {
|
interface SiteSettingsDetailsProps {
|
||||||
data: SiteSettingsPageFormData;
|
data: SiteSettingsPageFormData;
|
||||||
errors: Partial<{
|
errors: UserError[];
|
||||||
description: string;
|
|
||||||
domain: string;
|
|
||||||
name: string;
|
|
||||||
}>;
|
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
@ -36,14 +34,14 @@ const SiteSettingsDetails: React.FC<SiteSettingsDetailsProps> = ({
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="name"
|
name="name"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Name of your store"
|
defaultMessage: "Name of your store"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
errors.name ||
|
getFieldError(errors, "name")?.message ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"Name of your store is shown on tab in web browser"
|
"Name of your store is shown on tab in web browser"
|
||||||
|
@ -55,27 +53,27 @@ const SiteSettingsDetails: React.FC<SiteSettingsDetailsProps> = ({
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.domain}
|
error={!!getFieldError(errors, "domain")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="domain"
|
name="domain"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "URL of your online store"
|
defaultMessage: "URL of your online store"
|
||||||
})}
|
})}
|
||||||
helperText={errors.domain}
|
helperText={getFieldError(errors, "domain")?.message}
|
||||||
value={data.domain}
|
value={data.domain}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.domain}
|
error={!!getFieldError(errors, "description")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="description"
|
name="description"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Store Description"
|
defaultMessage: "Store Description"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
errors.description ||
|
getFieldError(errors, "description")?.message ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"Store description is shown on taskbar after your store name"
|
"Store description is shown on taskbar after your store name"
|
||||||
|
|
|
@ -7,10 +7,12 @@ import TextField from "@material-ui/core/TextField";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import Form, { FormProps } from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
import { FormSpacer } from "@saleor/components/FormSpacer";
|
import { FormSpacer } from "@saleor/components/FormSpacer";
|
||||||
import SingleSelectField from "@saleor/components/SingleSelectField";
|
import SingleSelectField from "@saleor/components/SingleSelectField";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
|
import { UserError, DialogProps } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { authorizationKeyTypes } from "../../../misc";
|
import { authorizationKeyTypes } from "../../../misc";
|
||||||
import { AuthorizationKeyType } from "../../../types/globalTypes";
|
import { AuthorizationKeyType } from "../../../types/globalTypes";
|
||||||
|
|
||||||
|
@ -20,13 +22,10 @@ export interface SiteSettingsKeyDialogForm {
|
||||||
type: AuthorizationKeyType;
|
type: AuthorizationKeyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SiteSettingsKeyDialogProps
|
export interface SiteSettingsKeyDialogProps extends DialogProps {
|
||||||
extends Pick<
|
errors: UserError[];
|
||||||
FormProps<SiteSettingsKeyDialogForm>,
|
initial: SiteSettingsKeyDialogForm;
|
||||||
Exclude<keyof FormProps<SiteSettingsKeyDialogForm>, "children">
|
onSubmit: (data: SiteSettingsKeyDialogForm) => void;
|
||||||
> {
|
|
||||||
open: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
||||||
|
@ -40,8 +39,8 @@ const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} maxWidth="xs" open={open}>
|
<Dialog onClose={onClose} maxWidth="xs" open={open}>
|
||||||
<Form initial={initial} onSubmit={onSubmit} errors={errors}>
|
<Form initial={initial} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors }) => (
|
{({ change, data }) => (
|
||||||
<>
|
<>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
|
@ -55,37 +54,37 @@ const SiteSettingsKeyDialog: React.FC<SiteSettingsKeyDialogProps> = ({
|
||||||
label: authorizationKeyTypes[key],
|
label: authorizationKeyTypes[key],
|
||||||
value: key
|
value: key
|
||||||
}))}
|
}))}
|
||||||
error={!!errors.keyType}
|
error={!!getFieldError(errors, "keyType")}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Authentication type",
|
defaultMessage: "Authentication type",
|
||||||
description: "authentication provider name"
|
description: "authentication provider name"
|
||||||
})}
|
})}
|
||||||
hint={errors.keyType}
|
hint={getFieldError(errors, "keyType")?.message}
|
||||||
name="type"
|
name="type"
|
||||||
onChange={change}
|
onChange={change}
|
||||||
value={data.type}
|
value={data.type}
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.key}
|
error={!!getFieldError(errors, "key")}
|
||||||
fullWidth
|
fullWidth
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Key",
|
defaultMessage: "Key",
|
||||||
description: "authentication provider API key"
|
description: "authentication provider API key"
|
||||||
})}
|
})}
|
||||||
helperText={errors.key}
|
helperText={getFieldError(errors, "key")?.message}
|
||||||
name="key"
|
name="key"
|
||||||
onChange={change}
|
onChange={change}
|
||||||
value={data.key}
|
value={data.key}
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.password}
|
error={!!getFieldError(errors, "password")}
|
||||||
fullWidth
|
fullWidth
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Password"
|
defaultMessage: "Password"
|
||||||
})}
|
})}
|
||||||
helperText={errors.password}
|
helperText={getFieldError(errors, "password")?.message}
|
||||||
name="password"
|
name="password"
|
||||||
onChange={change}
|
onChange={change}
|
||||||
value={data.password}
|
value={data.password}
|
||||||
|
|
|
@ -9,7 +9,8 @@ import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import Hr from "@saleor/components/Hr";
|
import Hr from "@saleor/components/Hr";
|
||||||
import { FormErrors } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
export interface SiteSettingsMailingFormData {
|
export interface SiteSettingsMailingFormData {
|
||||||
defaultMailSenderName: string;
|
defaultMailSenderName: string;
|
||||||
|
@ -18,11 +19,7 @@ export interface SiteSettingsMailingFormData {
|
||||||
}
|
}
|
||||||
interface SiteSettingsMailingProps {
|
interface SiteSettingsMailingProps {
|
||||||
data: SiteSettingsMailingFormData;
|
data: SiteSettingsMailingFormData;
|
||||||
errors: FormErrors<
|
errors: UserError[];
|
||||||
| "defaultMailSenderAddress"
|
|
||||||
| "defaultMailSenderName"
|
|
||||||
| "customerSetPasswordUrl"
|
|
||||||
>;
|
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
@ -68,27 +65,29 @@ const SiteSettingsMailing: React.FC<SiteSettingsMailingProps> = props => {
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.defaultMailSenderAddress}
|
error={!!getFieldError(errors, "defaultMailSenderAddress")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="defaultMailSenderAddress"
|
name="defaultMailSenderAddress"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Mailing email address"
|
defaultMessage: "Mailing email address"
|
||||||
})}
|
})}
|
||||||
helperText={errors.defaultMailSenderAddress}
|
helperText={
|
||||||
|
getFieldError(errors, "defaultMailSenderAddress")?.message
|
||||||
|
}
|
||||||
value={data.defaultMailSenderAddress}
|
value={data.defaultMailSenderAddress}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.defaultMailSenderName}
|
error={!!getFieldError(errors, "defaultMailSenderName")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="defaultMailSenderName"
|
name="defaultMailSenderName"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Mailing email sender"
|
defaultMessage: "Mailing email sender"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
errors.defaultMailSenderName ||
|
getFieldError(errors, "defaultMailSenderName")?.message ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage: 'This will be visible as "from" name',
|
defaultMessage: 'This will be visible as "from" name',
|
||||||
description: "email sender"
|
description: "email sender"
|
||||||
|
@ -102,7 +101,7 @@ const SiteSettingsMailing: React.FC<SiteSettingsMailingProps> = props => {
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.customerSetPasswordUrl}
|
error={!!getFieldError(errors, "customerSetPasswordUrl")}
|
||||||
fullWidth
|
fullWidth
|
||||||
name="customerSetPasswordUrl"
|
name="customerSetPasswordUrl"
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
|
@ -112,7 +111,7 @@ const SiteSettingsMailing: React.FC<SiteSettingsMailingProps> = props => {
|
||||||
defaultMessage: "URL address"
|
defaultMessage: "URL address"
|
||||||
})}
|
})}
|
||||||
helperText={
|
helperText={
|
||||||
errors.customerSetPasswordUrl ||
|
getFieldError(errors, "customerSetPasswordUrl")?.message ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"This URL will be used as a main URL for password resets. It will be sent via email."
|
"This URL will be used as a main URL for password resets. It will be sent via email."
|
||||||
|
|
|
@ -127,9 +127,10 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
||||||
name: maybe(() => shop.name, "")
|
name: maybe(() => shop.name, "")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formErrors = [...errors, ...validationErrors];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
errors={[...errors, ...validationErrors]}
|
|
||||||
initial={initialForm}
|
initial={initialForm}
|
||||||
onSubmit={data => {
|
onSubmit={data => {
|
||||||
const submitFunc = areAddressInputFieldsModified(data)
|
const submitFunc = areAddressInputFieldsModified(data)
|
||||||
|
@ -139,8 +140,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
||||||
}}
|
}}
|
||||||
confirmLeave
|
confirmLeave
|
||||||
>
|
>
|
||||||
{({ change, data, errors: formErrors, hasChanged, submit }) => {
|
{({ change, data, hasChanged, submit }) => {
|
||||||
const siteFormErrors = { ...formErrors };
|
|
||||||
const countryChoices = mapCountriesToChoices(
|
const countryChoices = mapCountriesToChoices(
|
||||||
maybe(() => shop.countries, [])
|
maybe(() => shop.countries, [])
|
||||||
);
|
);
|
||||||
|
@ -169,7 +169,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
<SiteSettingsDetails
|
<SiteSettingsDetails
|
||||||
data={data}
|
data={data}
|
||||||
errors={siteFormErrors}
|
errors={formErrors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
|
@ -187,7 +187,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
<SiteSettingsMailing
|
<SiteSettingsMailing
|
||||||
data={data}
|
data={data}
|
||||||
errors={siteFormErrors}
|
errors={formErrors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
|
@ -208,7 +208,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
|
||||||
data={data}
|
data={data}
|
||||||
displayCountry={displayCountry}
|
displayCountry={displayCountry}
|
||||||
countries={countryChoices}
|
countries={countryChoices}
|
||||||
errors={siteFormErrors}
|
errors={formErrors}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
onCountryChange={handleCountryChange}
|
onCountryChange={handleCountryChange}
|
||||||
|
|
|
@ -16,6 +16,8 @@ import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||||
import Form from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import { buttonMessages, commonMessages } from "@saleor/intl";
|
import { buttonMessages, commonMessages } from "@saleor/intl";
|
||||||
|
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { UserError } from "../../../types";
|
import { UserError } from "../../../types";
|
||||||
|
|
||||||
export interface FormData {
|
export interface FormData {
|
||||||
|
@ -65,13 +67,14 @@ interface StaffAddMemberDialogProps {
|
||||||
const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
||||||
const { confirmButtonState, errors, open, onClose, onConfirm } = props;
|
const { confirmButtonState, errors, open, onClose, onConfirm } = props;
|
||||||
const classes = useStyles(props);
|
const classes = useStyles(props);
|
||||||
|
const dialogErrors = useModalDialogErrors(errors, open);
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} open={open}>
|
<Dialog onClose={onClose} open={open}>
|
||||||
<Form errors={errors} initial={initialForm} onSubmit={onConfirm}>
|
<Form initial={initialForm} onSubmit={onConfirm}>
|
||||||
{({ change, data, errors: formErrors, hasChanged }) => (
|
{({ change, data, hasChanged }) => (
|
||||||
<>
|
<>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
|
@ -82,8 +85,8 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<div className={classes.textFieldGrid}>
|
<div className={classes.textFieldGrid}>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!formErrors.firstName}
|
error={!!getFieldError(dialogErrors, "firstName")}
|
||||||
helperText={formErrors.firstName}
|
helperText={getFieldError(dialogErrors, "firstName")?.message}
|
||||||
label={intl.formatMessage(commonMessages.firstName)}
|
label={intl.formatMessage(commonMessages.firstName)}
|
||||||
name="firstName"
|
name="firstName"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -91,8 +94,8 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!formErrors.lastName}
|
error={!!getFieldError(dialogErrors, "lastName")}
|
||||||
helperText={formErrors.lastName}
|
helperText={getFieldError(dialogErrors, "lastName")?.message}
|
||||||
label={intl.formatMessage(commonMessages.lastName)}
|
label={intl.formatMessage(commonMessages.lastName)}
|
||||||
name="lastName"
|
name="lastName"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -102,9 +105,9 @@ const StaffAddMemberDialog: React.FC<StaffAddMemberDialogProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
error={!!formErrors.email}
|
error={!!getFieldError(dialogErrors, "email")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={formErrors.email}
|
helperText={getFieldError(dialogErrors, "email")?.message}
|
||||||
label={intl.formatMessage(commonMessages.email)}
|
label={intl.formatMessage(commonMessages.email)}
|
||||||
name="email"
|
name="email"
|
||||||
type="email"
|
type="email"
|
||||||
|
|
|
@ -15,6 +15,7 @@ import ConfirmButton, {
|
||||||
} from "@saleor/components/ConfirmButton";
|
} from "@saleor/components/ConfirmButton";
|
||||||
import FormSpacer from "@saleor/components/FormSpacer";
|
import FormSpacer from "@saleor/components/FormSpacer";
|
||||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
|
|
||||||
interface StaffPasswordResetDialogFormData {
|
interface StaffPasswordResetDialogFormData {
|
||||||
newPassword: string;
|
newPassword: string;
|
||||||
|
@ -33,13 +34,13 @@ const initialForm: StaffPasswordResetDialogFormData = {
|
||||||
|
|
||||||
const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
||||||
confirmButtonState,
|
confirmButtonState,
|
||||||
errors: apiErrors,
|
errors,
|
||||||
open,
|
open,
|
||||||
onClose,
|
onClose,
|
||||||
onSubmit
|
onSubmit
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dialogErrors = useModalDialogErrors(apiErrors, open);
|
const dialogErrors = useModalDialogErrors(errors, open);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
|
<Dialog onClose={onClose} open={open} fullWidth maxWidth="sm">
|
||||||
|
@ -49,14 +50,14 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
||||||
description="dialog header"
|
description="dialog header"
|
||||||
/>
|
/>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<Form errors={dialogErrors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ change, data, errors, submit }) => (
|
{({ change, data, submit }) => (
|
||||||
<>
|
<>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.oldPassword}
|
error={!!getFieldError(dialogErrors, "oldPassword")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={errors.oldPassword}
|
helperText={getFieldError(dialogErrors, "oldPassword")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Previous Password",
|
defaultMessage: "Previous Password",
|
||||||
description: "input label"
|
description: "input label"
|
||||||
|
@ -67,10 +68,10 @@ const StaffPasswordResetDialog: React.FC<StaffPasswordResetDialogProps> = ({
|
||||||
/>
|
/>
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
error={!!errors.newPassword}
|
error={!!getFieldError(dialogErrors, "newPassword")}
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={
|
helperText={
|
||||||
errors.newPassword ||
|
getFieldError(dialogErrors, "newPassword") ||
|
||||||
intl.formatMessage({
|
intl.formatMessage({
|
||||||
defaultMessage:
|
defaultMessage:
|
||||||
"New password must be at least 8 characters long"
|
"New password must be at least 8 characters long"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@ import React from "react";
|
||||||
|
|
||||||
import placeholderCollectionImage from "@assets/images/block1.jpg";
|
import placeholderCollectionImage from "@assets/images/block1.jpg";
|
||||||
import placeholderProductImage from "@assets/images/placeholder60x60.png";
|
import placeholderProductImage from "@assets/images/placeholder60x60.png";
|
||||||
|
import { formError } from "@saleor/storybook/misc";
|
||||||
import CollectionDetailsPage, {
|
import CollectionDetailsPage, {
|
||||||
CollectionDetailsPageProps
|
CollectionDetailsPageProps
|
||||||
} from "../../../collections/components/CollectionDetailsPage";
|
} from "../../../collections/components/CollectionDetailsPage";
|
||||||
|
@ -21,6 +22,7 @@ const props: Omit<CollectionDetailsPageProps, "classes"> = {
|
||||||
...pageListProps.default,
|
...pageListProps.default,
|
||||||
collection,
|
collection,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
errors: [],
|
||||||
isFeatured: true,
|
isFeatured: true,
|
||||||
onBack: () => undefined,
|
onBack: () => undefined,
|
||||||
onCollectionRemove: () => undefined,
|
onCollectionRemove: () => undefined,
|
||||||
|
@ -37,6 +39,14 @@ storiesOf("Views / Collections / Collection details", module)
|
||||||
.add("loading", () => (
|
.add("loading", () => (
|
||||||
<CollectionDetailsPage {...props} collection={undefined} disabled={true} />
|
<CollectionDetailsPage {...props} collection={undefined} disabled={true} />
|
||||||
))
|
))
|
||||||
|
.add("form errors", () => (
|
||||||
|
<CollectionDetailsPage
|
||||||
|
{...props}
|
||||||
|
errors={["name", "descriptionJson", "publicationDate", "isPublished"].map(
|
||||||
|
formError
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
))
|
||||||
.add("no products", () => (
|
.add("no products", () => (
|
||||||
<CollectionDetailsPage
|
<CollectionDetailsPage
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -20,7 +20,7 @@ storiesOf("Generics / AddressEdit", module)
|
||||||
>
|
>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<AddressEdit
|
<AddressEdit
|
||||||
errors={{}}
|
errors={[]}
|
||||||
data={transformAddressToForm(customer.defaultBillingAddress)}
|
data={transformAddressToForm(customer.defaultBillingAddress)}
|
||||||
countries={countries.map(c => ({
|
countries={countries.map(c => ({
|
||||||
label: c.label,
|
label: c.label,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import { formError } from "@saleor/storybook/misc";
|
||||||
import MenuCreateDialog, {
|
import MenuCreateDialog, {
|
||||||
MenuCreateDialogProps
|
MenuCreateDialogProps
|
||||||
} from "../../../navigation/components/MenuCreateDialog";
|
} from "../../../navigation/components/MenuCreateDialog";
|
||||||
|
@ -9,6 +10,7 @@ import Decorator from "../../Decorator";
|
||||||
const props: MenuCreateDialogProps = {
|
const props: MenuCreateDialogProps = {
|
||||||
confirmButtonState: "default",
|
confirmButtonState: "default",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
errors: [],
|
||||||
onClose: () => undefined,
|
onClose: () => undefined,
|
||||||
onConfirm: () => undefined,
|
onConfirm: () => undefined,
|
||||||
open: true
|
open: true
|
||||||
|
@ -19,4 +21,7 @@ storiesOf("Navigation / Menu create", module)
|
||||||
.add("default", () => <MenuCreateDialog {...props} />)
|
.add("default", () => <MenuCreateDialog {...props} />)
|
||||||
.add("loading", () => (
|
.add("loading", () => (
|
||||||
<MenuCreateDialog {...props} disabled={true} confirmButtonState="loading" />
|
<MenuCreateDialog {...props} disabled={true} confirmButtonState="loading" />
|
||||||
|
))
|
||||||
|
.add("form errors", () => (
|
||||||
|
<MenuCreateDialog {...props} errors={["name"].map(formError)} />
|
||||||
));
|
));
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { storiesOf } from "@storybook/react";
|
import { storiesOf } from "@storybook/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
|
import { formError } from "@saleor/storybook/misc";
|
||||||
import ProductTypeAttributeEditDialog, {
|
import ProductTypeAttributeEditDialog, {
|
||||||
ProductTypeAttributeEditDialogProps
|
ProductTypeAttributeEditDialogProps
|
||||||
} from "../../../productTypes/components/ProductTypeAttributeEditDialog";
|
} from "../../../productTypes/components/ProductTypeAttributeEditDialog";
|
||||||
|
@ -32,10 +33,6 @@ storiesOf("Product types / Edit attribute", module)
|
||||||
.add("form errors", () => (
|
.add("form errors", () => (
|
||||||
<ProductTypeAttributeEditDialog
|
<ProductTypeAttributeEditDialog
|
||||||
{...props}
|
{...props}
|
||||||
// errors={["name", "values"].map(field => formError(field))}
|
errors={["name", "values"].map(field => formError(field))}
|
||||||
errors={["name", "values"].map(field => ({
|
|
||||||
field,
|
|
||||||
message: "Generic error"
|
|
||||||
}))}
|
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
|
@ -16,6 +16,7 @@ const props: SiteSettingsKeyDialogProps = {
|
||||||
type: AuthorizationKeyType.FACEBOOK
|
type: AuthorizationKeyType.FACEBOOK
|
||||||
},
|
},
|
||||||
onClose: () => undefined,
|
onClose: () => undefined,
|
||||||
|
onSubmit: () => undefined,
|
||||||
open: true
|
open: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { IFilter } from "./components/Filter";
|
||||||
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
import { MultiAutocompleteChoiceType } from "./components/MultiAutocompleteSelectField";
|
||||||
|
|
||||||
export interface UserError {
|
export interface UserError {
|
||||||
field: string;
|
field: string | null;
|
||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +116,6 @@ export interface Node {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FormErrors<TKeys extends string> = Partial<Record<TKeys, string>>;
|
|
||||||
|
|
||||||
export type Pagination = Partial<{
|
export type Pagination = Partial<{
|
||||||
after: string;
|
after: string;
|
||||||
before: string;
|
before: string;
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import { maybe } from "@saleor/misc";
|
|
||||||
import { UserError } from "@saleor/types";
|
import { UserError } from "@saleor/types";
|
||||||
|
|
||||||
export function getFieldError(errors: UserError[], field: string): string {
|
export function getFieldError(errors: UserError[], field: string): UserError {
|
||||||
const err = errors.find(err => err.field === field);
|
return errors.find(err => err.field === field);
|
||||||
|
|
||||||
return maybe(() => err.message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getErrors(errors: UserError[]): string[] {
|
export function getErrors(errors: UserError[]): string[] {
|
||||||
|
|
|
@ -40,7 +40,7 @@ export interface WebhookCreatePageProps {
|
||||||
|
|
||||||
const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
||||||
disabled,
|
disabled,
|
||||||
errors: apiErrors,
|
errors,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
services,
|
services,
|
||||||
fetchServiceAccounts,
|
fetchServiceAccounts,
|
||||||
|
@ -70,8 +70,8 @@ const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form errors={apiErrors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ data, errors, hasChanged, submit, change }) => {
|
{({ data, hasChanged, submit, change }) => {
|
||||||
const handleServiceSelect = createSingleAutocompleteSelectHandler(
|
const handleServiceSelect = createSingleAutocompleteSelectHandler(
|
||||||
change,
|
change,
|
||||||
setSelectedServiceAcccount,
|
setSelectedServiceAcccount,
|
||||||
|
@ -93,11 +93,10 @@ const WebhookCreatePage: React.FC<WebhookCreatePageProps> = ({
|
||||||
<WebhookInfo
|
<WebhookInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
errors={errors}
|
||||||
|
fetchServiceAccounts={fetchServiceAccounts}
|
||||||
serviceDisplayValue={selectedServiceAcccount}
|
serviceDisplayValue={selectedServiceAcccount}
|
||||||
services={servicesChoiceList}
|
services={servicesChoiceList}
|
||||||
fetchServiceAccounts={fetchServiceAccounts}
|
|
||||||
apiErrors={apiErrors}
|
|
||||||
errors={errors}
|
|
||||||
serviceOnChange={handleServiceSelect}
|
serviceOnChange={handleServiceSelect}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -14,17 +14,16 @@ import SingleAutocompleteSelectField, {
|
||||||
} from "@saleor/components/SingleAutocompleteSelectField";
|
} from "@saleor/components/SingleAutocompleteSelectField";
|
||||||
import { ChangeEvent } from "@saleor/hooks/useForm";
|
import { ChangeEvent } from "@saleor/hooks/useForm";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { FormErrors } from "@saleor/types";
|
|
||||||
import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate";
|
import { WebhookCreate_webhookCreate_webhookErrors } from "@saleor/webhooks/types/WebhookCreate";
|
||||||
|
import { getFieldError } from "@saleor/utils/errors";
|
||||||
import { FormData } from "../WebhooksDetailsPage";
|
import { FormData } from "../WebhooksDetailsPage";
|
||||||
|
|
||||||
interface WebhookInfoProps {
|
interface WebhookInfoProps {
|
||||||
apiErrors: WebhookCreate_webhookCreate_webhookErrors[];
|
|
||||||
data: FormData;
|
data: FormData;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
errors: WebhookCreate_webhookCreate_webhookErrors[];
|
||||||
serviceDisplayValue: string;
|
serviceDisplayValue: string;
|
||||||
services: SingleAutocompleteChoiceType[];
|
services: SingleAutocompleteChoiceType[];
|
||||||
errors: FormErrors<"name" | "targetUrl" | "secretKey">;
|
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
serviceOnChange: (event: ChangeEvent) => void;
|
serviceOnChange: (event: ChangeEvent) => void;
|
||||||
fetchServiceAccounts: (data: string) => void;
|
fetchServiceAccounts: (data: string) => void;
|
||||||
|
@ -45,7 +44,6 @@ const useStyles = makeStyles(
|
||||||
);
|
);
|
||||||
|
|
||||||
const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
||||||
apiErrors,
|
|
||||||
data,
|
data,
|
||||||
disabled,
|
disabled,
|
||||||
services,
|
services,
|
||||||
|
@ -58,7 +56,7 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
||||||
const classes = useStyles({});
|
const classes = useStyles({});
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const serviceAccountsError =
|
const serviceAccountsError =
|
||||||
apiErrors.filter(error => error.field === null).length > 0;
|
errors.filter(error => error.field === null).length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
|
@ -74,8 +72,8 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
||||||
</Typography>
|
</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.name}
|
error={!!getFieldError(errors, "name")}
|
||||||
helperText={errors.name}
|
helperText={getFieldError(errors, "name")?.message}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Webhook Name",
|
defaultMessage: "Webhook Name",
|
||||||
description: "webhook"
|
description: "webhook"
|
||||||
|
@ -117,11 +115,14 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.targetUrl}
|
error={!!getFieldError(errors, "targetUrl")}
|
||||||
helperText={intl.formatMessage({
|
helperText={
|
||||||
defaultMessage: "This URL will receive webhook POST requests",
|
getFieldError(errors, "targetUrl")?.message ||
|
||||||
description: "webhook target url help text"
|
intl.formatMessage({
|
||||||
})}
|
defaultMessage: "This URL will receive webhook POST requests",
|
||||||
|
description: "webhook target url help text"
|
||||||
|
})
|
||||||
|
}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Target URL",
|
defaultMessage: "Target URL",
|
||||||
description: "webhook"
|
description: "webhook"
|
||||||
|
@ -134,12 +135,15 @@ const WebhookInfo: React.FC<WebhookInfoProps> = ({
|
||||||
<FormSpacer />
|
<FormSpacer />
|
||||||
<TextField
|
<TextField
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
error={!!errors.secretKey}
|
error={!!getFieldError(errors, "secretKey")}
|
||||||
helperText={intl.formatMessage({
|
helperText={
|
||||||
defaultMessage:
|
getFieldError(errors, "secretKey")?.message ||
|
||||||
"secret key is used to create a hash signature with each payload. *optional field",
|
intl.formatMessage({
|
||||||
description: "webhook secret key help text"
|
defaultMessage:
|
||||||
})}
|
"secret key is used to create a hash signature with each payload. *optional field",
|
||||||
|
description: "webhook secret key help text"
|
||||||
|
})
|
||||||
|
}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Secrect Key",
|
defaultMessage: "Secrect Key",
|
||||||
description: "webhook"
|
description: "webhook"
|
||||||
|
|
|
@ -45,7 +45,7 @@ export interface WebhooksDetailsPageProps {
|
||||||
|
|
||||||
const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
||||||
disabled,
|
disabled,
|
||||||
errors: apiErrors,
|
errors,
|
||||||
webhook,
|
webhook,
|
||||||
saveButtonBarState,
|
saveButtonBarState,
|
||||||
services,
|
services,
|
||||||
|
@ -81,8 +81,8 @@ const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<Form errors={apiErrors} initial={initialForm} onSubmit={onSubmit}>
|
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||||
{({ data, errors, hasChanged, submit, change }) => {
|
{({ data, hasChanged, submit, change }) => {
|
||||||
const handleServiceSelect = createSingleAutocompleteSelectHandler(
|
const handleServiceSelect = createSingleAutocompleteSelectHandler(
|
||||||
change,
|
change,
|
||||||
setSelectedServiceAcccounts,
|
setSelectedServiceAcccounts,
|
||||||
|
@ -107,7 +107,6 @@ const WebhooksDetailsPage: React.FC<WebhooksDetailsPageProps> = ({
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<WebhookInfo
|
<WebhookInfo
|
||||||
apiErrors={apiErrors}
|
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
serviceDisplayValue={selectedServiceAcccounts}
|
serviceDisplayValue={selectedServiceAcccounts}
|
||||||
|
|
Loading…
Reference in a new issue