Skip to content

Commit

Permalink
Feat change the export of files implemented by the client to server A…
Browse files Browse the repository at this point in the history
…PI calls
  • Loading branch information
minai621 committed Jul 20, 2024
1 parent 4b253e7 commit 19046ed
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 78 deletions.
23 changes: 4 additions & 19 deletions frontend/src/components/common/DownloadMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SaveAlt as SaveAltIcon } from "@mui/icons-material";
import { IconButton, Menu, MenuItem, Paper } from "@mui/material";
import { MouseEvent, useCallback, useState } from "react";
import { MouseEvent, useState } from "react";
import { useFileExport } from "../../hooks/useFileExport";

const DownloadMenu = () => {
Expand All @@ -14,22 +14,7 @@ const DownloadMenu = () => {
setAnchorEl(null);
};

const { exportToPDF, exportToTXT, exportToDOCX } = useFileExport();

const handleExportToPDF = useCallback(() => {
exportToPDF();
handleClose();
}, [exportToPDF]);

const handleExportToTXT = useCallback(() => {
exportToTXT();
handleClose();
}, [exportToTXT]);

const handleExportToDOCX = useCallback(() => {
exportToDOCX();
handleClose();
}, [exportToDOCX]);
const { handleExportToPDF, handleExportToHTML, handleExportToMarkdown } = useFileExport();

return (
<Paper>
Expand All @@ -44,8 +29,8 @@ const DownloadMenu = () => {
onClose={handleClose}
>
<MenuItem onClick={handleExportToPDF}>Download as PDF</MenuItem>
<MenuItem onClick={handleExportToTXT}>Download as TXT</MenuItem>
<MenuItem onClick={handleExportToDOCX}>Download as DOCX</MenuItem>
<MenuItem onClick={handleExportToHTML}>Download as HTML</MenuItem>
<MenuItem onClick={handleExportToMarkdown}>Download as Markd</MenuItem>
</Menu>
</Paper>
);
Expand Down
116 changes: 57 additions & 59 deletions frontend/src/hooks/useFileExport.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,75 @@
import { Document, Packer, Paragraph, TextRun } from "docx";
import { saveAs } from "file-saver";
import jspdfHtml2canvas from "jspdf-html2canvas";
import axios from "axios";
import { useSnackbar } from "notistack";
import { useCallback, useContext } from "react";
import { useCallback } from "react";
import { useSelector } from "react-redux";
import { PreviewRefContext } from "../contexts/PreviewRefContext";
import { selectDocument } from "../store/documentSlice";
import { selectEditor } from "../store/editorSlice";
import { documentNameStorage } from "../utils/localStorage";

interface useFileExportReturn {
exportToPDF: () => Promise<void>;
exportToTXT: () => void;
exportToDOCX: () => void;
export const enum FileExtension {
Markdown = "markdown",
HTML = "html",
PDF = "pdf",
}

export const useFileExport = (): useFileExportReturn => {
const editorStore = useSelector(selectEditor);
const markdown = editorStore.doc?.getRoot().content?.toString() || "";

const { previewRef } = useContext(PreviewRefContext);
interface UseFileExportReturn {
handleExportToPDF: () => void;
handleExportToHTML: () => void;
handleExportToMarkdown: () => void;
}

export const useFileExport = (): UseFileExportReturn => {
const { enqueueSnackbar } = useSnackbar();
const editorStore = useSelector(selectEditor);
const documentStore = useSelector(selectDocument);

const documentName = documentNameStorage.getDocumentName() || 'codepair_document';
const markdown = editorStore.doc?.getRoot().content?.toString() || "";
const documentName = documentStore.data?.title || "codepair_document";

const exportToPDF = useCallback(async () => {
if (previewRef.current?.mdp && previewRef.current.mdp.current instanceof HTMLDivElement) {
const handleExportFile = useCallback(
async (exportType: string) => {
try {
await jspdfHtml2canvas(previewRef.current.mdp.current, {
output: `${documentName}`,
jsPDF: {
format: "a4",
orientation: "portrait",
},
html2canvas: {
scale: 3,
enqueueSnackbar(`${exportType.toUpperCase()} 파일 내보내기 시작...`, {
variant: "info",
});

const response = await axios.post(
"/files/export-markdown",
{
exportType,
content: markdown,
fileName: documentName,
},
{
responseType: "blob",
}
);

const blob = new Blob([response.data], { type: `application/${exportType}` });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", `${encodeURIComponent(documentName)}.${exportType}`);
document.body.appendChild(link);
link.click();
if (link.parentNode) link.parentNode.removeChild(link);
window.URL.revokeObjectURL(url);

enqueueSnackbar(`${exportType.toUpperCase()} 파일이 성공적으로 내보내졌습니다.`, {
variant: "success",
});
} catch (error) {
if(previewRef.current.mdp.current) {
enqueueSnackbar("Content is empty", { variant: "error" });
} else {
enqueueSnackbar("Failed to export PDF", { variant: "error" });
}
console.error("오류:", error);
enqueueSnackbar(`${exportType.toUpperCase()} 파일 내보내기에 실패했습니다.`, {
variant: "error",
});
}
} else {
enqueueSnackbar("Please try again", { variant: "error" });
}
}, [previewRef, enqueueSnackbar, documentName]);

const exportToTXT = useCallback(() => {
const blob = new Blob([markdown], { type: "text/plain;charset=utf-8" });
saveAs(blob, documentName);
}, [documentName, markdown]);

const exportToDOCX = useCallback(() => {
const doc = new Document({
sections: [
{
properties: {},
children: [
new Paragraph({
children: [new TextRun(markdown)],
}),
],
},
],
});
},
[markdown, documentName, enqueueSnackbar]
);

Packer.toBlob(doc).then((blob) => {
saveAs(blob, documentName);
});
}, [markdown, documentName]);
const handleExportToPDF = () => handleExportFile(FileExtension.PDF);
const handleExportToHTML = () => handleExportFile(FileExtension.HTML);
const handleExportToMarkdown = () => handleExportFile(FileExtension.Markdown);

return { exportToPDF, exportToTXT, exportToDOCX };
return { handleExportToPDF, handleExportToHTML, handleExportToMarkdown };
};

0 comments on commit 19046ed

Please sign in to comment.