2020-11-04 10:48:49 +00:00
|
|
|
import { OutputData } from "@editorjs/editorjs";
|
2021-01-12 11:13:02 +00:00
|
|
|
import { getAttributesDisplayData } from "@saleor/attributes/utils/data";
|
2021-01-18 15:37:38 +00:00
|
|
|
import {
|
|
|
|
createAttributeChangeHandler,
|
|
|
|
createAttributeFileChangeHandler,
|
|
|
|
createAttributeMultiChangeHandler,
|
|
|
|
createAttributeReferenceChangeHandler,
|
2021-01-20 16:37:36 +00:00
|
|
|
createAttributeValueReorderHandler,
|
|
|
|
createFetchMoreReferencesHandler,
|
|
|
|
createFetchReferencesHandler
|
2021-01-18 15:37:38 +00:00
|
|
|
} from "@saleor/attributes/utils/handlers";
|
2020-12-16 10:53:28 +00:00
|
|
|
import { AttributeInput } from "@saleor/components/Attributes";
|
2020-11-04 10:48:49 +00:00
|
|
|
import { MetadataFormData } from "@saleor/components/Metadata";
|
|
|
|
import { RichTextEditorChange } from "@saleor/components/RichTextEditor";
|
2020-11-06 10:54:03 +00:00
|
|
|
import useForm, { FormChange, SubmitPromise } from "@saleor/hooks/useForm";
|
2020-12-16 10:53:28 +00:00
|
|
|
import useFormset, {
|
|
|
|
FormsetChange,
|
|
|
|
FormsetData
|
|
|
|
} from "@saleor/hooks/useFormset";
|
2020-11-19 14:42:14 +00:00
|
|
|
import {
|
|
|
|
PageDetails_page,
|
|
|
|
PageDetails_page_pageType
|
|
|
|
} from "@saleor/pages/types/PageDetails";
|
2021-06-08 07:05:19 +00:00
|
|
|
import { PageType_pageType } from "@saleor/pages/types/PageType";
|
|
|
|
import {
|
|
|
|
getAttributeInputFromPage,
|
|
|
|
getAttributeInputFromPageType
|
|
|
|
} from "@saleor/pages/utils/data";
|
2020-11-19 14:42:14 +00:00
|
|
|
import { createPageTypeSelectHandler } from "@saleor/pages/utils/handlers";
|
2021-01-12 11:13:02 +00:00
|
|
|
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
|
2021-06-08 07:05:19 +00:00
|
|
|
import { SearchPageTypes_search_edges_node } from "@saleor/searches/types/SearchPageTypes";
|
2021-01-20 16:37:36 +00:00
|
|
|
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
|
|
|
|
import { FetchMoreProps, ReorderEvent } from "@saleor/types";
|
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";
|
2020-12-17 09:25:16 +00:00
|
|
|
import React from "react";
|
2020-11-19 14:42:14 +00:00
|
|
|
|
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;
|
2021-06-08 07:05:19 +00:00
|
|
|
pageType: PageType_pageType | PageDetails_page_pageType;
|
2020-11-04 10:48:49 +00:00
|
|
|
}
|
|
|
|
export interface PageData extends PageFormData {
|
2020-12-16 10:53:28 +00:00
|
|
|
attributes: AttributeInput[];
|
|
|
|
content: OutputData;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface PageSubmitData extends PageFormData {
|
|
|
|
attributes: AttributeInput[];
|
|
|
|
attributesWithNewFileValue: FormsetData<null, File>;
|
2020-11-04 10:48:49 +00:00
|
|
|
content: OutputData;
|
|
|
|
}
|
|
|
|
|
2021-01-12 11:13:02 +00:00
|
|
|
export interface PageUpdateHandlers {
|
2020-11-04 10:48:49 +00:00
|
|
|
changeMetadata: FormChange;
|
|
|
|
changeContent: RichTextEditorChange;
|
2020-11-19 14:42:14 +00:00
|
|
|
selectPageType: FormChange;
|
2020-12-16 10:53:28 +00:00
|
|
|
selectAttribute: FormsetChange<string>;
|
|
|
|
selectAttributeMulti: FormsetChange<string>;
|
2021-01-12 11:13:02 +00:00
|
|
|
selectAttributeReference: FormsetChange<string[]>;
|
2020-12-16 10:53:28 +00:00
|
|
|
selectAttributeFile: FormsetChange<File>;
|
2021-01-18 15:37:38 +00:00
|
|
|
reorderAttributeValue: FormsetChange<ReorderEvent>;
|
2021-01-20 16:37:36 +00:00
|
|
|
fetchReferences: (value: string) => void;
|
|
|
|
fetchMoreReferences: FetchMoreProps;
|
2020-11-04 10:48:49 +00:00
|
|
|
}
|
|
|
|
export interface UsePageUpdateFormResult {
|
|
|
|
change: FormChange;
|
|
|
|
data: PageData;
|
2021-07-12 08:34:13 +00:00
|
|
|
valid: boolean;
|
2020-11-04 10:48:49 +00:00
|
|
|
handlers: PageUpdateHandlers;
|
|
|
|
hasChanged: boolean;
|
|
|
|
submit: () => void;
|
|
|
|
}
|
|
|
|
|
2021-01-20 16:37:36 +00:00
|
|
|
export interface UsePageFormOpts {
|
2021-06-08 07:05:19 +00:00
|
|
|
pageTypes?: SearchPageTypes_search_edges_node[];
|
2021-01-20 16:37:36 +00:00
|
|
|
referencePages: SearchPages_search_edges_node[];
|
|
|
|
referenceProducts: SearchProducts_search_edges_node[];
|
|
|
|
fetchReferencePages?: (data: string) => void;
|
|
|
|
fetchMoreReferencePages?: FetchMoreProps;
|
|
|
|
fetchReferenceProducts?: (data: string) => void;
|
|
|
|
fetchMoreReferenceProducts?: FetchMoreProps;
|
|
|
|
assignReferencesAttributeId?: string;
|
2021-06-08 07:05:19 +00:00
|
|
|
selectedPageType?: PageType_pageType;
|
|
|
|
onSelectPageType: (pageTypeId: string) => void;
|
2021-01-20 16:37:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface PageFormProps extends UsePageFormOpts {
|
2020-11-04 10:48:49 +00:00
|
|
|
children: (props: UsePageUpdateFormResult) => React.ReactNode;
|
|
|
|
page: PageDetails_page;
|
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,
|
2021-01-20 16:37:36 +00:00
|
|
|
opts: UsePageFormOpts
|
2020-11-04 10:48:49 +00:00
|
|
|
): UsePageUpdateFormResult {
|
|
|
|
const [changed, setChanged] = React.useState(false);
|
|
|
|
const triggerChange = () => setChanged(true);
|
|
|
|
|
|
|
|
const pageExists = page !== null;
|
|
|
|
|
2021-06-08 07:05:19 +00:00
|
|
|
const attributes = useFormset(
|
|
|
|
pageExists
|
|
|
|
? getAttributeInputFromPage(page)
|
|
|
|
: opts.selectedPageType
|
|
|
|
? getAttributeInputFromPageType(opts.selectedPageType)
|
|
|
|
: []
|
|
|
|
);
|
2020-12-16 10:53:28 +00:00
|
|
|
const attributesWithNewFileValue = useFormset<null, File>([]);
|
2020-11-19 14:42:14 +00:00
|
|
|
|
2020-11-04 10:48:49 +00:00
|
|
|
const form = useForm<PageFormData>({
|
|
|
|
isPublished: page?.isPublished,
|
|
|
|
metadata: pageExists ? page?.metadata?.map(mapMetadataItemToInput) : [],
|
2021-06-08 07:05:19 +00:00
|
|
|
pageType: null,
|
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({
|
2021-03-02 10:24:25 +00:00
|
|
|
initial: pageExists ? page?.content : null,
|
2020-11-04 10:48:49 +00:00
|
|
|
triggerChange
|
|
|
|
});
|
|
|
|
|
|
|
|
const {
|
|
|
|
isMetadataModified,
|
|
|
|
isPrivateMetadataModified,
|
|
|
|
makeChangeHandler: makeMetadataChangeHandler
|
|
|
|
} = useMetadataChangeTrigger();
|
|
|
|
|
|
|
|
const handleChange: FormChange = (event, cb) => {
|
|
|
|
form.change(event, cb);
|
|
|
|
triggerChange();
|
|
|
|
};
|
|
|
|
const changeMetadata = makeMetadataChangeHandler(handleChange);
|
2021-06-08 07:05:19 +00:00
|
|
|
const handlePageTypeSelect = createPageTypeSelectHandler(
|
|
|
|
opts.onSelectPageType,
|
|
|
|
triggerChange
|
2020-11-19 14:42:14 +00:00
|
|
|
);
|
2020-12-16 10:53:28 +00:00
|
|
|
const handleAttributeChange = createAttributeChangeHandler(
|
|
|
|
attributes.change,
|
2020-11-19 14:42:14 +00:00
|
|
|
triggerChange
|
|
|
|
);
|
2020-12-16 10:53:28 +00:00
|
|
|
const handleAttributeMultiChange = createAttributeMultiChangeHandler(
|
|
|
|
attributes.change,
|
|
|
|
attributes.data,
|
2020-11-19 14:42:14 +00:00
|
|
|
triggerChange
|
|
|
|
);
|
2021-01-12 11:13:02 +00:00
|
|
|
const handleAttributeReferenceChange = createAttributeReferenceChangeHandler(
|
|
|
|
attributes.change,
|
|
|
|
triggerChange
|
|
|
|
);
|
2021-01-20 16:37:36 +00:00
|
|
|
const handleFetchReferences = createFetchReferencesHandler(
|
|
|
|
attributes.data,
|
|
|
|
opts.assignReferencesAttributeId,
|
|
|
|
opts.fetchReferencePages,
|
|
|
|
opts.fetchReferenceProducts
|
|
|
|
);
|
|
|
|
const handleFetchMoreReferences = createFetchMoreReferencesHandler(
|
|
|
|
attributes.data,
|
|
|
|
opts.assignReferencesAttributeId,
|
|
|
|
opts.fetchMoreReferencePages,
|
|
|
|
opts.fetchMoreReferenceProducts
|
|
|
|
);
|
2020-12-16 10:53:28 +00:00
|
|
|
const handleAttributeFileChange = createAttributeFileChangeHandler(
|
|
|
|
attributes.change,
|
|
|
|
attributesWithNewFileValue.data,
|
|
|
|
attributesWithNewFileValue.add,
|
|
|
|
attributesWithNewFileValue.change,
|
|
|
|
triggerChange
|
|
|
|
);
|
2021-01-18 15:37:38 +00:00
|
|
|
const handleAttributeValueReorder = createAttributeValueReorderHandler(
|
|
|
|
attributes.change,
|
|
|
|
attributes.data,
|
|
|
|
triggerChange
|
|
|
|
);
|
2020-12-16 10:53:28 +00:00
|
|
|
|
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-12-16 10:53:28 +00:00
|
|
|
attributes: getAttributesDisplayData(
|
|
|
|
attributes.data,
|
2021-01-12 11:13:02 +00:00
|
|
|
attributesWithNewFileValue.data,
|
2021-01-20 16:37:36 +00:00
|
|
|
opts.referencePages,
|
|
|
|
opts.referenceProducts
|
2020-12-16 10:53:28 +00:00
|
|
|
),
|
2021-06-08 07:05:19 +00:00
|
|
|
content: content.current,
|
|
|
|
pageType: pageExists ? page?.pageType : opts.selectedPageType
|
2020-11-04 10:48:49 +00:00
|
|
|
});
|
|
|
|
|
2020-12-16 10:53:28 +00:00
|
|
|
const getSubmitData = (): PageSubmitData => ({
|
2020-11-04 10:48:49 +00:00
|
|
|
...getData(),
|
|
|
|
...getMetadata(form.data, isMetadataModified, isPrivateMetadataModified),
|
2020-12-16 10:53:28 +00:00
|
|
|
...getPublicationData(form.data),
|
|
|
|
attributesWithNewFileValue: attributesWithNewFileValue.data
|
2020-11-04 10:48:49 +00:00
|
|
|
});
|
|
|
|
|
2020-12-17 09:25:16 +00:00
|
|
|
const handleSubmit = async (data: PageData) => {
|
|
|
|
const errors = await onSubmit(data);
|
|
|
|
|
|
|
|
if (!errors?.length && pageExists) {
|
|
|
|
attributesWithNewFileValue.set([]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return errors;
|
|
|
|
};
|
|
|
|
|
2020-11-04 10:48:49 +00:00
|
|
|
const submit = () =>
|
|
|
|
pageExists
|
2020-12-17 09:25:16 +00:00
|
|
|
? handleFormSubmit(getSubmitData(), handleSubmit, setChanged)
|
2020-11-04 10:48:49 +00:00
|
|
|
: onSubmit(getSubmitData());
|
|
|
|
|
2021-07-12 08:34:13 +00:00
|
|
|
const valid = !!opts.selectedPageType;
|
|
|
|
|
2020-11-04 10:48:49 +00:00
|
|
|
return {
|
|
|
|
change: handleChange,
|
|
|
|
data: getData(),
|
2021-07-12 08:34:13 +00:00
|
|
|
valid,
|
2020-11-04 10:48:49 +00:00
|
|
|
handlers: {
|
|
|
|
changeContent,
|
2020-11-19 14:42:14 +00:00
|
|
|
changeMetadata,
|
2021-01-20 16:37:36 +00:00
|
|
|
fetchMoreReferences: handleFetchMoreReferences,
|
|
|
|
fetchReferences: handleFetchReferences,
|
2021-01-18 15:37:38 +00:00
|
|
|
reorderAttributeValue: handleAttributeValueReorder,
|
2020-12-16 10:53:28 +00:00
|
|
|
selectAttribute: handleAttributeChange,
|
|
|
|
selectAttributeFile: handleAttributeFileChange,
|
|
|
|
selectAttributeMulti: handleAttributeMultiChange,
|
2021-01-12 11:13:02 +00:00
|
|
|
selectAttributeReference: handleAttributeReferenceChange,
|
2021-06-08 07:05:19 +00:00
|
|
|
selectPageType: handlePageTypeSelect
|
2020-11-04 10:48:49 +00:00
|
|
|
},
|
|
|
|
hasChanged: changed,
|
|
|
|
submit
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-11-19 14:42:14 +00:00
|
|
|
const PageForm: React.FC<PageFormProps> = ({
|
|
|
|
children,
|
|
|
|
page,
|
2021-01-20 16:37:36 +00:00
|
|
|
onSubmit,
|
|
|
|
...rest
|
2020-11-19 14:42:14 +00:00
|
|
|
}) => {
|
2021-01-20 16:37:36 +00:00
|
|
|
const props = usePageForm(page, onSubmit, rest);
|
2020-11-04 10:48:49 +00:00
|
|
|
|
|
|
|
return <form onSubmit={props.submit}>{children(props)}</form>;
|
|
|
|
};
|
|
|
|
|
|
|
|
PageForm.displayName = "PageForm";
|
|
|
|
export default PageForm;
|