Skip to content

Commit

Permalink
autosave and save for review
Browse files Browse the repository at this point in the history
  • Loading branch information
GraemeFulton committed Jun 23, 2024
1 parent 5b68166 commit b9493b3
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 27 deletions.
20 changes: 14 additions & 6 deletions components/Editor/Editor.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect } from "react";
import ReactDOM from "react-dom";

import { useEditor, EditorContent } from "@tiptap/react";
Expand Down Expand Up @@ -67,20 +67,27 @@ const Editor = ({
//save status
isSaving = false,
hasUnsavedChanges = false,
saved = false,
//functions
refetchPost = false,
// savePost = false,
updatePost = false,
forceSave= false,
updatePostSettings = false,
setInitialEditorContent = false,
}) => {
const { user } = useUser({
redirectIfFound: false,
});

// const [isSaving, setIsSaving] = useState(false);

const [forReview, setForReview] = useState(false);
const [saveForReview, setForReview] = useState(false);

useEffect(() => {
if(forceSave && saveForReview){
forceSave({editor, json:editor.getJSON(), forReview:saveForReview})
setForReview(false)
}
},[saveForReview])

const editor = useEditor({
extensions: [
Expand Down Expand Up @@ -187,7 +194,7 @@ const Editor = ({
try {
const json = editor.getJSON();
// autosave would happen in the parent here;
updatePost({ editor, json, forReview });
updatePost({ editor, json, forReview:saveForReview });
} catch (e) {
if (typeof updatePost !== "function") {
console.log(e);
Expand Down Expand Up @@ -268,7 +275,7 @@ const Editor = ({
<div className="flex">
<UndoRedoButtons editor={editor} />
<div className={`ml-3 my-auto text-gray-500`}>
{isSaving ? "Saving..." : hasUnsavedChanges ? "" : "Saved"}
{isSaving ? "Saving..." : hasUnsavedChanges ? "" : saved?"Saved":''}
</div>
</div>
</UndoRedoNavPortal>
Expand All @@ -283,6 +290,7 @@ const Editor = ({
}}
isSaving={isSaving}
postStatus={postStatus}
saved={saved}
canEdit={canEdit}
editor={editor}
//for settings panel
Expand Down
4 changes: 2 additions & 2 deletions components/Editor/EditorNavButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ const EditorNavButtons = ({

{/* show publish button if post not published */}
{/* publish button does same as save draft button, but uses dialog and adds 'forReview' flag */}
{canEdit && postStatus !== "publish" && postObject?.id ? (

<PublishDialogButton
canPublish = {canEdit && postStatus !== "publish" && postObject?.id ? (true) : (false)}
//save post creates a post or updates an existing one
//for /write (new post), it creates a new post
//for /p/[slug] (existing post), it updates the existing post
onSave={onSave}
/>
) : null}

{/* show side panel trigger if updatePostSettings is defined (in /p/[slug]) */}
{editor && updatePostSettings !== false ? (
Expand Down
39 changes: 28 additions & 11 deletions components/Editor/EditorWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,15 @@ export default function EditorWrapper({ isInterview = false, tool = false }) {
productName: tool?.name ? tool.name : false,
});
//create new post hook
const { createPost } = useCreate();
const { createPost, creatingPost, created } = useCreate();

const {
//update post content
updatePostById,
//update post settings
updateSettings,
setHasUnsavedChanges,
saved,
saving,
setSaving,
hasUnsavedChanges,
Expand All @@ -88,22 +89,31 @@ export default function EditorWrapper({ isInterview = false, tool = false }) {
// send the content to an API here (if new post only)
if (postId) {
setHasUnsavedChanges(true);
setTimeout(()=>{
setSaving(!saving)
},2700)
setTimeout(() => {
setSaving(!saving);
}, 2700);
debounceSave({ editor, forReview });
} else {
localStorage.setItem("wipContent", JSON.stringify(json));
debounceSave({ editor, forReview });
}
};

/**
* bypass debounce and save immediately
* @param {*} param0
*/
const forceSave = ({ editor, json, forReview }) => {
setSaving(false);
savePost({ editor, forReview });
}

/**
* for autosave
*/
const debounceSave = useCallback(
debounce(async ({ editor, forReview }) => {
setSaving(false)
setSaving(false);
savePost({ editor, forReview });
}, saveDebounceDelay),
[user, postId, postObject, postStatus]
Expand All @@ -119,12 +129,18 @@ export default function EditorWrapper({ isInterview = false, tool = false }) {
* @returns
*/
const savePost = async ({ editor, forReview }) => {
//check if editor has any content
// Updating an existing post
if (
editor.state.doc.textContent.trim() === "" &&
editor.state.doc.childCount <= 2
) {
return false;
}

try {
if (postId) {
if (postId) {
// Updating an existing post

//debounce the save

const updatedPostObject = await updatePostById({
editor: editor,
postId: postId,
Expand Down Expand Up @@ -218,17 +234,18 @@ export default function EditorWrapper({ isInterview = false, tool = false }) {
canEdit={canEdit}
initialContent={initialContent}
postStatus={postStatus}

//saving status
hasUnsavedChanges={hasUnsavedChanges}
isSaving={saving}
isSaving={saving || creatingPost}
saved={saved || created}
//used for updating existing post
slug={slug}
postId={postId}
postObject={postObject}
//save and update content
// savePost={debounceSave}
updatePost={updatePost}
forceSave={forceSave}
//refetch post needed when the featured image is updated in post settings
refetchPost={refetch}
//update post settings
Expand Down
4 changes: 3 additions & 1 deletion components/Editor/PublishDialogButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import Button from "@/components/Primitives/Button";
const Spinner = dynamic(() => import("@/components/atom/Spinner/Spinner"));

export const PublishDialogButton = ({
onSave
onSave,
canPublish
}) => {

const [submitting, setSubmitting] = useState(null);
Expand All @@ -41,6 +42,7 @@ export const PublishDialogButton = ({
<Dialog onOpenChange={toggleSubmitOpen} open={submitOpen}>
<DialogTrigger asChild>
<Button
disabled={!canPublish}
variant="confirmRounded"
className="text-[13px] font-normal h-[25px] px-2 outline outline-blue-600 outline-1 py-0 mr-1 my-auto"
>
Expand Down
5 changes: 4 additions & 1 deletion components/Editor/editorHooks/editPost/useUpdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const axios = require("axios");
*/
const useUpdate = () => {
const [saving, setSaving] = useState(false);
const [saved, setSaved] = useState(false);
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(undefined);

/**
Expand Down Expand Up @@ -67,12 +68,13 @@ const useUpdate = () => {
};

setSaving(true);

setSaved(false)
const updateData = await axios(publishPostEndpointConfig)
.then(async function (response) {
setTimeout(() => {
setSaving(false);
setHasUnsavedChanges(false);
setSaved(true);
}, 1000);
if (forReview) {
toast.success("Submitted for review!", {
Expand Down Expand Up @@ -179,6 +181,7 @@ const useUpdate = () => {
hasUnsavedChanges,
setHasUnsavedChanges,
setSaving,
saved
};
};

Expand Down
29 changes: 23 additions & 6 deletions components/Editor/editorHooks/newPost/useCreate.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import toast from "react-hot-toast";
import { getCreatePostData } from "../libs/getCreatePostData";
import { useState } from "react";
var axios = require("axios");

const useCreate = () => {
const createPost = async ({ user, editor, forReview, relatedPost }) => {
const [creatingPost, setCreating] = useState(false);
const [created, setCreated] = useState(false);

const { entry } = getCreatePostData({ user, editor, forReview, relatedPost });
const createPost = async ({ user, editor, forReview, relatedPost }) => {
setCreating(true);
if (created) {
throw new Error("Post already created");
}
const { entry } = getCreatePostData({
user,
editor,
forReview,
relatedPost,
});

let publishPostEndpointConfig = {
method: "post",
Expand All @@ -25,12 +37,17 @@ const useCreate = () => {
try {
let postResult = await axios(publishPostEndpointConfig)
.then(async function (response) {
toast.success("Your draft has been saved!", {
duration: 5000,
});
// toast.success("Your draft has been saved!", {
// duration: 5000,
// });
setCreated(true);
setTimeout(() => {
setCreating(false);
}, 1000);
return response?.data?.data;
})
.catch(function (error) {
setCreating(false);
console.log(error);
});

Expand All @@ -43,7 +60,7 @@ const useCreate = () => {
}
};

return { createPost };
return { createPost, creatingPost, created };
};

export default useCreate;

0 comments on commit b9493b3

Please sign in to comment.