From a95e8c148ffcf3abcb47852a6d65cbaa51de07b8 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Sat, 12 Jul 2025 00:01:41 +0545 Subject: [PATCH 1/3] Refactor presentation components: integrate FooterProvider in layout, remove unused mini-slide components, and update slide rendering logic. Adjust theme handling in PresentationCard and SidePanel for improved styling and functionality. --- .../components/EditableText.tsx | 13 +- .../components/mini-slides/MiniCharts.tsx | 18 --- .../components/mini-slides/MiniTypeWriter.tsx | 17 --- .../components/mini-slides/Type1Mini.tsx | 38 ----- .../components/mini-slides/Type2Mini.tsx | 94 ------------ .../components/mini-slides/Type4Mini.tsx | 67 --------- .../components/mini-slides/Type5Mini.tsx | 42 ------ .../components/mini-slides/Type6Mini.tsx | 49 ------- .../components/mini-slides/Type7Mini.tsx | 59 -------- .../components/mini-slides/Type8Mini.tsx | 68 --------- .../components/mini-slides/Type9Mini.tsx | 49 ------- .../components/slide_config.tsx | 94 +----------- .../presentation/[id]/loading.tsx | 18 --- .../presentation/components/Header.tsx | 4 +- .../presentation/components/SidePanel.tsx | 63 ++++---- .../presentation/components/SlideContent.tsx | 2 +- .../presentation/components/SortableSlide.tsx | 15 +- .../presentation/page.tsx | 6 +- .../styles/themes.css | 3 + .../dashboard/components/PresentationCard.tsx | 134 +++++++++--------- .../dashboard/components/PresentationGrid.tsx | 3 +- servers/nextjs/app/layout.tsx | 8 +- 22 files changed, 126 insertions(+), 738 deletions(-) delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniCharts.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniTypeWriter.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type1Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type2Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type4Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type5Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type6Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type7Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type8Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/components/mini-slides/Type9Mini.tsx delete mode 100644 servers/nextjs/app/(presentation-generator)/presentation/[id]/loading.tsx diff --git a/servers/nextjs/app/(presentation-generator)/components/EditableText.tsx b/servers/nextjs/app/(presentation-generator)/components/EditableText.tsx index ae5c2367..b2702807 100644 --- a/servers/nextjs/app/(presentation-generator)/components/EditableText.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/EditableText.tsx @@ -1,12 +1,5 @@ -import { - updateSlideDescription, - updateSlideBodyString, - updateSlideTitle, - updateSlideBodyHeading, - updateSlideBodyDescription, -} from "@/store/slices/presentationGeneration"; -import React, { useCallback, useEffect, useRef, useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import React, { useEffect, useRef } from "react"; +import { useSelector } from "react-redux"; import TipTapEditor from "./Tiptap"; import { RootState } from "@/store/store"; import Typewriter from "./TypeWriter"; @@ -14,7 +7,7 @@ import Typewriter from "./TypeWriter"; interface EditableTextProps { slideIndex: number; bodyIdx?: number; - elementId: string; // Format: 'title' | 'body.0.heading' | 'body.0.description' + elementId: string; type: | "title" | "heading" diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniCharts.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniCharts.tsx deleted file mode 100644 index 30dbed91..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniCharts.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' -import { Chart } from '@/store/slices/presentationGeneration'; -import { renderChart } from '../slide_config'; -import { RootState } from '@/store/store'; -import { useSelector } from 'react-redux'; - -const MiniCharts = ({ chartData }: { chartData: Chart }) => { - const { currentColors } = useSelector((state: RootState) => state.theme); - return ( - -
- {renderChart(chartData, true, currentColors)} -
- - ) -} - -export default MiniCharts diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniTypeWriter.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniTypeWriter.tsx deleted file mode 100644 index 7d0b2d5d..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/MiniTypeWriter.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useTypewriter } from "@/hooks/useTypeWriter"; -import { RootState } from "@/store/store"; -import { useSelector } from "react-redux"; - -const MiniTypeWriter = ({ text }: { text: string }) => { - const { isStreaming } = useSelector( - (state: RootState) => state.presentationGeneration - ); - - // Pass the isStreaming value directly to the hook as the enabled parameter - const { displayText } = useTypewriter(text, 20, isStreaming || false); - - // Since the hook now handles both states, we can simply return displayText - return {displayText}; -}; - -export default MiniTypeWriter; diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type1Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type1Mini.tsx deleted file mode 100644 index 8b0afccb..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type1Mini.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { PresentationGenerationApi } from "../../services/api/presentation-generation"; -import { getStaticFileUrl } from "../../utils/others"; -import MiniTypeWriter from "./MiniTypeWriter"; - -interface Type1MiniProps { - title: string; - description: string; - image: string; -} - -const Type1Mini = ({ title, description, image }: Type1MiniProps) => { - const updatedImage = getStaticFileUrl(image); - return ( -
-
-
-
- -
-
- -
-
-
- {image && ( - {title} - )} -
-
-
- ); -}; - -export default Type1Mini; diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type2Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type2Mini.tsx deleted file mode 100644 index 706e5dee..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type2Mini.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { RootState } from "@/store/store"; -import { useSelector } from "react-redux"; -import MiniTypeWriter from "./MiniTypeWriter"; - -interface Type2MiniProps { - title: string; - body: Array<{ - heading: string; - description: string; - }>; - design_index: number; -} - -const Type2Mini = ({ title, body, design_index }: Type2MiniProps) => { - const isGridLayout = body.length === 4; - const { currentColors } = useSelector((state: RootState) => state.theme); - const getGridCols = (length: number) => { - switch (length) { - case 1: return 'grid-cols-1'; - case 2: return 'grid-cols-2'; - case 3: return 'grid-cols-3'; - case 4: return 'grid-cols-4'; - // Add more cases as needed - default: return 'grid-cols-1'; - } - } - return ( -
-
-
- -
-
- - {design_index === 3 ? ( -
-
-
- {body.map((_, index) => ( -
- {index + 1} -
- ))} -
-
- {body.map((item, index) => ( -
-
- -
-
- -
-
- ))} -
-
- ) : ( -
- {body.map((item, index) => ( -
- {design_index === 2 && ( -
0{index + 1}
- )} -
- -
-
- -
-
- ))} -
- )} -
- ); -}; - -export default Type2Mini; \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type4Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type4Mini.tsx deleted file mode 100644 index 7a70eb69..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type4Mini.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { getStaticFileUrl } from "../../utils/others"; -import MiniTypeWriter from "./MiniTypeWriter"; - -interface Type4MiniProps { - title: string; - body: Array<{ - heading: string; - description: string; - }>; - images: string[]; -} - -const Type4Mini = ({ title, body, images }: Type4MiniProps) => { - const updatedImages = images.map((image) => { - if (image.startsWith("user")) { - return getStaticFileUrl(image); - } - return getStaticFileUrl(image); - }); - const getGridCols = (length: number) => { - switch (length) { - case 1: return 'grid-cols-1'; - case 2: return 'grid-cols-2'; - case 3: return 'grid-cols-3'; - case 4: return 'grid-cols-4'; - // Add more cases as needed - default: return 'grid-cols-1'; - } - } - return ( -
-
-
- -
-
-
- {body.map((item, index) => ( -
-
- {updatedImages && updatedImages[index] && ( - {item.heading} - )} -
-
-
- -
-
- -
-
-
- ))} -
-
- ); -}; - -export default Type4Mini; diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type5Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type5Mini.tsx deleted file mode 100644 index 60ace5f7..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type5Mini.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import MiniCharts from "./MiniCharts"; -import MiniTypeWriter from "./MiniTypeWriter"; - -interface Type5MiniProps { - title: string; - description: string; - chartData: any; - slideIndex: number; - isFullSizeGraph: boolean; -} - -const Type5Mini = ({ title, description, chartData, slideIndex, isFullSizeGraph }: Type5MiniProps) => { - return ( -
-
-
- -
-
-
-
- - -
- {/*
- -
*/} -
- -
-
- {/*
- - - -
{description}
-
*/} -
- ); -}; - -export default Type5Mini; \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type6Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type6Mini.tsx deleted file mode 100644 index 7b2d8606..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type6Mini.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { RootState } from "@/store/store"; -import { useSelector } from "react-redux"; -import MiniTypeWriter from "./MiniTypeWriter"; - -interface Type6MiniProps { - title: string; - description: string; - body: Array<{ - heading: string; - description: string; - }>; -} - -const Type6Mini = ({ title, description, body }: Type6MiniProps) => { - const { currentColors } = useSelector((state: RootState) => state.theme); - return ( -
-
-
-
- -
-
- -
-
-
- {body.map((item, index) => ( -
-
0{index + 1}
-
- -
-
- -
-
- ))} -
-
-
- ); -}; - -export default Type6Mini; \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type7Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type7Mini.tsx deleted file mode 100644 index df17d0af..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type7Mini.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useSelector } from "react-redux"; -import { PresentationGenerationApi } from "../../services/api/presentation-generation"; -import { RootState } from "@/store/store"; -import MiniTypeWriter from "./MiniTypeWriter"; -import { getStaticFileUrl } from "../../utils/others"; - -interface Type7MiniProps { - title: string; - body: Array<{ - heading: string; - description: string; - }>; - icons: string[]; -} - -const Type7Mini = ({ title, body, icons }: Type7MiniProps) => { - const { currentColors } = useSelector((state: RootState) => state.theme); - const isGridLayout = body.length === 4; - const updatedIcons = icons.map((icon) => { - - return getStaticFileUrl(icon); - }); - - return ( -
-
-
- -
-
-
- {body.map((item, index) => ( -
-
- {updatedIcons && updatedIcons[index] && ( - {item.heading} - )} -
-
- -
-
- -
-
- ))} -
-
- ); -}; - -export default Type7Mini; diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type8Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type8Mini.tsx deleted file mode 100644 index 88812031..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type8Mini.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { useSelector } from "react-redux"; -import { RootState } from "@/store/store"; -import { PresentationGenerationApi } from "../../services/api/presentation-generation"; -import MiniTypeWriter from "./MiniTypeWriter"; -import { getStaticFileUrl } from "../../utils/others"; - -interface Type8MiniProps { - title: string; - description: string; - body: Array<{ - heading: string; - description: string; - }>; - icons: string[]; -} - -const Type8Mini = ({ title, description, body, icons }: Type8MiniProps) => { - const { currentColors } = useSelector((state: RootState) => state.theme); - const updatedIcons = icons.map((icon) => { - return getStaticFileUrl(icon); - }); - - return ( -
-
-
-
- -
-
- -
-
-
- {body.map((item, index) => ( -
-
- {updatedIcons && updatedIcons[index] && ( - {item.heading} - )} -
-
-
- -
-
- -
-
-
- ))} -
-
-
- ); -}; - -export default Type8Mini; diff --git a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type9Mini.tsx b/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type9Mini.tsx deleted file mode 100644 index 55375d5a..00000000 --- a/servers/nextjs/app/(presentation-generator)/components/mini-slides/Type9Mini.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { useSelector } from "react-redux"; -import MiniCharts from "./MiniCharts"; -import { RootState } from "@/store/store"; -import MiniTypeWriter from "./MiniTypeWriter"; - -interface Type9MiniProps { - title: string; - body: Array<{ - heading: string; - description: string; - }>; - chartData: any; - slideIndex: number; -} - -const Type9Mini = ({ title, body, chartData, slideIndex }: Type9MiniProps) => { - const { currentColors } = useSelector((state: RootState) => state.theme); - return ( -
-
-
-
- -
- -
-
- {body && body.length > 0 && body.map((item, index) => ( -
-
0{index + 1}
-
- -
-
- -
-
- ))} -
-
-
- ); -}; - -export default Type9Mini; \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/components/slide_config.tsx b/servers/nextjs/app/(presentation-generator)/components/slide_config.tsx index 5798ccb3..bdcb0c9d 100644 --- a/servers/nextjs/app/(presentation-generator)/components/slide_config.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/slide_config.tsx @@ -1,7 +1,5 @@ import { Slide } from "../types/slide"; -import Type1Mini from "./mini-slides/Type1Mini"; -import Type4Mini from "./mini-slides/Type4Mini"; -import Type2Mini from "./mini-slides/Type2Mini"; + import Type1Layout from "./slide_layouts/Type1Layout"; import Type2Layout from "./slide_layouts/Type2Layout"; import Type4Layout from "./slide_layouts/Type4Layout"; @@ -10,11 +8,7 @@ import Type6Layout from "./slide_layouts/Type6Layout"; import Type7Layout from "./slide_layouts/Type7Layout"; import Type8Layout from "./slide_layouts/Type8Layout"; import Type9Layout from "./slide_layouts/Type9Layout"; -import Type7Mini from "./mini-slides/Type7Mini"; -import Type6Mini from "./mini-slides/Type6Mini"; -import Type5Mini from "./mini-slides/Type5Mini"; -import Type9Mini from "./mini-slides/Type9Mini"; -import Type8Mini from "./mini-slides/Type8Mini"; + import { Chart, ChartSettings } from "@/store/slices/presentationGeneration"; @@ -154,91 +148,7 @@ export const renderSlideContent = (slide: Slide, language: string) => { } }; -export const renderMiniSlideContent = (slide: Slide) => { - const { type, content } = slide; - switch (type) { - case 1: - return ( - - ); - case 2: - return ( - - ); - case 4: - return ( - - ); - case 5: - const isFullSizeGraph = - slide.content.graph?.data.categories.length > 4 && - slide.content.graph.type !== "pie"; - return ( - - ); - case 6: - return ( - - ); - case 7: - return ( - - ); - case 8: - return ( - - ); - case 9: - return ( - - ); - - default: - return null; - } -}; // CHART RENDERING export const renderChart = ( diff --git a/servers/nextjs/app/(presentation-generator)/presentation/[id]/loading.tsx b/servers/nextjs/app/(presentation-generator)/presentation/[id]/loading.tsx deleted file mode 100644 index 33989b55..00000000 --- a/servers/nextjs/app/(presentation-generator)/presentation/[id]/loading.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' -import { Skeleton } from '@/components/ui/skeleton' -const loading = () => { - return ( -
- -
- { - Array.from({ length: 10 }).map((_, index) => ( - - )) - } -
-
- ) -} - -export default loading diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx index dd33bf83..387f1ada 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx @@ -47,7 +47,7 @@ import Modal from "./Modal"; import Announcement from "@/components/Announcement"; import { getFontLink, getStaticFileUrl } from "../../utils/others"; -import path from "path"; + const Header = ({ presentation_id, @@ -132,7 +132,7 @@ const Header = ({ const metadata = await (await fetch('/api/slide-metadata', { method: 'POST', body: JSON.stringify({ - url: 'http://localhost/presentation?id=' + presentation_id, + url: 'http://localhost/pdf-maker?id=' + presentation_id, theme: currentTheme, customColors: currentColors, }) diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx index cddd299b..ffc68aba 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx @@ -24,7 +24,7 @@ import * as htmlToImage from "html-to-image"; import { setPresentationData } from "@/store/slices/presentationGeneration"; import { SortableSlide } from "./SortableSlide"; import { SortableListItem } from "./SortableListItem"; -import { renderMiniSlideContent } from "../../components/slide_config"; +import { renderSlideContent } from "../../components/slide_config"; interface SidePanelProps { selectedSlide: number; @@ -156,18 +156,6 @@ const SidePanel = ({ ) { return null; - //
- //
- //
- //
- //
- // {Array.from({ length: 8 }).map((_, index) => ( - //
- //
- - //
- // ))} - //
} return ( @@ -206,10 +194,9 @@ const SidePanel = ({ fixed xl:relative h-full z-50 xl:z-auto transition-all duration-300 ease-in-out ${isOpen ? "ml-0" : "-ml-[300px]"} - ${ - isMobilePanelOpen - ? "translate-x-0" - : "-translate-x-full xl:translate-x-0" + ${isMobilePanelOpen + ? "translate-x-0" + : "-translate-x-full xl:translate-x-0" } `} > @@ -230,34 +217,30 @@ const SidePanel = ({
@@ -323,8 +306,18 @@ const SidePanel = ({ {isStreaming ? ( presentationData && presentationData?.slides.map((slide, index) => ( -
- {renderMiniSlideContent(slide)} +
onSlideClick(index)} + className={` cursor-pointer ring-2 p-1 rounded-md transition-all duration-200 ${selectedSlide === index ? ' ring-[#5141e5]' : 'ring-gray-200' + }`} + > +
+
+
+ {renderSlideContent(slide, 'English')} +
+
)) ) : ( diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx index 1477e18c..987e2257 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx @@ -116,7 +116,7 @@ const SlideContent = ({ <>
{isStreaming && ( diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx index 1be86bd3..fc789137 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SortableSlide.tsx @@ -1,6 +1,6 @@ import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; -import { renderMiniSlideContent } from '../../components/slide_config'; +import { renderSlideContent } from '../../components/slide_config'; import { Slide } from '../../types/slide'; import { useState } from 'react'; @@ -51,12 +51,15 @@ export function SortableSlide({ slide, index, selectedSlide, onSlideClick }: Sor {...listeners} onMouseDown={handleMouseDown} onMouseUp={handleMouseUp} - className={`flex justify-center items-center cursor-pointer ${selectedSlide === index - ? 'ring-2 ring-[#5141e5]' - : 'hover:ring-2 hover:ring-gray-200' - } rounded-lg`} + className={` cursor-pointer border-[3px] p-1 shadow-lg rounded-md transition-all duration-200 ${selectedSlide === index ? ' border-[#5141e5]' : 'border-color' + }`} > - {renderMiniSlideContent(slide)} +
+
+
+ {renderSlideContent(slide, 'English')} +
+
); } \ No newline at end of file diff --git a/servers/nextjs/app/(presentation-generator)/presentation/page.tsx b/servers/nextjs/app/(presentation-generator)/presentation/page.tsx index d68b2cd0..0ccb7c51 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/page.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/page.tsx @@ -19,9 +19,9 @@ const page = () => { ); } return ( - - - + + + ); }; export default page; diff --git a/servers/nextjs/app/(presentation-generator)/styles/themes.css b/servers/nextjs/app/(presentation-generator)/styles/themes.css index be47c697..0063ee06 100644 --- a/servers/nextjs/app/(presentation-generator)/styles/themes.css +++ b/servers/nextjs/app/(presentation-generator)/styles/themes.css @@ -99,6 +99,9 @@ transition: background-color 0.3s ease, color 0.3s ease; } +.slide-theme .border-color{ + border-color: var(--slide-box); +} @keyframes progress { diff --git a/servers/nextjs/app/dashboard/components/PresentationCard.tsx b/servers/nextjs/app/dashboard/components/PresentationCard.tsx index bb4c73a4..4e0b815f 100644 --- a/servers/nextjs/app/dashboard/components/PresentationCard.tsx +++ b/servers/nextjs/app/dashboard/components/PresentationCard.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Card } from "@/components/ui/card"; -import { DashboardApi, PresentationResponse } from "../api/dashboard"; +import { DashboardApi } from "../api/dashboard"; import { DotsVerticalIcon, TrashIcon } from "@radix-ui/react-icons"; import { Popover, @@ -10,21 +10,25 @@ import { } from "@/components/ui/popover"; import { useRouter } from "next/navigation"; import { toast } from "@/hooks/use-toast"; -import { PresentationGenerationApi } from "@/app/(presentation-generator)/services/api/presentation-generation"; -import { getStaticFileUrl } from "@/app/(presentation-generator)/utils/others"; +import { renderSlideContent } from "@/app/(presentation-generator)/components/slide_config"; export const PresentationCard = ({ id, title, created_at, thumbnail, - type, -}: PresentationResponse & { type: "video" | "slide" }) => { + theme, +}: { + id: string; + title: string; + created_at: string; + thumbnail: string; + theme: any; +}) => { const router = useRouter(); const handlePreview = (e: React.MouseEvent) => { e.preventDefault(); - router.push(`/presentation?id=${id}`); }; @@ -38,7 +42,7 @@ export const PresentationCard = ({ variant: "default", }); const response = await DashboardApi.deletePresentation(id); - console.log(response); + if (response) { toast({ title: "Presentation deleted", @@ -55,10 +59,25 @@ export const PresentationCard = ({ window.location.reload(); }; + const themeName = theme.name; + // Create CSS variables object + const cssVariables = { + '--slide-bg': theme.colors.slideBg, + '--slide-title': theme.colors.slideTitle, + '--slide-heading': theme.colors.slideHeading, + '--slide-description': theme.colors.slideDescription, + '--slide-box': theme.colors.slideBox, + '--icon-bg': theme.colors.iconBg, + '--background': theme.colors.background, + '--font-family': theme.colors.fontFamily, + } as React.CSSProperties; + return (
{/* Date */} @@ -83,7 +102,7 @@ export const PresentationCard = ({
{/* Thumbnail */} -
+ {/*
{thumbnail ? (
)} +
*/} +
+
+
+ {renderSlideContent({ + id: 'mock-slide-1', + type: 1, + index: 0, + design_index: 1, + properties: null, + images: ['/static/user_data/ee7cb066-86d0-45fc-adc9-15bf565eab30/images/af54ed41-483e-4983-aef0-b254aac48408.jpg'], + icons: [], + graph_id: null, + presentation: id, + content: { + title: title || 'Sample Presentation', + body: "This is a sample slide description to demonstrate the layout and styling. The content here helps visualize how actual presentation content would appear.", + infographics: [], + image_prompts: ['Sample image showing business growth'] + }, + }, 'English')} +
{/* Icon and Title */}
- {type === "video" ? ( - - - - - - - - ) : ( - - - - )} - + + +

{title}

diff --git a/servers/nextjs/app/dashboard/components/PresentationGrid.tsx b/servers/nextjs/app/dashboard/components/PresentationGrid.tsx index b6ab0abb..205ab709 100644 --- a/servers/nextjs/app/dashboard/components/PresentationGrid.tsx +++ b/servers/nextjs/app/dashboard/components/PresentationGrid.tsx @@ -102,7 +102,8 @@ export const PresentationGrid = ({ ))}
diff --git a/servers/nextjs/app/layout.tsx b/servers/nextjs/app/layout.tsx index d9fbcd08..783bf2b9 100644 --- a/servers/nextjs/app/layout.tsx +++ b/servers/nextjs/app/layout.tsx @@ -4,6 +4,7 @@ import { Fraunces, Montserrat, Inria_Serif, Roboto, Instrument_Sans } from "next import "./globals.css"; import { Providers } from "./providers"; import { Toaster } from "@/components/ui/toaster"; +import { FooterProvider } from "./(presentation-generator)/context/footerContext"; const fraunces = Fraunces({ subsets: ["latin"], @@ -100,7 +101,12 @@ export default function RootLayout({ - {children} + + + + {children} + + From 33ed6eaa5b94b5905728bf7a02a356e35a2f0a38 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Sat, 12 Jul 2025 01:52:10 +0545 Subject: [PATCH 2/3] remove(sidepanel,api/dashboard): remove thumbnail logic,api endpoint & SS package --- .../presentation/components/SidePanel.tsx | 43 +------------------ servers/nextjs/app/dashboard/api/dashboard.ts | 22 +--------- servers/nextjs/package.json | 1 - 3 files changed, 2 insertions(+), 64 deletions(-) diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx index ffc68aba..f5fc1a5e 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx @@ -5,7 +5,6 @@ import ToolTip from "@/components/ToolTip"; import { Button } from "@/components/ui/button"; import { useDispatch, useSelector } from "react-redux"; import { RootState } from "@/store/store"; -import { DashboardApi } from "@/app/dashboard/api/dashboard"; import { DndContext, closestCenter, @@ -20,7 +19,6 @@ import { sortableKeyboardCoordinates, verticalListSortingStrategy, } from "@dnd-kit/sortable"; -import * as htmlToImage from "html-to-image"; import { setPresentationData } from "@/store/slices/presentationGeneration"; import { SortableSlide } from "./SortableSlide"; import { SortableListItem } from "./SortableListItem"; @@ -58,18 +56,7 @@ const SidePanel = ({ } }, [isMobilePanelOpen]); - useEffect(() => { - if ( - presentationData?.presentation?.thumbnail === null && - presentationData.slides.some( - (slide) => slide.images && slide.images.length > 0 - ) - ) { - setTimeout(() => { - setSlideThumbnail(); - }, 4000); - } - }, [presentationData]); + const sensors = useSensors( useSensor(PointerSensor), useSensor(KeyboardSensor, { @@ -84,17 +71,6 @@ const SidePanel = ({ } }; - const dataUrlToFile = (dataUrl: string, filename: string) => { - const arr = dataUrl.split(","); - const mime = arr[0].match(/:(.*)/)?.[1]; - const bstr = atob(arr[1]); - let n = bstr.length; - const u8arr = new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - return new File([u8arr], filename, { type: mime }); - }; const handleDragEnd = (event: any) => { const { active, over } = event; @@ -130,23 +106,6 @@ const SidePanel = ({ } }; - const setSlideThumbnail = async () => { - const slideContainer = document.querySelector(".slide-container"); - if (!slideContainer) return; - const image = await htmlToImage - .toPng(slideContainer as HTMLElement) - .then((dataUrl) => { - return dataUrl; - }); - - const file = dataUrlToFile(image, "thumbnail.png"); - - const response = await DashboardApi.setSlideThumbnail( - presentationData?.presentation?.id!, - file - ); - }; - // Loading shimmer component if ( !presentationData || diff --git a/servers/nextjs/app/dashboard/api/dashboard.ts b/servers/nextjs/app/dashboard/api/dashboard.ts index 351b5ad7..8ea66967 100644 --- a/servers/nextjs/app/dashboard/api/dashboard.ts +++ b/servers/nextjs/app/dashboard/api/dashboard.ts @@ -83,25 +83,5 @@ export class DashboardApi { throw error; } } - static async setSlideThumbnail(presentation_id: string, file: any) { - const formData = new FormData(); - - formData.append("presentation_id", presentation_id); - formData.append("thumbnail", file); - try { - const response = await fetch( - `/api/v1/ppt/presentation/thumbnail`, - { - method: "POST", - headers: getHeaderForFormData(), - body: formData, - } - ); - const data = await response.json(); - return data; - } catch (error) { - console.error("Error setting slide thumbnail:", error); - throw error; - } - } + } diff --git a/servers/nextjs/package.json b/servers/nextjs/package.json index 276d4876..35d5139d 100644 --- a/servers/nextjs/package.json +++ b/servers/nextjs/package.json @@ -42,7 +42,6 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cmdk": "^1.0.0", - "html-to-image": "^1.11.13", "jsonrepair": "^3.12.0", "lucide-react": "^0.447.0", "marked": "^15.0.11", From e86bc5259ab942dfafd5700f028033380fe4a364 Mon Sep 17 00:00:00 2001 From: sauravniraula Date: Sat, 12 Jul 2025 18:46:30 +0545 Subject: [PATCH 3/3] fix(env): changes SQL_URL to database url, feat(fastapi): returns first slide with presentation --- docker-compose.yml | 8 ++++---- .../handlers/generate_presentation.py | 1 + .../handlers/get_presentations.py | 16 +++++++++++++-- .../handlers/list_available_custom_models.py | 14 +++++++++++++ .../api/routers/presentation/models.py | 20 +++++++++++++++++++ .../api/routers/presentation/router.py | 19 +++++++++++------- servers/fastapi/api/services/database.py | 6 +++--- 7 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 servers/fastapi/api/routers/presentation/handlers/list_available_custom_models.py diff --git a/docker-compose.yml b/docker-compose.yml index 871db042..38211c6c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,7 @@ services: - CUSTOM_LLM_API_KEY=${CUSTOM_LLM_API_KEY} - CUSTOM_MODEL=${CUSTOM_MODEL} - PEXELS_API_KEY=${PEXELS_API_KEY} - - SQL_URL=${SQL_URL} + - DATABASE_URL=${DATABASE_URL} production-gpu: # image: ghcr.io/presenton/presenton:latest @@ -50,7 +50,7 @@ services: - CUSTOM_LLM_API_KEY=${CUSTOM_LLM_API_KEY} - CUSTOM_MODEL=${CUSTOM_MODEL} - PEXELS_API_KEY=${PEXELS_API_KEY} - - SQL_URL=${SQL_URL} + - DATABASE_URL=${DATABASE_URL} development: build: @@ -74,7 +74,7 @@ services: - CUSTOM_LLM_API_KEY=${CUSTOM_LLM_API_KEY} - CUSTOM_MODEL=${CUSTOM_MODEL} - PEXELS_API_KEY=${PEXELS_API_KEY} - - SQL_URL=${SQL_URL} + - DATABASE_URL=${DATABASE_URL} development-gpu: build: @@ -105,4 +105,4 @@ services: - CUSTOM_LLM_API_KEY=${CUSTOM_LLM_API_KEY} - CUSTOM_MODEL=${CUSTOM_MODEL} - PEXELS_API_KEY=${PEXELS_API_KEY} - - SQL_URL=${SQL_URL} \ No newline at end of file + - DATABASE_URL=${DATABASE_URL} \ No newline at end of file diff --git a/servers/fastapi/api/routers/presentation/handlers/generate_presentation.py b/servers/fastapi/api/routers/presentation/handlers/generate_presentation.py index 55c4dfc3..2d707e3f 100644 --- a/servers/fastapi/api/routers/presentation/handlers/generate_presentation.py +++ b/servers/fastapi/api/routers/presentation/handlers/generate_presentation.py @@ -153,6 +153,7 @@ class GeneratePresentationHandler(FetchAssetsOnPresentationGenerationMixin): print("-" * 40) print("Exporting Presentation") export_request_body["presentation_id"] = self.presentation_id + print(export_request_body) export_request = ExportAsRequest(**export_request_body) presentation_and_path = await ExportAsPptxHandler(export_request).post( diff --git a/servers/fastapi/api/routers/presentation/handlers/get_presentations.py b/servers/fastapi/api/routers/presentation/handlers/get_presentations.py index d7d09951..809a99c8 100644 --- a/servers/fastapi/api/routers/presentation/handlers/get_presentations.py +++ b/servers/fastapi/api/routers/presentation/handlers/get_presentations.py @@ -1,5 +1,6 @@ from sqlmodel import select, exists from api.models import LogMetadata +from api.routers.presentation.models import PresentationWithOneSlide from api.services.logging import LoggingService from api.sql_models import PresentationSqlModel, SlideSqlModel from api.services.database import get_sql_session @@ -18,8 +19,19 @@ class GetPresentationsHandler: ) ) ).all() - presentations.sort(key=lambda x: x.created_at, reverse=True) + presentations_with_slide = [] + for presentation in presentations: + slide = sql_session.exec( + select(SlideSqlModel) + .where(SlideSqlModel.presentation == presentation.id) + .where(SlideSqlModel.index == 0) + ).first() + presentations_with_slide.append( + PresentationWithOneSlide.from_presentation_and_slide( + presentation, slide + ) + ) logging_service.logger.info( logging_service.message( @@ -27,4 +39,4 @@ class GetPresentationsHandler: ), extra=log_metadata.model_dump(), ) - return presentations + return presentations_with_slide diff --git a/servers/fastapi/api/routers/presentation/handlers/list_available_custom_models.py b/servers/fastapi/api/routers/presentation/handlers/list_available_custom_models.py new file mode 100644 index 00000000..dbdf88d8 --- /dev/null +++ b/servers/fastapi/api/routers/presentation/handlers/list_available_custom_models.py @@ -0,0 +1,14 @@ +from typing import Optional +from api.services.logging import LoggingService +from api.models import LogMetadata +from api.utils.model_utils import list_available_custom_models + + +class ListAvailableCustomModelsHandler: + + def __init__(self, url: Optional[str] = None, api_key: Optional[str] = None): + self.url = url + self.api_key = api_key + + async def get(self, logging_service: LoggingService, log_metadata: LogMetadata): + return await list_available_custom_models(self.url, self.api_key) diff --git a/servers/fastapi/api/routers/presentation/models.py b/servers/fastapi/api/routers/presentation/models.py index fb63b3c7..70af5abc 100644 --- a/servers/fastapi/api/routers/presentation/models.py +++ b/servers/fastapi/api/routers/presentation/models.py @@ -177,3 +177,23 @@ class OllamaModelStatusResponse(BaseModel): class OllamaSupportedModelsResponse(BaseModel): models: List[OllamaModelMetadata] + + +class PresentationWithOneSlide(BaseModel): + id: str + created_at: datetime + theme: Optional[dict] = None + title: Optional[str] = None + slide: SlideSqlModel + + @classmethod + def from_presentation_and_slide( + cls, presentation: PresentationSqlModel, slide: SlideSqlModel + ): + return cls( + id=presentation.id, + created_at=presentation.created_at, + theme=presentation.theme, + title=presentation.title, + slide=slide, + ) diff --git a/servers/fastapi/api/routers/presentation/router.py b/servers/fastapi/api/routers/presentation/router.py index 3b3a0894..825ea14c 100644 --- a/servers/fastapi/api/routers/presentation/router.py +++ b/servers/fastapi/api/routers/presentation/router.py @@ -1,7 +1,6 @@ from typing import Annotated, List, Optional import uuid from fastapi import APIRouter, BackgroundTasks, Body, File, Form, UploadFile -import openai from api.models import SessionModel from api.request_utils import RequestUtils @@ -35,6 +34,9 @@ from api.routers.presentation.handlers.generate_outlines import ( ) from api.routers.presentation.handlers.get_presentation import GetPresentationHandler from api.routers.presentation.handlers.get_presentations import GetPresentationsHandler +from api.routers.presentation.handlers.list_available_custom_models import ( + ListAvailableCustomModelsHandler, +) from api.routers.presentation.handlers.list_ollama_pulled_models import ( ListPulledOllamaModelsHandler, ) @@ -80,13 +82,10 @@ from api.routers.presentation.models import ( SearchImageRequest, UpdatePresentationThemeRequest, PresentationUpdateRequest, + PresentationWithOneSlide, ) from api.sql_models import PresentationSqlModel -from api.utils.model_utils import get_llm_client, list_available_custom_models from api.utils.utils import handle_errors -from image_processor.images_finder import ( - generate_image_google, -) from ppt_generator.models.slide_model import SlideModel route_prefix = "/api/v1/ppt" @@ -94,7 +93,7 @@ presentation_router = APIRouter(prefix=route_prefix) @presentation_router.get( - "/user_presentations", response_model=List[PresentationSqlModel] + "/user_presentations", response_model=List[PresentationWithOneSlide] ) async def get_user_presentations(): request_utils = RequestUtils(f"{route_prefix}/user_presentations") @@ -398,4 +397,10 @@ async def list_custom_models( url: Annotated[Optional[str], Body()] = None, api_key: Annotated[Optional[str], Body()] = None, ): - return await list_available_custom_models(url, api_key) + request_utils = RequestUtils(f"{route_prefix}/models/list/custom") + logging_service, log_metadata = await request_utils.initialize_logger() + return await handle_errors( + ListAvailableCustomModelsHandler(url, api_key).get, + logging_service, + log_metadata, + ) diff --git a/servers/fastapi/api/services/database.py b/servers/fastapi/api/services/database.py index ea9f3cd1..ece0430d 100644 --- a/servers/fastapi/api/services/database.py +++ b/servers/fastapi/api/services/database.py @@ -4,14 +4,14 @@ from sqlalchemy import create_engine from sqlmodel import Session -sql_url = os.getenv("SQL_URL") or "sqlite:///" + os.path.join( +database_url = os.getenv("DATABASE_URL") or "sqlite:///" + os.path.join( os.getenv("APP_DATA_DIRECTORY"), "fastapi.db" ) connect_args = {} -if "sqlite" in sql_url: +if "sqlite" in database_url: connect_args["check_same_thread"] = False -sql_engine = create_engine(sql_url, connect_args=connect_args) +sql_engine = create_engine(database_url, connect_args=connect_args) @contextmanager