use swr to autosave in builder

This commit is contained in:
Matthias Nannt
2022-06-21 15:51:09 +09:00
parent 9dd2f557d2
commit fd7c794806
5 changed files with 1864 additions and 1817 deletions
+16 -37
View File
@@ -1,56 +1,37 @@
import Link from "next/link";
import { useCallback, useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { persistNoCodeForm, useNoCodeForm } from "../../lib/noCodeForm";
import Loading from "../Loading";
import Page from "./Page";
import UsageIntro from "./UsageIntro";
import LoadingModal from "../LoadingModal";
import Link from "next/link";
export default function Builder({ formId }) {
const { noCodeForm, isLoadingNoCodeForm, mutateNoCodeForm } =
useNoCodeForm(formId);
const [pagesDraft, setPagesDraft] = useState([]);
const [isInitialized, setIsInitialized] = useState(false);
const [isLoading, setIsLoading] = useState(false);
// autosave
useEffect(() => {
if (isInitialized) {
save();
}
}, [pagesDraft, isInitialized]);
const save = async () => {
setIsLoading(true);
const addPage = useCallback(async () => {
const newNoCodeForm = JSON.parse(JSON.stringify(noCodeForm));
newNoCodeForm.pagesDraft = pagesDraft;
await persistNoCodeForm(newNoCodeForm);
mutateNoCodeForm(newNoCodeForm);
setIsLoading(false);
};
const addPage = useCallback(() => {
const newPagesDraft = JSON.parse(JSON.stringify(pagesDraft));
newPagesDraft.push({
newNoCodeForm.pagesDraft.push({
id: uuidv4(),
blocks: [],
});
setPagesDraft(newPagesDraft);
}, [pagesDraft, setPagesDraft]);
await persistNoCodeForm(newNoCodeForm);
mutateNoCodeForm(newNoCodeForm);
}, [noCodeForm, mutateNoCodeForm]);
const deletePage = (pageIdx) => {
const newPagesDraft = JSON.parse(JSON.stringify(pagesDraft));
newPagesDraft.splice(pageIdx, 1);
setPagesDraft(newPagesDraft);
const deletePage = async (pageIdx) => {
const newNoCodeForm = JSON.parse(JSON.stringify(noCodeForm));
newNoCodeForm.pagesDraft.splice(pageIdx, 1);
await persistNoCodeForm(newNoCodeForm);
mutateNoCodeForm(newNoCodeForm);
};
const initPages = useCallback(() => {
const initPages = useCallback(async () => {
if (!isLoadingNoCodeForm && !isInitialized) {
if (noCodeForm.pagesDraft.length === 0) {
addPage();
} else {
setPagesDraft(noCodeForm.pagesDraft);
await addPage();
}
setIsInitialized(true);
}
@@ -61,7 +42,7 @@ export default function Builder({ formId }) {
}, [isLoadingNoCodeForm, initPages]);
if (isLoadingNoCodeForm) {
<Loading />;
return <Loading />;
}
return (
@@ -91,13 +72,12 @@ export default function Builder({ formId }) {
<div className="px-10">
<UsageIntro />
</div>
{pagesDraft.map((page, pageIdx) => (
{noCodeForm.pagesDraft.map((page, pageIdx) => (
<Page
key={page.id}
formId={formId}
page={page}
pageIdx={pageIdx}
pagesDraft={pagesDraft}
setPagesDraft={setPagesDraft}
deletePageAction={deletePage}
/>
))}
@@ -105,7 +85,6 @@ export default function Builder({ formId }) {
</div>
</div>
</div>
<LoadingModal isLoading={isLoading} />
</>
);
}
+17 -13
View File
@@ -1,21 +1,21 @@
import { TrashIcon } from "@heroicons/react/outline";
import dynamic from "next/dynamic";
import { persistNoCodeForm, useNoCodeForm } from "../../lib/noCodeForm";
import Loading from "../Loading";
let Editor = dynamic(() => import("../editorjs/Editor"), {
ssr: false,
});
export default function Page({
page,
pageIdx,
pagesDraft,
setPagesDraft,
deletePageAction,
}) {
const updatePage = (blocks) => {
const newPagesDraft = JSON.parse(JSON.stringify(pagesDraft));
if (pageIdx < newPagesDraft.length) {
newPagesDraft[pageIdx].blocks = blocks;
setPagesDraft(newPagesDraft);
export default function Page({ formId, page, pageIdx, deletePageAction }) {
const { noCodeForm, isLoadingNoCodeForm, mutateNoCodeForm } =
useNoCodeForm(formId);
const updatePage = async (blocks) => {
const newNoCodeForm = JSON.parse(JSON.stringify(noCodeForm));
if (pageIdx < newNoCodeForm.pagesDraft.length) {
newNoCodeForm.pagesDraft[pageIdx].blocks = blocks;
await persistNoCodeForm(newNoCodeForm);
mutateNoCodeForm(newNoCodeForm);
} else {
throw Error(
`updatePage error: Page at position ${pageIdx} not found in pagesDraft`
@@ -23,6 +23,10 @@ export default function Page({
}
};
if (isLoadingNoCodeForm) {
return <Loading />;
}
return (
<div className="flex w-full">
<div className="flex w-8">
@@ -46,7 +50,7 @@ export default function Page({
id={`${page.id}-editor`}
autofocus={pageIdx === 0}
onChange={(blocks) => updatePage(blocks)}
value={pagesDraft[pageIdx]}
value={noCodeForm.pagesDraft[pageIdx]}
/>
)}
</div>
+1 -2
View File
@@ -4,8 +4,7 @@ import { useNoCodeForm } from "../../lib/noCodeForm";
import Loading from "../Loading";
export default function App({ id = "", formId, draft = false }) {
const { noCodeForm, isLoadingNoCodeForm, mutateNoCodeForm } =
useNoCodeForm(formId);
const { noCodeForm, isLoadingNoCodeForm } = useNoCodeForm(formId);
const pages = useMemo(() => {
if (!isLoadingNoCodeForm) {
return noCodeForm[draft ? "pagesDraft" : "pages"];