[WEB-1322] dev: conflict free pages collaboration (#4463)
* chore: pages realtime * chore: empty binary response * chore: added a ypy package * feat: pages collaboration * chore: update fetching logic * chore: degrade ypy version * chore: replace useEffect fetch logic with useSWR * chore: move all the update logic to the page store * refactor: remove react-hook-form * chore: save description_html as well * chore: migrate old data logic * fix: added description_binary as field name * fix: code cleanup * refactor: create separate hook to handle page description * fix: build errors * chore: combine updates instead of using the whole document * chore: removed ypy package * chore: added conflict resolving logic to the client side * chore: add a save changes button * chore: add read-only validation * chore: remove saving state information * chore: added permission class * chore: removed the migration file * chore: corrected the model field * chore: rename pageStore to page * chore: update collaboration provider * chore: add try catch to handle error --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
This commit is contained in:
parent
a04ce5abfc
commit
ff03c0b718
42 changed files with 1134 additions and 509 deletions
|
|
@ -1,8 +1,7 @@
|
|||
import { ReactElement, useEffect, useRef, useState } from "react";
|
||||
import { ReactElement, useRef, useState } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useForm } from "react-hook-form";
|
||||
import useSWR from "swr";
|
||||
// document-editor
|
||||
import { EditorRefApi, useEditorMarkings } from "@plane/document-editor";
|
||||
|
|
@ -38,38 +37,24 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
|||
const { workspaceSlug, projectId, pageId } = router.query;
|
||||
// store hooks
|
||||
const { createPage, getPageById } = useProjectPages(projectId?.toString() ?? "");
|
||||
const pageStore = usePage(pageId?.toString() ?? "");
|
||||
const page = usePage(pageId?.toString() ?? "");
|
||||
const { description_html, id, name } = page;
|
||||
// editor markings hook
|
||||
const { markings, updateMarkings } = useEditorMarkings();
|
||||
// form info
|
||||
const { handleSubmit, getValues, control } = useForm<TPage>({
|
||||
defaultValues: {
|
||||
name: "",
|
||||
description_html: "",
|
||||
},
|
||||
});
|
||||
|
||||
// fetching page details
|
||||
const {
|
||||
data: swrPageDetails,
|
||||
isValidating,
|
||||
error: pageDetailsError,
|
||||
} = useSWR(pageId ? `PAGE_DETAILS_${pageId}` : null, pageId ? () => getPageById(pageId.toString()) : null, {
|
||||
revalidateIfStale: false,
|
||||
revalidateOnFocus: true,
|
||||
revalidateOnReconnect: true,
|
||||
});
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
if (pageStore.cleanup) pageStore.cleanup();
|
||||
},
|
||||
[pageStore]
|
||||
// fetch page details
|
||||
const { error: pageDetailsError } = useSWR(
|
||||
pageId ? `PAGE_DETAILS_${pageId}` : null,
|
||||
pageId ? () => getPageById(pageId.toString()) : null,
|
||||
{
|
||||
revalidateIfStale: false,
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
}
|
||||
);
|
||||
|
||||
if ((!pageStore || !pageStore.id) && !pageDetailsError)
|
||||
if ((!page || !id) && !pageDetailsError)
|
||||
return (
|
||||
<div className="h-full w-full grid place-items-center">
|
||||
<div className="size-full grid place-items-center">
|
||||
<LogoSpinner />
|
||||
</div>
|
||||
);
|
||||
|
|
@ -90,28 +75,12 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
|||
</div>
|
||||
);
|
||||
|
||||
// we need to get the values of title and description from the page store but we don't have to subscribe to those values
|
||||
const pageTitle = pageStore?.name;
|
||||
|
||||
const handleCreatePage = async (payload: Partial<TPage>) => await createPage(payload);
|
||||
|
||||
const handleUpdatePage = async (formData: TPage) => {
|
||||
let updatedDescription = formData.description_html;
|
||||
if (!updatedDescription || updatedDescription.trim() === "") updatedDescription = "<p></p>";
|
||||
pageStore.updateDescription(updatedDescription);
|
||||
};
|
||||
|
||||
const handleDuplicatePage = async () => {
|
||||
const currentPageValues = getValues();
|
||||
|
||||
if (!currentPageValues?.description_html) {
|
||||
// TODO: We need to get latest data the above variable will give us stale data
|
||||
currentPageValues.description_html = pageStore.description_html;
|
||||
}
|
||||
|
||||
const formData: Partial<TPage> = {
|
||||
name: "Copy of " + pageStore.name,
|
||||
description_html: currentPageValues.description_html,
|
||||
name: "Copy of " + name,
|
||||
description_html: description_html ?? "<p></p>",
|
||||
};
|
||||
|
||||
await handleCreatePage(formData)
|
||||
|
|
@ -127,7 +96,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<PageHead title={pageTitle} />
|
||||
<PageHead title={name} />
|
||||
<div className="flex h-full flex-col justify-between">
|
||||
<div className="h-full w-full flex-shrink-0 flex flex-col overflow-hidden">
|
||||
{projectId && (
|
||||
|
|
@ -137,24 +106,20 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
|||
editorReady={editorReady}
|
||||
readOnlyEditorReady={readOnlyEditorReady}
|
||||
handleDuplicatePage={handleDuplicatePage}
|
||||
isSyncing={isValidating}
|
||||
markings={markings}
|
||||
pageStore={pageStore}
|
||||
page={page}
|
||||
projectId={projectId.toString()}
|
||||
sidePeekVisible={sidePeekVisible}
|
||||
setSidePeekVisible={(state) => setSidePeekVisible(state)}
|
||||
/>
|
||||
)}
|
||||
<PageEditorBody
|
||||
swrPageDetails={swrPageDetails}
|
||||
control={control}
|
||||
editorRef={editorRef}
|
||||
handleEditorReady={(val) => setEditorReady(val)}
|
||||
readOnlyEditorRef={readOnlyEditorRef}
|
||||
handleReadOnlyEditorReady={() => setReadOnlyEditorReady(true)}
|
||||
handleSubmit={() => handleSubmit(handleUpdatePage)()}
|
||||
markings={markings}
|
||||
pageStore={pageStore}
|
||||
page={page}
|
||||
sidePeekVisible={sidePeekVisible}
|
||||
updateMarkings={updateMarkings}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue