diff --git a/components/Editor/Editor.js b/components/Editor/Editor.js index 45d63320..e5c8b001 100644 --- a/components/Editor/Editor.js +++ b/components/Editor/Editor.js @@ -64,9 +64,12 @@ const Editor = ({ postStatus = "draft", postObject = null, showNavButtons = true, + //save status + isSaving = false, + hasUnsavedChanges = false, //functions refetchPost = false, - savePost = false, + // savePost = false, updatePost = false, updatePostSettings = false, setInitialEditorContent = false, @@ -75,7 +78,9 @@ const Editor = ({ redirectIfFound: false, }); - const [isSaving, setIsSaving] = useState(false); + // const [isSaving, setIsSaving] = useState(false); + + const [forReview, setForReview] = useState(false); const editor = useEditor({ extensions: [ @@ -182,7 +187,7 @@ const Editor = ({ try { const json = editor.getJSON(); // autosave would happen in the parent here; - updatePost({ editor, json }); + updatePost({ editor, json, forReview }); } catch (e) { if (typeof updatePost !== "function") { console.log(e); @@ -201,25 +206,25 @@ const Editor = ({ * - not using autosave yet * - remove onSave when switching to autosaving */ - const onSave = async ({ forReview }) => { - setIsSaving(true); + // const onSave = async ({ forReview }) => { + // setIsSaving(true); - try { - const saved = await savePost({ - editor, - forReview: forReview ? true : false, - }); - if (saved) { - setIsSaving(false); - } else { - console.log("Error saving"); - setIsSaving(false); - } - } catch (e) { - console.log("Error saving"); - setIsSaving(false); - } - }; + // try { + // const saved = await savePost({ + // editor, + // forReview: forReview ? true : false, + // }); + // if (saved) { + // setIsSaving(false); + // } else { + // console.log("Error saving"); + // setIsSaving(false); + // } + // } catch (e) { + // console.log("Error saving"); + // setIsSaving(false); + // } + // }; if (!canEdit) { return ( @@ -260,7 +265,12 @@ const Editor = ({ {/* undoredo buttons render in a portal on the navbar */} {showNavButtons !== false ? ( - + + + + {isSaving ? "Saving..." : hasUnsavedChanges ? "" : "Saved"} + + ) : null} @@ -268,7 +278,9 @@ const Editor = ({ { + setForReview(forReview); + }} isSaving={isSaving} postStatus={postStatus} canEdit={canEdit} diff --git a/components/Editor/EditorNavButtons.js b/components/Editor/EditorNavButtons.js index 8d2af035..65fa00db 100644 --- a/components/Editor/EditorNavButtons.js +++ b/components/Editor/EditorNavButtons.js @@ -23,7 +23,7 @@ const EditorNavButtons = ({ }) => { return ( <> - {user?.isLoggedIn ? + {/* {user?.isLoggedIn ? - :null} + :null} */} {/* show publish button if post not published */} {/* publish button does same as save draft button, but uses dialog and adds 'forReview' flag */} diff --git a/components/Editor/EditorWrapper.js b/components/Editor/EditorWrapper.js index 1c841bea..04ede166 100644 --- a/components/Editor/EditorWrapper.js +++ b/components/Editor/EditorWrapper.js @@ -3,7 +3,7 @@ import dynamic from "next/dynamic"; // import Fallback from "@/components/atom/Fallback/Fallback"; import useUser from "@/lib/iron-session/useUser"; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import { addTwitterScript } from "@/components/Editor/editorHooks/libs/addTwitterScript"; import Editor from "@/components/Editor/Editor"; @@ -17,6 +17,8 @@ import useUpdate from "@/components/Editor/editorHooks/editPost/useUpdate"; import { useRouter } from "next/router"; import EditorNav from "@/components/EditorNav"; import { useConfirmTabClose } from "./useConfirmTabClose"; +import { debounce } from "lodash"; +const saveDebounceDelay = 3000; /** * Write @@ -28,7 +30,7 @@ import { useConfirmTabClose } from "./useConfirmTabClose"; * * @returns */ -export default function EditorWrapper({isInterview=false,tool=false}) { +export default function EditorWrapper({ isInterview = false, tool = false }) { const router = useRouter(); const { user } = useUser({ @@ -43,7 +45,6 @@ export default function EditorWrapper({isInterview=false,tool=false}) { addTwitterScript(); }, []); - //useLoad hook //initialContent is null until loaded - so is 'false' when it's a new post //useLoad hook @@ -56,7 +57,11 @@ export default function EditorWrapper({isInterview=false,tool=false}) { postId, refetch, setPostObject, - } = useLoad({ user, interview:isInterview, productName: tool?.name?tool.name:false}); + } = useLoad({ + user, + interview: isInterview, + productName: tool?.name ? tool.name : false, + }); //create new post hook const { createPost } = useCreate(); @@ -66,6 +71,8 @@ export default function EditorWrapper({isInterview=false,tool=false}) { //update post settings updateSettings, setHasUnsavedChanges, + saving, + setSaving, hasUnsavedChanges, } = useUpdate(); @@ -77,15 +84,30 @@ export default function EditorWrapper({isInterview=false,tool=false}) { * save the content to local storage * @param {*} param0 */ - const updatePost = ({ editor, json }) => { + const updatePost = ({ editor, json, forReview }) => { // send the content to an API here (if new post only) - if(postId){ - setHasUnsavedChanges(true); - }else{ - localStorage.setItem("wipContent", JSON.stringify(json)); + if (postId) { + setHasUnsavedChanges(true); + setTimeout(()=>{ + setSaving(!saving) + },2700) + debounceSave({ editor, forReview }); + } else { + localStorage.setItem("wipContent", JSON.stringify(json)); + debounceSave({ editor, forReview }); } }; - + + /** + * for autosave + */ + const debounceSave = useCallback( + debounce(async ({ editor, forReview }) => { + setSaving(false) + savePost({ editor, forReview }); + }, saveDebounceDelay), + [user, postId, postObject, postStatus] + ); /** * savePost @@ -98,8 +120,11 @@ export default function EditorWrapper({isInterview=false,tool=false}) { */ const savePost = async ({ editor, forReview }) => { try { - if (postId) { + if (postId) { // Updating an existing post + + //debounce the save + const updatedPostObject = await updatePostById({ editor: editor, postId: postId, @@ -118,11 +143,11 @@ export default function EditorWrapper({isInterview=false,tool=false}) { return true; } else { // Creating a new post - if(!router.query.slug){ + if (!router.query.slug) { const postInfo = await createPost({ user, editor, forReview }); // Set the new slug localStorage.removeItem("wipContent"); - + router.replace( { pathname: router.pathname, @@ -133,15 +158,11 @@ export default function EditorWrapper({isInterview=false,tool=false}) { { shallow: true } ); - - - refetch(); return true; - }else{ - return false + } else { + return false; } - } } catch (e) { console.log(e); @@ -193,26 +214,20 @@ export default function EditorWrapper({isInterview=false,tool=false}) { user?.isLoggedIn && ( <> - {/* */} - { useEffect(()=>{ let editor = document.querySelector('.tiptap.ProseMirror') if(open){ - editor.classList.add('menu-open') + editor?.classList?.add('menu-open') }else{ - editor.classList.remove('menu-open') + editor?.classList?.remove('menu-open') } },[open]) diff --git a/components/Editor/editorHooks/editPost/useUpdate.js b/components/Editor/editorHooks/editPost/useUpdate.js index 8f6f75ee..78f95af8 100644 --- a/components/Editor/editorHooks/editPost/useUpdate.js +++ b/components/Editor/editorHooks/editPost/useUpdate.js @@ -70,23 +70,25 @@ const useUpdate = () => { const updateData = await axios(publishPostEndpointConfig) .then(async function (response) { - setSaving(false); - setHasUnsavedChanges(false); + setTimeout(() => { + setSaving(false); + setHasUnsavedChanges(false); + }, 1000); if (forReview) { toast.success("Submitted for review!", { duration: 5000, }); localStorage.removeItem("wipContent"); } else if (postStatus == "publish") { - toast.success("Your post has been updated!", { - duration: 5000, - }); + // toast.success("Your post has been updated!", { + // duration: 5000, + // }); localStorage.removeItem("wipContent"); } else { - toast.success("Your draft has been updated!", { - duration: 5000, - }); + // toast.success("Your draft has been updated!", { + // duration: 5000, + // }); localStorage.removeItem("wipContent"); } diff --git a/components/Editor/editorHooks/libs/helpers/updatePostObjectWithUpdateResults.js b/components/Editor/editorHooks/libs/helpers/updatePostObjectWithUpdateResults.js index 899acc07..1be314e8 100644 --- a/components/Editor/editorHooks/libs/helpers/updatePostObjectWithUpdateResults.js +++ b/components/Editor/editorHooks/libs/helpers/updatePostObjectWithUpdateResults.js @@ -6,7 +6,6 @@ * @param {*} param0 */ export const updatePostObject = ({updatedObject, existingObject}) => { - console.log('existingObject', existingObject) const newFields={ content: updatedObject.content,