diff --git a/src/app/workspace/[fileId]/page.tsx b/src/app/workspace/[fileId]/page.tsx index 41b3211..97898e8 100644 --- a/src/app/workspace/[fileId]/page.tsx +++ b/src/app/workspace/[fileId]/page.tsx @@ -6,13 +6,12 @@ import { useConvex } from "convex/react"; import { api } from "../../../../convex/_generated/api"; import { FILE } from "../../dashboard/_components/FileList"; import Canvas from "../_components/Canvas"; +import dynamic from 'next/dynamic'; import EditorJS, { OutputData } from "@editorjs/editorjs"; -import { useKindeBrowserClient } from "@kinde-oss/kinde-auth-nextjs"; -import { useRouter } from "next/navigation"; // Dynamic imports for server-side libraries -const jsPDFPromise = import("jspdf"); -const excalidrawPromise = import("@excalidraw/excalidraw"); +const jsPDFPromise = import('jspdf'); +const excalidrawPromise = import('@excalidraw/excalidraw'); function Workspace({ params }: any) { const [triggerSave, setTriggerSave] = useState(false); @@ -22,49 +21,29 @@ function Workspace({ params }: any) { const editorRef = useRef(null); const canvasRef = useRef(null); - const { user, isAuthenticated, isLoading } = useKindeBrowserClient(); - const router = useRouter(); - - console.log(user, isAuthenticated, isLoading); - useEffect(() => { - if (params.fileId && !isLoading) { + if (params.fileId) { getFileData(); } - }, [params.fileId, isLoading]); + }, [params.fileId]); const getFileData = async () => { const result = await convex.query(api.files.getFileById, { _id: params.fileId, }); - - const teamInfo = await convex.query(api.teams.getTeamById, { - _id: result.teamId, - }); - - if (result.private) { - if (user) { - if (!teamInfo.teamMembers.includes(user.email)) { - router.push("/"); - } - console.log(user); - } else { - router.push("/"); - } - } setFileData(result); }; const saveAsPdf = async () => { const { default: jsPDF } = await jsPDFPromise; const { exportToSvg } = await excalidrawPromise; - + const editorInstance = editorRef.current; const canvasInstance = canvasRef.current; - + if (editorInstance && canvasInstance) { const pdf = new jsPDF("p", "mm", "a4"); - + // Extract text content from the editor editorInstance.save().then((editorContent: OutputData) => { const pageWidth = pdf.internal.pageSize.getWidth(); @@ -73,57 +52,50 @@ function Workspace({ params }: any) { const textWidth = pageWidth - margin * 2; const textHeight = pageHeight - margin * 2; let y = margin; - + editorContent.blocks.forEach((block: any) => { let lines: any[] = []; - + switch (block.type) { case "paragraph": lines = parseText(block.data.text); break; case "header": pdf.setFontSize(16); // Set font size for header - lines = [{ text: block.data.text, style: "header" }]; + lines = [{ text: block.data.text, style: 'header' }]; pdf.setFontSize(12); // Reset font size break; case "list": - lines = block.data.items.map((item: string) => ({ - text: `• ${item}`, - style: "normal", - })); + lines = block.data.items.map((item: string) => ({ text: `• ${item}`, style: 'normal' })); break; - // Add more cases if needed for different block types default: - lines = [{ text: block.data.text, style: "normal" }]; + lines = [{ text: block.data.text, style: 'normal' }]; } - + lines.forEach((line: any) => { if (y + 10 > textHeight) { pdf.addPage(); y = margin; } - + switch (line.style) { - case "bold": + case 'bold': pdf.setFont("helvetica", "bold"); break; - case "italic": + case 'italic': pdf.setFont("helvetica", "italic"); break; - case "header": + case 'header': pdf.setFont("helvetica", "bold"); - const headerWidth = - (pdf.getStringUnitWidth(line.text) * 16) / - pdf.internal.scaleFactor; + const headerWidth = pdf.getStringUnitWidth(line.text) * 16 / pdf.internal.scaleFactor; pdf.text(line.text, (pageWidth - headerWidth) / 2, y); y += 10; break; default: pdf.setFont("helvetica", "normal"); } - - if (line.style !== "header") { - // Split text if it's too wide and handle separately + + if (line.style !== 'header') { const wrappedLines = pdf.splitTextToSize(line.text, textWidth); wrappedLines.forEach((wrappedLine: string) => { if (y + 10 > textHeight) { @@ -135,87 +107,87 @@ function Workspace({ params }: any) { }); } }); - - // Reset font style and size after each block + pdf.setFont("helvetica", "normal"); pdf.setFontSize(12); }); - + // Export flowchart as SVG from Excalidraw const elements = canvasInstance.getSceneElements(); const appState = canvasInstance.getAppState(); const files = canvasInstance.getFiles(); - + exportToSvg({ elements: elements, - appState: { ...appState, exportBackground: false }, // No background + appState: { ...appState, exportBackground: false }, files: files, }).then((svg: SVGSVGElement) => { - // Add heading for the flowchart - pdf.setFont("helvetica", "bold"); - pdf.setFontSize(16); // Set font size for the heading - const headingText = "Flowchart"; - const headingWidth = - pdf.getStringUnitWidth(headingText) * pdf.internal.scaleFactor; - const headingX = (pageWidth - headingWidth) / 2; - pdf.text(headingText, headingX, y + 10); - pdf.setFontSize(12); // Reset font size - pdf.setFont("helvetica", "normal"); - y += 20; // Adjust y position to avoid overlap with the heading - - // Convert SVG to PNG using the Canvas API const svgData = new XMLSerializer().serializeToString(svg); const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); const img = new Image(); - + img.onload = () => { if (context) { canvas.width = img.width; canvas.height = img.height; context.drawImage(img, 0, 0); - + const imgData = canvas.toDataURL("image/png"); const imgProps = pdf.getImageProperties(imgData); - const imgHeight = (imgProps.height * pageWidth) / imgProps.width; - - // Add canvas image just below the heading - pdf.addImage( - imgData, - "PNG", - margin, - y, - pageWidth - margin * 2, - imgHeight - ); - y += imgHeight; - - // Save the PDF + let imgWidth = pageWidth - margin * 2; + let imgHeight = (imgProps.height * imgWidth) / imgProps.width; + + // Check if the image height exceeds the remaining page height + if (y + imgHeight + 20 > pageHeight - margin) { // 20 for the heading space + pdf.addPage(); + y = margin; + } + + // Add heading for the flowchart + pdf.setFont("helvetica", "bold"); + pdf.setFontSize(16); // Set font size for the heading + const headingText = "Flowchart"; + const headingWidth = pdf.getStringUnitWidth(headingText) * 16 / pdf.internal.scaleFactor; + pdf.text(headingText, (pageWidth - headingWidth) / 2, y); + pdf.setFontSize(12); // Reset font size + pdf.setFont("helvetica", "normal"); + y += 20; // Adjust y position to avoid overlap with the heading + + // Check if the image height exceeds the page height and scale it down if necessary + if (imgHeight > pageHeight - margin * 2) { + const scaleFactor = (pageHeight - margin * 2) / imgHeight; + imgHeight *= scaleFactor; + imgWidth *= scaleFactor; + } + + pdf.addImage(imgData, "PNG", margin, y, imgWidth, imgHeight, undefined, "FAST"); + pdf.save("document.pdf"); } else { console.error("Failed to get canvas context"); } }; - + img.src = `data:image/svg+xml;base64,${btoa(svgData)}`; }); }); } else { console.error("Unable to find the content to save as PDF"); } - }; + }; const parseText = (text: string) => { const lines: any[] = []; const parser = new DOMParser(); - const parsedHtml = parser.parseFromString(text, "text/html"); + const parsedHtml = parser.parseFromString(text, 'text/html'); parsedHtml.body.childNodes.forEach((node: ChildNode) => { if (node.nodeType === Node.TEXT_NODE) { - lines.push({ text: node.textContent, style: "normal" }); - } else if (node.nodeName === "B") { - lines.push({ text: node.textContent, style: "bold" }); - } else if (node.nodeName === "I") { - lines.push({ text: node.textContent, style: "italic" }); + lines.push({ text: node.textContent, style: 'normal' }); + } else if (node.nodeName === 'B') { + lines.push({ text: node.textContent, style: 'bold' }); + } else if (node.nodeName === 'I') { + lines.push({ text: node.textContent, style: 'italic' }); } }); return lines; @@ -231,9 +203,7 @@ function Workspace({ params }: any) { onSaveAsPdf={saveAsPdf} /> - {!isLoading &&
+
} @@ -250,7 +220,7 @@ function Workspace({ params }: any) { fileData={fileData} />
-
} +
); }