2020-11-04 10:48:49 +00:00
|
|
|
import { OutputData } from "@editorjs/editorjs";
|
|
|
|
import { MetadataFormData } from "@saleor/components/Metadata";
|
|
|
|
import { RichTextEditorChange } from "@saleor/components/RichTextEditor";
|
2020-11-19 14:42:14 +00:00
|
|
|
import { PageTypeFragment } from "@saleor/fragments/types/PageTypeFragment";
|
2020-11-06 10:54:03 +00:00
|
|
|
import useForm, { FormChange, SubmitPromise } from "@saleor/hooks/useForm";
|
2020-11-19 14:42:14 +00:00
|
|
|
import useFormset, { FormsetChange } from "@saleor/hooks/useFormset";
|
|
|
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
|
|
|
import {
|
|
|
|
PageDetails_page,
|
|
|
|
PageDetails_page_pageType
|
|
|
|
} from "@saleor/pages/types/PageDetails";
|
|
|
|
import { getAttributeInputFromPage } from "@saleor/pages/utils/data";
|
|
|
|
import { createPageTypeSelectHandler } from "@saleor/pages/utils/handlers";
|
|
|
|
import {
|
|
|
|
createAttributeChangeHandler,
|
|
|
|
createAttributeMultiChangeHandler
|
|
|
|
} from "@saleor/products/utils/handlers";
|
2020-11-04 10:48:49 +00:00
|
|
|
import getPublicationData from "@saleor/utils/data/getPublicationData";
|
|
|
|
import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit";
|
|
|
|
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
|
|
|
import getMetadata from "@saleor/utils/metadata/getMetadata";
|
|
|
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
|
|
|
import useRichText from "@saleor/utils/richText/useRichText";
|
|
|
|
import React from "react";
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
import { PageAttributeInput, PageAttributeInputData } from "../PageAttributes";
|
|
|
|
|
2020-11-04 10:48:49 +00:00
|
|
|
export interface PageFormData extends MetadataFormData {
|
|
|
|
isPublished: boolean;
|
|
|
|
publicationDate: string;
|
|
|
|
seoDescription: string;
|
|
|
|
seoTitle: string;
|
|
|
|
slug: string;
|
|
|
|
title: string;
|
2020-11-19 14:42:14 +00:00
|
|
|
pageType: string;
|
2020-11-04 10:48:49 +00:00
|
|
|
}
|
|
|
|
export interface PageData extends PageFormData {
|
2020-11-19 14:42:14 +00:00
|
|
|
attributes: PageAttributeInput[];
|
2020-11-04 10:48:49 +00:00
|
|
|
content: OutputData;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface PageUpdateHandlers {
|
|
|
|
changeMetadata: FormChange;
|
|
|
|
changeContent: RichTextEditorChange;
|
2020-11-19 14:42:14 +00:00
|
|
|
selectPageType: FormChange;
|
|
|
|
changeAttribute: FormsetChange<string>;
|
|
|
|
changeAttributeMulti: FormsetChange<string>;
|
2020-11-04 10:48:49 +00:00
|
|
|
}
|
|
|
|
export interface UsePageUpdateFormResult {
|
|
|
|
change: FormChange;
|
|
|
|
data: PageData;
|
2020-11-19 14:42:14 +00:00
|
|
|
pageType: PageTypeFragment;
|
2020-11-04 10:48:49 +00:00
|
|
|
handlers: PageUpdateHandlers;
|
|
|
|
hasChanged: boolean;
|
|
|
|
submit: () => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface PageFormProps {
|
|
|
|
children: (props: UsePageUpdateFormResult) => React.ReactNode;
|
|
|
|
page: PageDetails_page;
|
2020-11-19 14:42:14 +00:00
|
|
|
pageTypes?: PageDetails_page_pageType[];
|
2020-11-06 10:54:03 +00:00
|
|
|
onSubmit: (data: PageData) => SubmitPromise;
|
2020-11-04 10:48:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function usePageForm(
|
|
|
|
page: PageDetails_page,
|
2020-11-19 14:42:14 +00:00
|
|
|
onSubmit: (data: PageData) => SubmitPromise,
|
|
|
|
pageTypes?: PageDetails_page_pageType[]
|
2020-11-04 10:48:49 +00:00
|
|
|
): UsePageUpdateFormResult {
|
|
|
|
const [changed, setChanged] = React.useState(false);
|
|
|
|
const triggerChange = () => setChanged(true);
|
|
|
|
|
|
|
|
const pageExists = page !== null;
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
const attributesFromPage = React.useMemo(
|
|
|
|
() => getAttributeInputFromPage(page),
|
|
|
|
[page]
|
|
|
|
);
|
|
|
|
|
|
|
|
const {
|
|
|
|
change: changeAttributeData,
|
|
|
|
data: attributes,
|
|
|
|
set: setAttributeData
|
|
|
|
} = useFormset<PageAttributeInputData>(attributesFromPage || []);
|
|
|
|
|
2020-11-04 10:48:49 +00:00
|
|
|
const form = useForm<PageFormData>({
|
|
|
|
isPublished: page?.isPublished,
|
|
|
|
metadata: pageExists ? page?.metadata?.map(mapMetadataItemToInput) : [],
|
2020-11-19 14:42:14 +00:00
|
|
|
pageType: page?.pageType.id || "",
|
2020-11-04 10:48:49 +00:00
|
|
|
privateMetadata: pageExists
|
|
|
|
? page?.privateMetadata?.map(mapMetadataItemToInput)
|
|
|
|
: [],
|
|
|
|
publicationDate: page?.publicationDate || "",
|
|
|
|
seoDescription: page?.seoDescription || "",
|
|
|
|
seoTitle: page?.seoTitle || "",
|
|
|
|
slug: page?.slug || "",
|
|
|
|
title: page?.title || ""
|
|
|
|
});
|
|
|
|
const [content, changeContent] = useRichText({
|
|
|
|
initial: pageExists ? page?.contentJson : null,
|
|
|
|
triggerChange
|
|
|
|
});
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
const [pageType, setPageType] = useStateFromProps<PageTypeFragment>(
|
|
|
|
page?.pageType || null
|
|
|
|
);
|
|
|
|
|
2020-11-04 10:48:49 +00:00
|
|
|
const {
|
|
|
|
isMetadataModified,
|
|
|
|
isPrivateMetadataModified,
|
|
|
|
makeChangeHandler: makeMetadataChangeHandler
|
|
|
|
} = useMetadataChangeTrigger();
|
|
|
|
|
|
|
|
const handleChange: FormChange = (event, cb) => {
|
|
|
|
form.change(event, cb);
|
|
|
|
triggerChange();
|
|
|
|
};
|
|
|
|
const changeMetadata = makeMetadataChangeHandler(handleChange);
|
2020-11-19 14:42:14 +00:00
|
|
|
const selectPageType = createPageTypeSelectHandler(
|
|
|
|
handleChange,
|
|
|
|
setAttributeData,
|
|
|
|
setPageType,
|
|
|
|
pageTypes
|
|
|
|
);
|
|
|
|
const changeAttribute = createAttributeChangeHandler(
|
|
|
|
changeAttributeData,
|
|
|
|
triggerChange
|
|
|
|
);
|
|
|
|
const changeAttributeMulti = createAttributeMultiChangeHandler(
|
|
|
|
changeAttributeData,
|
|
|
|
attributes,
|
|
|
|
triggerChange
|
|
|
|
);
|
2020-11-04 10:48:49 +00:00
|
|
|
|
|
|
|
// Need to make it function to always have content.current up to date
|
|
|
|
const getData = (): PageData => ({
|
|
|
|
...form.data,
|
2020-11-19 14:42:14 +00:00
|
|
|
attributes,
|
2020-11-04 10:48:49 +00:00
|
|
|
content: content.current
|
|
|
|
});
|
|
|
|
|
|
|
|
const getSubmitData = (): PageData => ({
|
|
|
|
...getData(),
|
|
|
|
...getMetadata(form.data, isMetadataModified, isPrivateMetadataModified),
|
|
|
|
...getPublicationData(form.data)
|
|
|
|
});
|
|
|
|
|
|
|
|
const submit = () =>
|
|
|
|
pageExists
|
|
|
|
? handleFormSubmit(getSubmitData(), onSubmit, setChanged)
|
|
|
|
: onSubmit(getSubmitData());
|
|
|
|
|
|
|
|
return {
|
|
|
|
change: handleChange,
|
|
|
|
data: getData(),
|
|
|
|
handlers: {
|
2020-11-19 14:42:14 +00:00
|
|
|
changeAttribute,
|
|
|
|
changeAttributeMulti,
|
2020-11-04 10:48:49 +00:00
|
|
|
changeContent,
|
2020-11-19 14:42:14 +00:00
|
|
|
changeMetadata,
|
|
|
|
selectPageType
|
2020-11-04 10:48:49 +00:00
|
|
|
},
|
|
|
|
hasChanged: changed,
|
2020-11-19 14:42:14 +00:00
|
|
|
pageType,
|
2020-11-04 10:48:49 +00:00
|
|
|
submit
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
const PageForm: React.FC<PageFormProps> = ({
|
|
|
|
children,
|
|
|
|
page,
|
|
|
|
pageTypes,
|
|
|
|
onSubmit
|
|
|
|
}) => {
|
|
|
|
const props = usePageForm(page, onSubmit, pageTypes);
|
2020-11-04 10:48:49 +00:00
|
|
|
|
|
|
|
return <form onSubmit={props.submit}>{children(props)}</form>;
|
|
|
|
};
|
|
|
|
|
|
|
|
PageForm.displayName = "PageForm";
|
|
|
|
export default PageForm;
|