diff --git a/servers/fastapi/chroma/chroma.sqlite3 b/servers/fastapi/chroma/chroma.sqlite3 index 75372bfc..1b3a19a3 100644 Binary files a/servers/fastapi/chroma/chroma.sqlite3 and b/servers/fastapi/chroma/chroma.sqlite3 differ diff --git a/servers/nextjs/app/(presentation-generator)/dashboard/components/DashboardPage.tsx b/servers/nextjs/app/(presentation-generator)/dashboard/components/DashboardPage.tsx index 70a70d97..3e127e94 100644 --- a/servers/nextjs/app/(presentation-generator)/dashboard/components/DashboardPage.tsx +++ b/servers/nextjs/app/(presentation-generator)/dashboard/components/DashboardPage.tsx @@ -5,8 +5,9 @@ import React, { useState, useEffect } from "react"; import Wrapper from "@/components/Wrapper"; import { DashboardApi } from "@/app/(presentation-generator)/services/api/dashboard"; import { PresentationGrid } from "@/app/(presentation-generator)/dashboard/components/PresentationGrid"; +import Header from "./Header"; + -import Header from "@/components/Header"; const DashboardPage: React.FC = () => { const [presentations, setPresentations] = useState(null); diff --git a/servers/nextjs/app/(presentation-generator)/outline/hooks/useOutlineStreaming.ts b/servers/nextjs/app/(presentation-generator)/outline/hooks/useOutlineStreaming.ts index c7d2c35f..d53cab9e 100644 --- a/servers/nextjs/app/(presentation-generator)/outline/hooks/useOutlineStreaming.ts +++ b/servers/nextjs/app/(presentation-generator)/outline/hooks/useOutlineStreaming.ts @@ -31,13 +31,13 @@ export const useOutlineStreaming = (presentationId: string | null) => { const data = JSON.parse(event.data); switch (data.type) { case "chunk": - // console.log('data', data) + // accumulatedChunks += data.chunk; - // console.log('accumulatedChunks', accumulatedChunks) + // try { const repairedJson = jsonrepair(accumulatedChunks); const partialData = JSON.parse(repairedJson); - console.log('partialData', partialData) + if (partialData.slides) { dispatch(setOutlines(partialData.slides)); setIsLoading(false) @@ -48,7 +48,7 @@ export const useOutlineStreaming = (presentationId: string | null) => { break; case "complete": - console.log('complete', data) + try { const outlinesData: { content: string }[] = data.presentation.outlines.slides; dispatch(setOutlines(outlinesData)); @@ -64,13 +64,13 @@ export const useOutlineStreaming = (presentationId: string | null) => { break; case "closing": - console.log('closing', data) + setIsStreaming(false) setIsLoading(false) eventSource.close(); break; case "error": - console.log('error', data) + setIsStreaming(false) setIsLoading(false) eventSource.close(); @@ -84,14 +84,14 @@ export const useOutlineStreaming = (presentationId: string | null) => { }); eventSource.onerror = () => { - console.log('onerror') + setIsStreaming(false) setIsLoading(false) eventSource.close(); toast.error("Failed to connect to the server. Please try again."); }; } catch (error) { - console.log('error', error) + setIsStreaming(false) setIsLoading(false) toast.error("Failed to initialize connection"); diff --git a/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx b/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx index 78d8c141..4cc4055a 100644 --- a/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx +++ b/servers/nextjs/app/(presentation-generator)/template-preview/[slug]/backup.tsx @@ -1,394 +1,399 @@ -"use client"; + "use client"; -import React, { useEffect, useState, useRef } from "react"; -import { useParams, useRouter } from "next/navigation"; -// import { useGroupLayoutLoader } from '../hooks/useGroupLayoutLoader' -import LoadingStates from "../components/LoadingStates"; -import { Card } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { ArrowLeft, Edit, Home, Trash2 } from "lucide-react"; -import { useLayout } from "@/app/(presentation-generator)/context/LayoutContext"; + import React, { useEffect, useState, useRef } from "react"; + import { useParams, useRouter } from "next/navigation"; + // import { useGroupLayoutLoader } from '../hooks/useGroupLayoutLoader' + import LoadingStates from "../components/LoadingStates"; + import { Card } from "@/components/ui/card"; + import { Button } from "@/components/ui/button"; + import { ArrowLeft, Edit, Home, Trash2 } from "lucide-react"; + import { useLayout } from "@/app/(presentation-generator)/context/LayoutContext"; -import html2canvas from "html2canvas"; + import html2canvas from "html2canvas"; +import { EditControls } from "../../custom-template/components/EachSlide/EditControls"; +import { useDrawingCanvas } from "../../custom-template/hooks/useDrawingCanvas"; + const GroupLayoutPreview = () => { + const params = useParams(); + const router = useRouter(); + const slug = params.slug as string; + // const isCustom = slug.includes("custom-"); + const isCustom = true; + // Custom hooks + const { + canvasRef, + slideDisplayRef, + strokeWidth, + strokeColor, + eraserMode, + isDrawing, + canvasDimensions, + setCanvasDimensions, + didYourDraw, + handleMouseDown, + handleMouseMove, + handleMouseUp, + handleTouchStart, + handleTouchMove, + handleTouchEnd, + handleClearCanvas, + handleEraserModeChange, + handleStrokeColorChange, + handleStrokeWidthChange, + } = useDrawingCanvas(); -const GroupLayoutPreview = () => { - const params = useParams(); - const router = useRouter(); - const slug = params.slug as string; - // const isCustom = slug.includes("custom-"); - const isCustom = true; - // Custom hooks - const { - canvasRef, - slideDisplayRef, - strokeWidth, - strokeColor, - eraserMode, - isDrawing, - canvasDimensions, - setCanvasDimensions, - didYourDraw, - handleMouseDown, - handleMouseMove, - handleMouseUp, - handleTouchStart, - handleTouchMove, - handleTouchEnd, - handleClearCanvas, - handleEraserModeChange, - handleStrokeColorChange, - handleStrokeWidthChange, - } = useDrawingCanvas(); + const slideContentRef = useRef(null); - const slideContentRef = useRef(null); + const { getFullDataByGroup, loading,refetch } = useLayout(); + const layoutGroup = getFullDataByGroup(slug); + const [isEditMode, setIsEditMode] = useState(false); + const [selectedIndex, setSelectedIndex] = useState(null); + const [prompt, setPrompt] = useState(""); + const [isUpdating, setIsUpdating] = useState(false); - const { getFullDataByGroup, loading,refetch } = useLayout(); - const layoutGroup = getFullDataByGroup(slug); - const [isEditMode, setIsEditMode] = useState(false); - const [selectedIndex, setSelectedIndex] = useState(null); - const [prompt, setPrompt] = useState(""); - const [isUpdating, setIsUpdating] = useState(false); + useEffect(() => { + const existingScript = document.querySelector( + 'script[src*="tailwindcss.com"]' + ); + if (!existingScript) { + const script = document.createElement("script"); + script.src = "https://cdn.tailwindcss.com"; + script.async = true; + document.head.appendChild(script); + } + }, [slug]); - useEffect(() => { - const existingScript = document.querySelector( - 'script[src*="tailwindcss.com"]' - ); - if (!existingScript) { - const script = document.createElement("script"); - script.src = "https://cdn.tailwindcss.com"; - script.async = true; - document.head.appendChild(script); - } - }, [slug]); - - // Size canvas to content when entering edit mode - useEffect(() => { - if (isEditMode && slideContentRef.current) { - const rect = slideContentRef.current.getBoundingClientRect(); - setCanvasDimensions({ - width: Math.max(rect.width, 800), - height: Math.max(rect.height, 600), - }); - } - }, [isEditMode, setCanvasDimensions]); - - // Handle loading state - if (loading) { - return ; - } - - // Handle empty state - if (!layoutGroup || layoutGroup.length === 0) { - return ; - } - const deleteLayouts = async () => { - const presentationId = slug.replace('custom-',''); - refetch(); - router.back(); - const response = await fetch(`/api/v1/ppt/layout-management/delete-layouts/${presentationId}`, { - method: "DELETE", - }); - if (response.ok) { - router.push("/template-preview"); - } - } - - const handleSave = async ( - slideDisplayRef: React.RefObject, - didYourDraw: boolean - ) => { - if ( - !slideContentRef.current || - !slideDisplayRef.current - ) - return; - - if (!prompt.trim()) { - alert("Please enter a prompt before saving."); - return; - } - - setIsUpdating(true); - - try { - // Take screenshot of the slide display area (slide only) - const slideOnly = await html2canvas(slideDisplayRef.current, { - backgroundColor: "#ffffff", - scale: 1, - logging: false, - useCORS: true, - ignoreElements: (element) => { - return element.tagName === "CANVAS"; - }, - }); - let slideWithCanvas; - if (didYourDraw) { - // Take screenshot of the entire slide display area including canvas - slideWithCanvas = await html2canvas(slideDisplayRef.current, { - backgroundColor: "#ffffff", - scale: 1, - logging: false, - useCORS: true, + // Size canvas to content when entering edit mode + useEffect(() => { + if (isEditMode && slideContentRef.current) { + const rect = slideContentRef.current.getBoundingClientRect(); + setCanvasDimensions({ + width: Math.max(rect.width, 800), + height: Math.max(rect.height, 600), }); - } + } + }, [isEditMode, setCanvasDimensions]); - - - const currentUiImageBlob = dataURLToBlob( - slideOnly.toDataURL("image/png") - ); - let sketchImageBlob; - if (didYourDraw && slideWithCanvas) { - sketchImageBlob = dataURLToBlob(slideWithCanvas.toDataURL("image/png")); - } - - // download the images - - const currentUiImageUrl = URL.createObjectURL(currentUiImageBlob); - const sketchImageUrl = didYourDraw ? URL.createObjectURL(sketchImageBlob) : null; - - const a = document.createElement("a"); - a.href = currentUiImageUrl; - a.download = `slide-current.png`; - a.click(); - - if (sketchImageUrl) { - const b = document.createElement("a"); - b.href = sketchImageUrl; - b.download = `slide-sketch.png`; - b.click(); - } - - - // const formData = new FormData(); - // formData.append( - // "current_ui_image", - // currentUiImageBlob, - // `slide--current.png` - // ); - // if (didYourDraw && slideWithCanvas && sketchImageBlob) { - // formData.append( - // "sketch_image", - // sketchImageBlob, - // `slide-sketch.png` - // ); - // } - // formData.append("html", ''); - // formData.append("prompt", prompt); - - // const response = await fetch("/api/v1/ppt/html-edit/", { - // method: "POST", - // body: formData, - // }); - - // if (!response.ok) { - // throw new Error(`API call failed: ${response.statusText}`); - // } - - // const data = await response.json(); - - - // Exit edit mode - setIsEditMode(false); - setPrompt(""); - } catch (error) { - console.error("Error updating slide:", error); - alert( - `Error updating slide: ${ - error instanceof Error ? error.message : "Unknown error" - }` - ); - } finally { - setIsUpdating(false); - } - }; - const dataURLToBlob = (dataURL: string): Blob => { - const parts = dataURL.split(","); - const contentType = parts[0].match(/:(.*?);/)?.[1] || "image/png"; - const raw = window.atob(parts[1]); - const rawLength = raw.length; - const uInt8Array = new Uint8Array(rawLength); - - for (let i = 0; i < rawLength; ++i) { - uInt8Array[i] = raw.charCodeAt(i); + // Handle loading state + if (loading) { + return ; } - return new Blob([uInt8Array], { type: contentType }); - }; + // Handle empty state + if (!layoutGroup || layoutGroup.length === 0) { + return ; + } + const deleteLayouts = async () => { + const presentationId = slug.replace('custom-',''); + refetch(); + router.back(); + const response = await fetch(`/api/v1/ppt/layout-management/delete-layouts/${presentationId}`, { + method: "DELETE", + }); + if (response.ok) { + router.push("/template-preview"); + } + } - return ( -
- {/* Header */} -
-
- {/* Navigation */} -
- - - {isCustom && } -
+ const handleSave = async ( + slideDisplayRef: React.RefObject, + didYourDraw: boolean + ) => { + if ( + !slideContentRef.current || + !slideDisplayRef.current + ) + return; -
-

- {layoutGroup[0].groupName} Layouts -

-

- {layoutGroup.length} layout{layoutGroup.length !== 1 ? "s" : ""} •{" "} - {layoutGroup[0].groupName} -

-
- -
-
+ if (!prompt.trim()) { + alert("Please enter a prompt before saving."); + return; + } - -
- {/* Edit Controls (no HTML editor) */} - {isCustom && ( - { - setIsUpdating(true); - setTimeout(() => { - setIsUpdating(false); + setIsUpdating(true); + + try { + // Take screenshot of the slide display area (slide only) + const slideOnly = await html2canvas(slideDisplayRef.current, { + backgroundColor: "#ffffff", + scale: 1, + logging: false, + useCORS: true, + ignoreElements: (element) => { + return element.tagName === "CANVAS"; + }, + }); + let slideWithCanvas; + if (didYourDraw) { + // Take screenshot of the entire slide display area including canvas + slideWithCanvas = await html2canvas(slideDisplayRef.current, { + backgroundColor: "#ffffff", + scale: 1, + logging: false, + useCORS: true, + }); + } + + + + const currentUiImageBlob = dataURLToBlob( + slideOnly.toDataURL("image/png") + ); + let sketchImageBlob; + if (didYourDraw && slideWithCanvas) { + sketchImageBlob = dataURLToBlob(slideWithCanvas.toDataURL("image/png")); + } + + // download the images + + const currentUiImageUrl = URL.createObjectURL(currentUiImageBlob); + if (currentUiImageUrl) { + const a = document.createElement("a"); + a.href = currentUiImageUrl; + a.download = `slide-current.png`; + a.click(); + } + if (sketchImageBlob) { + const sketchImageUrl = URL.createObjectURL(sketchImageBlob); + if (sketchImageUrl) { + const b = document.createElement("a"); + b.href = sketchImageUrl; + b.download = `slide-sketch.png`; + b.click(); + } + } + + + + + // const formData = new FormData(); + // formData.append( + // "current_ui_image", + // currentUiImageBlob, + // `slide--current.png` + // ); + // if (didYourDraw && slideWithCanvas && sketchImageBlob) { + // formData.append( + // "sketch_image", + // sketchImageBlob, + // `slide-sketch.png` + // ); + // } + // formData.append("html", ''); + // formData.append("prompt", prompt); + + // const response = await fetch("/api/v1/ppt/html-edit/", { + // method: "POST", + // body: formData, + // }); + + // if (!response.ok) { + // throw new Error(`API call failed: ${response.statusText}`); + // } + + // const data = await response.json(); + + + // Exit edit mode + setIsEditMode(false); + setPrompt(""); + } catch (error) { + console.error("Error updating slide:", error); + alert( + `Error updating slide: ${ + error instanceof Error ? error.message : "Unknown error" + }` + ); + } finally { + setIsUpdating(false); + } + }; + const dataURLToBlob = (dataURL: string): Blob => { + const parts = dataURL.split(","); + const contentType = parts[0].match(/:(.*?);/)?.[1] || "image/png"; + const raw = window.atob(parts[1]); + const rawLength = raw.length; + const uInt8Array = new Uint8Array(rawLength); + + for (let i = 0; i < rawLength; ++i) { + uInt8Array[i] = raw.charCodeAt(i); + } + + return new Blob([uInt8Array], { type: contentType }); + }; + + return ( +
+ {/* Header */} +
+
+ {/* Navigation */} +
+ + + {isCustom && } +
+ +
+

+ {layoutGroup[0].groupName} Layouts +

+

+ {layoutGroup.length} layout{layoutGroup.length !== 1 ? "s" : ""} •{" "} + {layoutGroup[0].groupName} +

+
+ +
+
+ + +
+ {/* Edit Controls (no HTML editor) */} + {isCustom && ( + { + setIsUpdating(true); + setTimeout(() => { + setIsUpdating(false); + setIsEditMode(false); + setSelectedIndex(null); + }, 300); + }} + onCancel={() => { setIsEditMode(false); setSelectedIndex(null); - }, 300); - }} - onCancel={() => { - setIsEditMode(false); - setSelectedIndex(null); - handleClearCanvas(); - }} - onStrokeWidthChange={handleStrokeWidthChange} - onStrokeColorChange={handleStrokeColorChange} - onEraserModeChange={handleEraserModeChange} - onClearCanvas={handleClearCanvas} - /> - )} -
- {layoutGroup.map((layout: any, index: number) => { - const { - component: LayoutComponent, - sampleData, - name, - fileName, - } = layout; + handleClearCanvas(); + }} + onStrokeWidthChange={handleStrokeWidthChange} + onStrokeColorChange={handleStrokeColorChange} + onEraserModeChange={handleEraserModeChange} + onClearCanvas={handleClearCanvas} + /> + )} +
+ {layoutGroup.map((layout: any, index: number) => { + const { + component: LayoutComponent, + sampleData, + name, + fileName, + } = layout; - const isSelected = isCustom && isEditMode && selectedIndex === index; + const isSelected = isCustom && isEditMode && selectedIndex === index; - return ( - - {/* Layout Header */} -
-
-
-

- {name} -

-
- - {fileName} - - - {layoutGroup[0].groupName} - -
+ return ( + + {/* Layout Header */} +
+
+
+

+ {name} +

+
+ + {fileName} + + + {layoutGroup[0].groupName} + +
+
+
+ {isCustom && ( + + )} +
-
- {isCustom && ( - - )}
-
-
- {/* Layout Content */} -
-
- - {isSelected && ( - e.preventDefault()} - /> - )} -
-
- - ); - })} + {/* Layout Content */} +
+
+ + {isSelected && ( + e.preventDefault()} + /> + )} +
+
+ + ); + })} +
+
+ + {/* Footer */} +
+
+
+

+ {layoutGroup[0].groupName} • {layoutGroup.length} components +

+
+
+
-
+ ); + }; - {/* Footer */} - -
- ); -}; - -export default GroupLayoutPreview; + export default GroupLayoutPreview;