diff --git a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx index 96777dbd..883cb91d 100644 --- a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx +++ b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx @@ -7,11 +7,12 @@ import { Switch } from '@/components/ui/switch' import { cn } from '@/lib/utils' import { LLMConfig } from '@/types/llm_config' import { DALLE_3_QUALITY_OPTIONS, GPT_IMAGE_1_5_QUALITY_OPTIONS, IMAGE_PROVIDERS } from '@/utils/providerConstants' -import { Check, ChevronsUpDown } from 'lucide-react' +import { Check, ChevronUp, Eye, EyeOff } from 'lucide-react' import React, { useState } from 'react' const ImageProvider = ({ llmConfig, setLlmConfig }: { llmConfig: LLMConfig, setLlmConfig: (config: any) => void }) => { const [openImageProviderSelect, setOpenImageProviderSelect] = useState(false); + const [showApiKey, setShowApiKey] = useState(false); const isImageGenerationDisabled = llmConfig.DISABLE_IMAGE_GENERATION ?? false; const handleChangeImageGenerationDisabled = (value: boolean) => { setLlmConfig((prev: any) => ({ @@ -173,7 +174,7 @@ const ImageProvider = ({ llmConfig, setLlmConfig }: { llmConfig: LLMConfig, setL : "Select image provider"} - +
+
diff --git a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/SettingPage.tsx b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/SettingPage.tsx index c040630f..ce55899c 100644 --- a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/SettingPage.tsx +++ b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/SettingPage.tsx @@ -15,6 +15,7 @@ import { trackEvent, MixpanelEvent } from "@/utils/mixpanel"; import SettingSideBar from "./SettingSideBar"; import TextProvider from "./TextProvider"; import ImageProvider from "./ImageProvider"; +import { IMAGE_PROVIDERS, LLM_PROVIDERS } from "@/utils/providerConstants"; // Button state interface interface ButtonState { @@ -156,6 +157,31 @@ const SettingsPage = () => { } + const textProviderKey = llmConfig.LLM || "openai"; + const textProviderLabel = + LLM_PROVIDERS[textProviderKey]?.label || textProviderKey; + const selectedTextModel = + textProviderKey === "openai" + ? llmConfig.OPENAI_MODEL + : textProviderKey === "google" + ? llmConfig.GOOGLE_MODEL + : textProviderKey === "anthropic" + ? llmConfig.ANTHROPIC_MODEL + : textProviderKey === "ollama" + ? llmConfig.OLLAMA_MODEL + : textProviderKey === "custom" + ? llmConfig.CUSTOM_MODEL + : ""; + const textSummary = selectedTextModel + ? `${textProviderLabel} (${selectedTextModel})` + : textProviderLabel; + + const imageSummary = llmConfig.DISABLE_IMAGE_GENERATION + ? "Image generation disabled" + : llmConfig.IMAGE_PROVIDER + ? IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]?.label || llmConfig.IMAGE_PROVIDER + : "No image provider"; + return (
{
-
+

Settings

+

+ {textSummary} ยท {imageSummary} +

diff --git a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx index 47b3f5d3..5ab0d15e 100644 --- a/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx +++ b/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx @@ -5,7 +5,7 @@ import { Switch } from '@/components/ui/switch'; import { cn } from '@/lib/utils'; import { LLMConfig } from '@/types/llm_config'; import { LLM_PROVIDERS } from '@/utils/providerConstants'; -import { Check, ChevronsUpDown, Loader2, Eye, EyeOff } from 'lucide-react'; +import { Check, ChevronsUpDown, Loader2, Eye, EyeOff, ChevronUp } from 'lucide-react'; import React, { useEffect, useMemo, useRef, useState } from 'react' import { toast } from 'sonner'; @@ -245,7 +245,7 @@ const TextProvider = ({ : "Select text provider"}
- + - + { /> -
+

Select a Slide Layout

- setShowNewSlideSelection(false)} className="text-gray-500 text-2xl cursor-pointer" /> @@ -111,7 +110,7 @@ const NewSlideV1 = ({

Select a Slide Layout

- setShowNewSlideSelection(false)} className="text-gray-500 text-2xl cursor-pointer" /> diff --git a/servers/nextjs/app/(presentation-generator)/components/PresentationMode.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationMode.tsx similarity index 98% rename from servers/nextjs/app/(presentation-generator)/components/PresentationMode.tsx rename to servers/nextjs/app/(presentation-generator)/presentation/components/PresentationMode.tsx index d9fbc1b2..41b8d913 100644 --- a/servers/nextjs/app/(presentation-generator)/components/PresentationMode.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationMode.tsx @@ -10,8 +10,9 @@ import { EyeOff, } from "lucide-react"; import { Button } from "@/components/ui/button"; -import { Slide } from "../types/slide"; -import { V1ContentRender } from "./V1ContentRender"; +import { Slide } from "../../types/slide"; +import { V1ContentRender } from "../../components/V1ContentRender"; + interface PresentationModeProps { diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx index 9603141d..00d1fe72 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationPage.tsx @@ -3,13 +3,13 @@ import React, { useState } from "react"; import { useSelector } from "react-redux"; import { RootState } from "@/store/store"; import { Skeleton } from "@/components/ui/skeleton"; -import PresentationMode from "../../components/PresentationMode"; +import PresentationMode from "./PresentationMode"; import SidePanel from "./SidePanel"; import SlideContent from "./SlideContent"; import { Button } from "@/components/ui/button"; import { usePathname } from "next/navigation"; import { trackEvent, MixpanelEvent } from "@/utils/mixpanel"; -import { AlertCircle, Loader2 } from "lucide-react"; +import { AlertCircle } from "lucide-react"; import { usePresentationStreaming, usePresentationData, @@ -79,7 +79,6 @@ const PresentationPage: React.FC = ({ handleSlideChange(newSlide, presentationData); }; - // useEffect(() => { // if(!loading && !isStreaming && presentationData?.slides && presentationData?.slides.length > 0){ // const presentation_id = presentationData?.slides[0].layout.split(":")[0].split("custom-")[1]; @@ -132,6 +131,7 @@ const PresentationPage: React.FC = ({ diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx index 301f2e41..20e13ae7 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SidePanel.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { } from "react"; +import React, { useState } from "react"; import { Plus } from "lucide-react"; import { useDispatch, useSelector } from "react-redux"; import { RootState } from "@/store/store"; @@ -22,10 +22,12 @@ import { SortableSlide } from "./SortableSlide"; import SlideScale from "../../components/PresentationRender"; import { Separator } from "@/components/ui/separator"; import { useRouter } from "next/navigation"; +import NewSlide from "./NewSlide"; interface SidePanelProps { selectedSlide: number; onSlideClick: (index: number) => void; + presentationId: string; loading: boolean; } @@ -33,11 +35,13 @@ interface SidePanelProps { const SidePanel = ({ selectedSlide, onSlideClick, + presentationId, loading, }: SidePanelProps) => { const router = useRouter(); + const [showNewSlideSelection, setShowNewSlideSelection] = useState(false); const { presentationData, isStreaming } = useSelector( (state: RootState) => state.presentationGeneration @@ -45,6 +49,18 @@ const SidePanel = ({ const dispatch = useDispatch(); + const lastSlideIndex = presentationData?.slides?.length + ? presentationData.slides.length - 1 + : 0; + const lastSlideTemplateId = presentationData?.slides?.[lastSlideIndex]?.layout + ? presentationData.slides[lastSlideIndex].layout.split(":")[0] + : ""; + + const handleAddSlideClick = () => { + if (!presentationData?.slides?.length || isStreaming) return; + setShowNewSlideSelection(true); + }; + @@ -174,12 +190,28 @@ const SidePanel = ({ -
+ {showNewSlideSelection && lastSlideTemplateId && ( +
+
+ +
+
+ )}
); }; diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx index 6030e48f..3ed7eb6a 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/SlideContent.tsx @@ -18,9 +18,9 @@ import { } from "@/store/slices/presentationGeneration"; import { usePathname } from "next/navigation"; import { trackEvent, MixpanelEvent } from "@/utils/mixpanel"; -import NewSlide from "../../components/NewSlide"; import { addToHistory } from "@/store/slices/undoRedoSlice"; import { V1ContentRender } from "../../components/V1ContentRender"; +import NewSlide from "./NewSlide"; interface SlideContentProps { slide: any;