From 92cc53bf083bf3dddcf7632f1d904d5b86edfc1e Mon Sep 17 00:00:00 2001 From: Krishav Raj Singh Date: Mon, 25 Aug 2025 06:27:50 +0530 Subject: [PATCH] ui: download pptx --- .../FullScreenPresentationViewer.tsx | 7 ++- .../presentation-tools/PresentationViewer.tsx | 56 +++++++++++++++++-- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx b/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx index 49d9a5c3..8576d43d 100644 --- a/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx +++ b/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx @@ -46,6 +46,7 @@ interface FullScreenPresentationViewerProps { sandboxUrl?: string; initialSlide?: number; onPDFDownload?: (setIsDownloadingPDF: (isDownloading: boolean) => void) => void; + onPPTXDownload?: (setIsDownloadingPPTX: (isDownloading: boolean) => void) => void; } export function FullScreenPresentationViewer({ @@ -55,6 +56,7 @@ export function FullScreenPresentationViewer({ sandboxUrl, initialSlide = 1, onPDFDownload, + onPPTXDownload, }: FullScreenPresentationViewerProps) { const [metadata, setMetadata] = useState(null); const [currentSlide, setCurrentSlide] = useState(initialSlide); @@ -65,6 +67,7 @@ export function FullScreenPresentationViewer({ const [showControls, setShowControls] = useState(true); const [showEditor, setShowEditor] = useState(false); const [isDownloadingPDF, setIsDownloadingPDF] = useState(false); + const [isDownloadingPPTX, setIsDownloadingPPTX] = useState(false); // Create a stable refresh timestamp when metadata changes (like PresentationViewer) const refreshTimestamp = useMemo(() => Date.now(), [metadata]); @@ -418,7 +421,7 @@ export function FullScreenPresentationViewer({ className="h-8 w-8 p-0" title="Export presentation" > - {isDownloadingPDF ? ( + {(isDownloadingPDF || isDownloadingPPTX) ? ( ) : ( @@ -430,7 +433,7 @@ export function FullScreenPresentationViewer({ PDF - + onPPTXDownload(setIsDownloadingPPTX)}> PPTX diff --git a/frontend/src/components/thread/tool-views/presentation-tools/PresentationViewer.tsx b/frontend/src/components/thread/tool-views/presentation-tools/PresentationViewer.tsx index f0b7e690..1631b579 100644 --- a/frontend/src/components/thread/tool-views/presentation-tools/PresentationViewer.tsx +++ b/frontend/src/components/thread/tool-views/presentation-tools/PresentationViewer.tsx @@ -79,6 +79,7 @@ export function PresentationViewer({ const [isFullScreenOpen, setIsFullScreenOpen] = useState(false); const [fullScreenInitialSlide, setFullScreenInitialSlide] = useState(null); const [isDownloadingPDF, setIsDownloadingPDF] = useState(false); + const [isDownloadingPPTX, setIsDownloadingPPTX] = useState(false); // Extract presentation info from tool data const { toolResult } = extractToolData(toolContent); @@ -505,6 +506,36 @@ export function PresentationViewer({ } }; + const downloadPresentationAsPPTX = async (sandboxUrl: string, presentationName: string): Promise => { + try { + const response = await fetch(`${sandboxUrl}/presentation/convert-to-pptx`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + presentation_path: `/workspace/presentations/${presentationName}`, + download: true + }) + }); + + if (!response.ok) { + throw new Error('Failed to download PPTX'); + } + + const blob = await response.blob(); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${presentationName}.pptx`; + a.click(); + window.URL.revokeObjectURL(url); + } catch (error) { + console.error('Error downloading PPTX:', error); + toast.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + }; + const handlePDFDownload = useCallback(async (setIsDownloadingPDF: (isDownloading: boolean) => void) => { @@ -520,6 +551,20 @@ export function PresentationViewer({ } }, [project?.sandbox?.sandbox_url, extractedPresentationName]); + const handlePPTXDownload = useCallback(async (setIsDownloadingPPTX: (isDownloading: boolean) => void) => { + + if (!project?.sandbox?.sandbox_url || !extractedPresentationName) return; + + setIsDownloadingPPTX(true); + try{ + await downloadPresentationAsPPTX(project.sandbox.sandbox_url, extractedPresentationName); + } catch (error) { + console.error('Error downloading PPTX:', error); + } finally { + setIsDownloadingPPTX(false); + } + }, [project?.sandbox?.sandbox_url, extractedPresentationName]); + return ( @@ -560,7 +605,7 @@ export function PresentationViewer({ className="h-8 w-8 p-0" title="Export presentation" > - {isDownloadingPDF ? ( + {(isDownloadingPDF || isDownloadingPPTX) ? ( ) : ( @@ -571,16 +616,15 @@ export function PresentationViewer({ handlePDFDownload(setIsDownloadingPDF)} className="cursor-pointer" + disabled={isDownloadingPPTX} > PDF { - // TODO: Implement PPTX export - console.log('Export as PPTX'); - }} + onClick={() => handlePPTXDownload(setIsDownloadingPPTX)} className="cursor-pointer" + disabled={isDownloadingPDF} > PPTX @@ -591,6 +635,7 @@ export function PresentationViewer({ console.log('Export to Google Slides'); }} className="cursor-pointer" + disabled={isDownloadingPDF || isDownloadingPPTX} > Google Slides @@ -781,6 +826,7 @@ export function PresentationViewer({ sandboxUrl={project?.sandbox?.sandbox_url} initialSlide={fullScreenInitialSlide || visibleSlide || currentSlideNumber || slides[0]?.number || 1} onPDFDownload={handlePDFDownload} + onPPTXDownload={handlePPTXDownload} /> );