import { useEffect } from "react"; import { observer } from "mobx-react"; import { useRouter } from "next/router"; import { Control, Controller } from "react-hook-form"; // document editor import { DocumentEditorWithRef, DocumentReadOnlyEditorWithRef, EditorReadOnlyRefApi, EditorRefApi, IMarking, } from "@plane/document-editor"; // types import { IUserLite, TPage } from "@plane/types"; // components import { PageContentBrowser, PageEditorTitle } from "@/components/pages"; // helpers import { cn } from "@/helpers/common.helper"; // hooks import { useMember, useMention, useUser, useWorkspace } from "@/hooks/store"; import useReloadConfirmations from "@/hooks/use-reload-confirmation"; // services import { FileService } from "@/services/file.service"; // store import { IPageStore } from "@/store/pages/page.store"; const fileService = new FileService(); type Props = { control: Control<TPage, any>; editorRef: React.RefObject<EditorRefApi>; readOnlyEditorRef: React.RefObject<EditorReadOnlyRefApi>; swrPageDetails: TPage | undefined; handleSubmit: () => void; markings: IMarking[]; pageStore: IPageStore; sidePeekVisible: boolean; handleEditorReady: (value: boolean) => void; handleReadOnlyEditorReady: (value: boolean) => void; updateMarkings: (description_html: string) => void; }; export const PageEditorBody: React.FC<Props> = observer((props) => { const { control, handleReadOnlyEditorReady, handleEditorReady, editorRef, markings, readOnlyEditorRef, handleSubmit, pageStore, swrPageDetails, sidePeekVisible, updateMarkings, } = props; // router const router = useRouter(); const { workspaceSlug, projectId } = router.query; // store hooks const { currentUser } = useUser(); const { getWorkspaceBySlug } = useWorkspace(); const { getUserDetails, project: { getProjectMemberIds }, } = useMember(); // derived values const workspaceId = workspaceSlug ? getWorkspaceBySlug(workspaceSlug.toString())?.id ?? "" : ""; const pageTitle = pageStore?.name ?? ""; const pageDescription = pageStore?.description_html ?? "<p></p>"; const isFullWidth = !!pageStore?.view_props?.full_width; const { description_html, isContentEditable, updateTitle, isSubmitting, setIsSubmitting } = pageStore; const projectMemberIds = projectId ? getProjectMemberIds(projectId.toString()) : []; const projectMemberDetails = projectMemberIds?.map((id) => getUserDetails(id) as IUserLite); // use-mention const { mentionHighlights, mentionSuggestions } = useMention({ workspaceSlug: workspaceSlug?.toString() ?? "", projectId: projectId?.toString() ?? "", members: projectMemberDetails, user: currentUser ?? undefined, }); const { setShowAlert } = useReloadConfirmations(isSubmitting === "submitting"); useEffect(() => { updateMarkings(description_html ?? "<p></p>"); }, [description_html, updateMarkings]); return ( <div className="flex items-center h-full w-full overflow-y-auto"> <div className={cn("sticky top-0 hidden h-full flex-shrink-0 -translate-x-full p-5 duration-200 md:block", { "translate-x-0": sidePeekVisible, "w-56 lg:w-72": !isFullWidth, "w-[10%]": isFullWidth, })} > {!isFullWidth && ( <PageContentBrowser editorRef={(isContentEditable ? editorRef : readOnlyEditorRef)?.current} markings={markings} /> )} </div> <div className={cn("h-full w-full pt-5", { "md:w-[calc(100%-14rem)] xl:w-[calc(100%-18rem-18rem)]": !isFullWidth, "md:w-[80%]": isFullWidth, })} > <div className="h-full w-full flex flex-col gap-y-7 overflow-y-auto overflow-x-hidden"> <div className="relative w-full flex-shrink-0 md:pl-5 px-4"> <PageEditorTitle editorRef={editorRef} title={pageTitle} updateTitle={updateTitle} readOnly={!isContentEditable} /> </div> {isContentEditable ? ( <Controller name="description_html" control={control} render={({ field: { onChange } }) => ( <DocumentEditorWithRef fileHandler={{ cancel: fileService.cancelUpload, delete: fileService.getDeleteImageFunction(workspaceId), restore: fileService.getRestoreImageFunction(workspaceId), upload: fileService.getUploadFileFunction(workspaceSlug as string, setIsSubmitting), }} handleEditorReady={handleEditorReady} initialValue={pageDescription} value={swrPageDetails?.description_html ?? "<p></p>"} ref={editorRef} containerClassName="p-0 pb-64" editorClassName="lg:px-10 pl-8" onChange={(_description_json, description_html) => { setIsSubmitting("submitting"); setShowAlert(true); onChange(description_html); handleSubmit(); }} mentionHandler={{ highlights: mentionHighlights, suggestions: mentionSuggestions, }} /> )} /> ) : ( <DocumentReadOnlyEditorWithRef ref={readOnlyEditorRef} initialValue={pageDescription} handleEditorReady={handleReadOnlyEditorReady} containerClassName="p-0 pb-64 border-none" editorClassName="lg:px-10 pl-8" mentionHandler={{ highlights: mentionHighlights, }} /> )} </div> </div> <div className={cn("hidden xl:block flex-shrink-0", { "w-56 lg:w-72": !isFullWidth, "w-[10%]": isFullWidth, })} /> </div> ); });