Add metadata editor to product creator
This commit is contained in:
parent
7bb5ca231b
commit
dde82e0756
3 changed files with 111 additions and 6 deletions
|
@ -4,6 +4,7 @@ import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
import Form from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import Metadata, { MetadataFormData } from "@saleor/components/Metadata";
|
||||||
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
|
@ -25,6 +26,7 @@ import { SearchProductTypes_search_edges_node_productAttributes } from "@saleor/
|
||||||
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
|
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
|
||||||
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
||||||
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
||||||
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
import { ContentState, convertToRaw, RawDraftContentState } from "draft-js";
|
import { ContentState, convertToRaw, RawDraftContentState } from "draft-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
@ -45,7 +47,7 @@ import ProductPricing from "../ProductPricing";
|
||||||
import ProductShipping from "../ProductShipping/ProductShipping";
|
import ProductShipping from "../ProductShipping/ProductShipping";
|
||||||
import ProductStocks, { ProductStockInput } from "../ProductStocks";
|
import ProductStocks, { ProductStockInput } from "../ProductStocks";
|
||||||
|
|
||||||
interface FormData {
|
interface FormData extends MetadataFormData {
|
||||||
basePrice: number;
|
basePrice: number;
|
||||||
publicationDate: string;
|
publicationDate: string;
|
||||||
category: string;
|
category: string;
|
||||||
|
@ -133,6 +135,13 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
const initialDescription = React.useRef(
|
const initialDescription = React.useRef(
|
||||||
convertToRaw(ContentState.createFromText(""))
|
convertToRaw(ContentState.createFromText(""))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
isMetadataModified,
|
||||||
|
isPrivateMetadataModified,
|
||||||
|
makeChangeHandler: makeMetadataChangeHandler
|
||||||
|
} = useMetadataChangeTrigger();
|
||||||
|
|
||||||
const initialData: FormData = {
|
const initialData: FormData = {
|
||||||
basePrice: 0,
|
basePrice: 0,
|
||||||
category: "",
|
category: "",
|
||||||
|
@ -140,7 +149,9 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
collections: [],
|
collections: [],
|
||||||
description: {} as any,
|
description: {} as any,
|
||||||
isPublished: false,
|
isPublished: false,
|
||||||
|
metadata: [],
|
||||||
name: "",
|
name: "",
|
||||||
|
privateMetadata: [],
|
||||||
productType: "",
|
productType: "",
|
||||||
publicationDate: "",
|
publicationDate: "",
|
||||||
seoDescription: "",
|
seoDescription: "",
|
||||||
|
@ -168,12 +179,20 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
const collections = getChoices(collectionChoiceList);
|
const collections = getChoices(collectionChoiceList);
|
||||||
const productTypes = getChoices(productTypeChoiceList);
|
const productTypes = getChoices(productTypeChoiceList);
|
||||||
|
|
||||||
const handleSubmit = (data: FormData) =>
|
const handleSubmit = (data: FormData) => {
|
||||||
|
const metadata = isMetadataModified ? data.metadata : undefined;
|
||||||
|
const privateMetadata = isPrivateMetadataModified
|
||||||
|
? data.privateMetadata
|
||||||
|
: undefined;
|
||||||
|
|
||||||
onSubmit({
|
onSubmit({
|
||||||
|
...data,
|
||||||
attributes,
|
attributes,
|
||||||
stocks,
|
metadata,
|
||||||
...data
|
privateMetadata,
|
||||||
|
stocks
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
|
<Form onSubmit={handleSubmit} initial={initialData} confirmLeave>
|
||||||
|
@ -212,6 +231,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
productTypeChoiceList
|
productTypeChoiceList
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const changeMetadata = makeMetadataChangeHandler(change);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
|
@ -296,6 +317,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
|
||||||
loading={disabled}
|
loading={disabled}
|
||||||
onChange={change}
|
onChange={change}
|
||||||
/>
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<Metadata data={data} onChange={changeMetadata} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<ProductOrganization
|
<ProductOrganization
|
||||||
|
|
|
@ -6,6 +6,11 @@ import useShop from "@saleor/hooks/useShop";
|
||||||
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
import useCategorySearch from "@saleor/searches/useCategorySearch";
|
||||||
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
|
||||||
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
|
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
|
||||||
|
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
|
||||||
|
import {
|
||||||
|
useMetadataUpdate,
|
||||||
|
usePrivateMetadataUpdate
|
||||||
|
} from "@saleor/utils/metadata/updateMetadata";
|
||||||
import { useWarehouseList } from "@saleor/warehouses/queries";
|
import { useWarehouseList } from "@saleor/warehouses/queries";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
@ -49,6 +54,8 @@ export const ProductCreateView: React.FC = () => {
|
||||||
first: 50
|
first: 50
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const [updateMetadata] = useMetadataUpdate({});
|
||||||
|
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
||||||
|
|
||||||
const handleBack = () => navigate(productListUrl());
|
const handleBack = () => navigate(productListUrl());
|
||||||
|
|
||||||
|
@ -66,8 +73,8 @@ export const ProductCreateView: React.FC = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleSubmit = (formData: ProductCreatePageSubmitData) => {
|
const handleCreate = async (formData: ProductCreatePageSubmitData) => {
|
||||||
productCreate({
|
const result = await productCreate({
|
||||||
variables: {
|
variables: {
|
||||||
attributes: formData.attributes.map(attribute => ({
|
attributes: formData.attributes.map(attribute => ({
|
||||||
id: attribute.id,
|
id: attribute.id,
|
||||||
|
@ -96,7 +103,14 @@ export const ProductCreateView: React.FC = () => {
|
||||||
weight: weight(formData.weight)
|
weight: weight(formData.weight)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return result.data.productCreate?.product?.id || null;
|
||||||
};
|
};
|
||||||
|
const handleSubmit = createMetadataCreateHandler(
|
||||||
|
handleCreate,
|
||||||
|
updateMetadata,
|
||||||
|
updatePrivateMetadata
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
68
src/utils/handlers/metadataCreateHandler.ts
Normal file
68
src/utils/handlers/metadataCreateHandler.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { MetadataFormData } from "@saleor/components/Metadata/types";
|
||||||
|
import { MutationFunction } from "react-apollo";
|
||||||
|
|
||||||
|
import {
|
||||||
|
UpdateMetadata,
|
||||||
|
UpdateMetadataVariables
|
||||||
|
} from "../metadata/types/UpdateMetadata";
|
||||||
|
import {
|
||||||
|
UpdatePrivateMetadata,
|
||||||
|
UpdatePrivateMetadataVariables
|
||||||
|
} from "../metadata/types/UpdatePrivateMetadata";
|
||||||
|
|
||||||
|
function createMetadataCreateHandler<T extends MetadataFormData>(
|
||||||
|
create: (data: T) => Promise<string>,
|
||||||
|
setMetadata: MutationFunction<UpdateMetadata, UpdateMetadataVariables>,
|
||||||
|
setPrivateMetadata: MutationFunction<
|
||||||
|
UpdatePrivateMetadata,
|
||||||
|
UpdatePrivateMetadataVariables
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
return async (data: T) => {
|
||||||
|
const id = await create(data);
|
||||||
|
|
||||||
|
if (id === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.metadata.length > 0) {
|
||||||
|
const updateMetaResult = await setMetadata({
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
input: data.metadata,
|
||||||
|
keysToDelete: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const updateMetaErrors = [
|
||||||
|
...(updateMetaResult.data.deleteMetadata.errors || []),
|
||||||
|
...(updateMetaResult.data.updateMetadata.errors || [])
|
||||||
|
];
|
||||||
|
|
||||||
|
if (updateMetaErrors.length > 0) {
|
||||||
|
return updateMetaErrors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.privateMetadata.length > 0) {
|
||||||
|
const updatePrivateMetaResult = await setPrivateMetadata({
|
||||||
|
variables: {
|
||||||
|
id,
|
||||||
|
input: data.privateMetadata,
|
||||||
|
keysToDelete: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatePrivateMetaErrors = [
|
||||||
|
...(updatePrivateMetaResult.data.deletePrivateMetadata.errors || []),
|
||||||
|
...(updatePrivateMetaResult.data.updatePrivateMetadata.errors || [])
|
||||||
|
];
|
||||||
|
|
||||||
|
if (updatePrivateMetaErrors.length > 0) {
|
||||||
|
return updatePrivateMetaErrors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createMetadataCreateHandler;
|
Loading…
Reference in a new issue