Add metadata editor to product creator

This commit is contained in:
dominik-zeglen 2020-08-31 16:58:07 +02:00
parent 7bb5ca231b
commit dde82e0756
3 changed files with 111 additions and 6 deletions

View file

@ -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

View file

@ -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 (
<> <>

View 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;