From 1dcf146f5dded9336c09a877941594fca7881cbb Mon Sep 17 00:00:00 2001 From: dubisdev Date: Sun, 5 Dec 2021 01:00:48 +0100 Subject: [PATCH 1/9] add api endpoint --- lib/dbfuncprisma.js | 30 ++++++++++++++++++++++ pages/api/user/backup.js | 55 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 pages/api/user/backup.js diff --git a/lib/dbfuncprisma.js b/lib/dbfuncprisma.js index 7067dc3..e874326 100644 --- a/lib/dbfuncprisma.js +++ b/lib/dbfuncprisma.js @@ -138,6 +138,36 @@ export async function updatePageData(data) { } } +export async function restoreBackupData(data) { + if (!data) throw new Error("no data to backup"); + // get old data as temporal backup + let oldData = await getPageDatawLinkAndSocialData(); + + // delete old data + await Promise.all([ + Prisma.linkdata.deleteMany(), + Prisma.socialdata.deleteMany(), + Prisma.pagedata.deleteMany(), + ]).catch((error) => { + throw new Error(error.message); + }); + + let { pageData, linkData, socialData } = data; + try { + await Prisma.pagedata.create({ data: pageData }); + await Prisma.linkdata.createMany({ data: linkData }); + await Prisma.socialdata.createMany({ data: socialData }); + return; + } catch (error) { + // try to recover previous data from backup + let { pageData, linkData, socialData } = oldData; + await Prisma.pagedata.create({ data: pageData }); + await Prisma.linkdata.createMany({ data: linkData }); + await Prisma.socialdata.createMany({ data: socialData }); + throw new Error(error.message); + } +} + /** * insert PageLink * @param {*} data diff --git a/pages/api/user/backup.js b/pages/api/user/backup.js new file mode 100644 index 0000000..db436df --- /dev/null +++ b/pages/api/user/backup.js @@ -0,0 +1,55 @@ +import { jwtAuth, use } from "../../../middleware/middleware"; +import { + getPageDatawLinkAndSocialData, + restoreBackupData, +} from "../../../lib/dbfuncprisma"; + +// endoint for download and restore backups +async function handler(req, res) { + switch (req.method) { + case "GET": + return await get(req, res); + case "POST": + return await post(req, res); + default: + res.status(400).send("method not allowed"); + return; + } +} + +async function get(req, res) { + try { + // Run the middleware + await use(req, res, jwtAuth); + + let data = await getPageDatawLinkAndSocialData(); + + res.json({ + ...data, + linkin_version: process.env.NEXT_PUBLIC_VERSION || "", + }); + } catch (error) { + console.log(error.message); + + res.status(500).json({ success: false, message: error.message }); + } +} + +async function post(req, res) { + try { + // Run the middleware + await use(req, res, jwtAuth); + + let { linkin_version, ...data } = req.body; + + await restoreBackupData(data); + + res.json({ success: true }); + } catch (error) { + console.log(error.message); + + res.status(500).json({ success: false, message: error.message }); + } +} + +export default handler; From 7dd44bea3efc84ab49a54e003928f2d4550bebe6 Mon Sep 17 00:00:00 2001 From: dubisdev Date: Sun, 5 Dec 2021 01:01:23 +0100 Subject: [PATCH 2/9] add component --- components/backup.js | 74 +++++++++++++++++++++++++++++++++++++++ components/generalform.js | 3 ++ 2 files changed, 77 insertions(+) create mode 100644 components/backup.js diff --git a/components/backup.js b/components/backup.js new file mode 100644 index 0000000..de751d7 --- /dev/null +++ b/components/backup.js @@ -0,0 +1,74 @@ +const BackupComponent = () => { + const endpoint = + process.env.NODE_ENV === "production" ? `` : "http://localhost:3000"; + + const getBackup = async () => { + try { + let res = await fetch(`${endpoint}/api/user/backup`).then((res) => + res.json() + ); + let data = JSON.stringify(res, undefined, 2); + let blob = new Blob([data], { type: "application/json" }); + + const url = window.URL.createObjectURL(blob); + const a = document.createElement("a"); + a.style.display = "none"; + a.href = url; + // the filename you want + a.download = "linkin-backup.json"; + document.body.appendChild(a); + a.click(); + a.remove(); + window.URL.revokeObjectURL(url); + } catch (error) { + console.log(error.message); + } + }; + + const handleBackup = async (event) => { + event.preventDefault(); + let data = document.getElementById("backup").files[0]; + + let fr = new FileReader(); + fr.onload = async function () { + const a = JSON.parse(fr.result); + + await fetch(`${endpoint}/api/user/backup`, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + method: "POST", + body: JSON.stringify(a), + }) + .then(location.reload()) // reload for getting restored page data + .catch((err) => console.log(err.message)); + }; + + if (data) fr.readAsText(data); + }; + + return ( + <> +

Backup and Restore data

+
+ +
+ + + +
+
+ + ); +}; + +export default BackupComponent; diff --git a/components/generalform.js b/components/generalform.js index 0f318f3..e06e23e 100644 --- a/components/generalform.js +++ b/components/generalform.js @@ -2,6 +2,7 @@ import { useForm } from "react-hook-form"; import { isEmpty } from "../lib/side"; import styles from "../styles/form.module.css"; +import BackupForm from "./backup"; const GeneralForm = ({ data, update, loading }) => { const { @@ -245,6 +246,8 @@ const GeneralForm = ({ data, update, loading }) => { Save +
+ From 713800770a276b1bbdd8cd1ac8b8814e05eeb041 Mon Sep 17 00:00:00 2001 From: dubisdev Date: Sun, 5 Dec 2021 13:41:34 +0100 Subject: [PATCH 3/9] fix: reload when data is restored --- components/backup.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/components/backup.js b/components/backup.js index de751d7..e6e36e7 100644 --- a/components/backup.js +++ b/components/backup.js @@ -14,12 +14,17 @@ const BackupComponent = () => { const a = document.createElement("a"); a.style.display = "none"; a.href = url; - // the filename you want - a.download = "linkin-backup.json"; + + // filename = linkin-backup-date.json + let filename = `linkin-backup-${new Date() + .toISOString() + .slice(0, 16) + .replace(":", "-")}.json`; + a.download = filename; // set filename document.body.appendChild(a); a.click(); a.remove(); - window.URL.revokeObjectURL(url); + window.URL.revokeObjectURL(url); // avoid memory leaks } catch (error) { console.log(error.message); } @@ -27,11 +32,11 @@ const BackupComponent = () => { const handleBackup = async (event) => { event.preventDefault(); - let data = document.getElementById("backup").files[0]; - + let file = document.getElementById("backup").files[0]; let fr = new FileReader(); + fr.onload = async function () { - const a = JSON.parse(fr.result); + const dataJson = JSON.parse(fr.result); await fetch(`${endpoint}/api/user/backup`, { headers: { @@ -39,13 +44,13 @@ const BackupComponent = () => { "Content-Type": "application/json", }, method: "POST", - body: JSON.stringify(a), + body: JSON.stringify(dataJson), }) - .then(location.reload()) // reload for getting restored page data + .then(() => location.reload()) // reload for getting restored page data .catch((err) => console.log(err.message)); }; - if (data) fr.readAsText(data); + if (file) fr.readAsText(file); }; return ( From 4894367f86c648c186e9e25d7a49cff8c0b1d595 Mon Sep 17 00:00:00 2001 From: dubisdev Date: Sun, 5 Dec 2021 13:58:22 +0100 Subject: [PATCH 4/9] fix: layout and toast error --- components/backup.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/components/backup.js b/components/backup.js index e6e36e7..caf42c7 100644 --- a/components/backup.js +++ b/components/backup.js @@ -1,3 +1,5 @@ +import { toast } from "react-toastify"; + const BackupComponent = () => { const endpoint = process.env.NODE_ENV === "production" ? `` : "http://localhost:3000"; @@ -51,21 +53,33 @@ const BackupComponent = () => { }; if (file) fr.readAsText(file); + else toast.error(`No file selected`, { autoClose: 5000 }); }; return ( <>

Backup and Restore data

-
-
- - + +