From fc1bad2d7cbdea44e6977e62f9be5c1ba664b53b Mon Sep 17 00:00:00 2001 From: sudipnext Date: Fri, 20 Mar 2026 11:41:50 +0545 Subject: [PATCH] feat: add new image assets and update presentation generation state - Added new image assets: image_mode.png, logo-with-bg.png, image-provider.png, and openai.png. - Enhanced presentation generation state to include theme property. - Introduced updateTheme action in presentation generation slice. - Updated user configuration with default LLM and image provider settings. - Modified Tailwind CSS configuration to include new font families. - Improved API utility functions for better handling of URLs in Electron environment. - Adjusted PPTX model utility for border radius handling. - Expanded provider constants to include URLs and icons for LLM providers. - Updated provider utility functions for consistent API URL usage. - Added new quality options for image generation providers. - Updated package-lock.json to include new dependencies for react-colorful and scheduler. --- .../(dashboard)/Components/DashboardNav.tsx | 64 + .../Components/DashboardSidebar.tsx | 128 + .../dashboard/components/DashboardPage.tsx | 111 + .../dashboard/components/EmptyState.tsx | 22 + .../dashboard/components/Header.tsx | 31 + .../dashboard/components/PresentationCard.tsx | 105 + .../dashboard/components/PresentationGrid.tsx | 124 + .../components/PresentationListItem.tsx | 44 + .../(dashboard)/dashboard/loading.tsx | 28 + .../{ => (dashboard)}/dashboard/page.tsx | 0 .../(dashboard)/dashboard/types.ts | 16 + .../(dashboard)/layout.tsx | 16 + .../(dashboard)/settings/ImageProvider.tsx | 355 ++ .../(dashboard)/settings/SettingPage.tsx | 345 ++ .../(dashboard)/settings/SettingSideBar.tsx | 68 + .../(dashboard)/settings/TextProvider.tsx | 576 ++ .../(dashboard)/settings/loading.tsx | 77 + .../{ => (dashboard)}/settings/page.tsx | 0 .../components/CreateCustomTemplate.tsx | 40 + .../templates/components/TemplatePanel.tsx | 278 + .../(dashboard)/templates/loading.tsx | 58 + .../(dashboard)/templates/page.tsx | 10 + .../ThemePanel/ColorPickerComponent.tsx | 66 + .../components/ThemePanel/CustomTabEmpty.tsx | 41 + .../theme/components/ThemePanel/FontCard.tsx | 44 + .../components/ThemePanel/StepIndicator.tsx | 33 + .../theme/components/ThemePanel/ThemeCard.tsx | 185 + .../theme/components/ThemePanel/constants.ts | 205 + .../theme/components/ThemePanel/index.tsx | 1066 ++++ .../theme/components/ThemePanel/types.ts | 20 + .../theme/components/ThemePanel/utils.ts | 10 + .../(dashboard)/theme/loading.tsx | 54 + .../(dashboard)/theme/page.tsx | 9 + .../components/HeaderNab.tsx | 4 +- .../components/ImageEditor.tsx | 6 +- .../components/MarkdownEditor.tsx | 15 +- .../components/V1ContentRender.tsx | 2 +- .../components/APIKeyWarning.tsx | 4 +- .../components/LoadingSpinner.tsx | 2 +- .../hooks/useFontManagement.ts | 2 +- .../custom-template/hooks/useLayoutSaving.ts | 4 +- .../custom-template/hooks/useSlideEdit.ts | 2 +- .../hooks/useSlideProcessing.ts | 6 +- .../custom-template/page.tsx | 2 +- .../custom-template/types/index.ts | 2 - .../hooks/useFontLoad.tsx | 36 + .../outline/components/CustomTemplateCard.tsx | 74 +- .../outline/components/EmptyStateView.tsx | 4 +- .../outline/components/GenerateButton.tsx | 33 +- .../outline/components/OutlineContent.tsx | 33 +- .../outline/components/OutlineItem.tsx | 50 +- .../outline/components/OutlinePage.tsx | 38 +- .../outline/components/TemplateSelection.tsx | 244 +- .../outline/hooks/useOutlineManagement.ts | 16 +- .../outline/hooks/useOutlineStreaming.ts | 3 +- .../hooks/usePresentationGeneration.ts | 2 +- .../(presentation-generator)/outline/page.tsx | 11 +- .../pdf-maker/PdfMakerPage.tsx | 50 +- .../presentation/components/NewSlide.tsx | 135 + .../components/PresentationHeader.tsx | 318 + .../components/PresentationMode.tsx | 306 + .../components/PresentationPage.tsx | 120 +- .../presentation/components/SidePanel.tsx | 283 +- .../presentation/components/SlideContent.tsx | 199 +- .../presentation/components/SortableSlide.tsx | 4 +- .../presentation/components/ThemeSelector.tsx | 122 + .../presentation/hooks/usePresentationData.ts | 42 +- .../hooks/usePresentationStreaming.ts | 3 +- .../presentation/page.tsx | 2 +- .../services/api/dashboard.ts | 28 +- .../services/api/params.ts | 17 +- .../services/api/presentation-generation.ts | 21 +- .../services/api/template.ts | 7 +- .../services/api/theme.ts | 121 + .../services/api/types.ts | 46 +- .../hooks/useTemplateLayoutsAutoSave.ts | 12 +- .../template-preview/[slug]/page.tsx | 324 +- .../template-preview/page.tsx | 4 +- .../upload/components/AdvanceSettings.tsx | 172 + .../components/ConfigurationSelects.tsx | 608 +- .../upload/components/LanguageSelector.tsx | 69 + .../upload/components/NumberOfSlide.tsx | 90 + .../upload/components/PromptInput.tsx | 28 +- .../upload/components/SupportingDoc.tsx | 386 +- .../upload/components/UploadPage.tsx | 82 +- .../upload/loading.tsx | 2 +- .../(presentation-generator)/upload/page.tsx | 10 +- electron/servers/nextjs/app/globals.css | 16 +- .../nextjs/app/hooks/useRemoteSvgIcon.tsx | 9 +- electron/servers/nextjs/app/layout.tsx | 29 +- .../general/ChartWithBulletsSlideLayout.tsx | 11 +- .../app/presentation-templates/index.tsx | 3 + .../nextjs/components/AnthropicConfig.tsx | 313 +- .../servers/nextjs/components/CodexConfig.tsx | 12 +- .../nextjs/components/CustomConfig.tsx | 2 +- .../nextjs/components/GoogleConfig.tsx | 286 +- electron/servers/nextjs/components/Home.tsx | 318 +- .../components/ImageSelectionConfig.tsx | 357 ++ .../nextjs/components/LLMSelection.tsx | 373 +- .../nextjs/components/MarkDownRender.tsx | 38 + .../nextjs/components/OllamaConfig.tsx | 2 +- .../components/OnBoarding/FinalStep.tsx | 31 + .../OnBoarding/GenerationWithImage.tsx | 11 + .../components/OnBoarding/ModeSelectStep.tsx | 61 + .../OnBoarding/OnBoardingHeader.tsx | 36 + .../OnBoarding/OnBoardingSlidebar.tsx | 19 + .../components/OnBoarding/PresentonMode.tsx | 940 +++ .../nextjs/components/OpenAIConfig.tsx | 319 +- .../servers/nextjs/components/ToolTip.tsx | 4 +- .../servers/nextjs/components/Wrapper.tsx | 2 +- electron/servers/nextjs/next.config.mjs | 11 +- electron/servers/nextjs/package-lock.json | 11 + electron/servers/nextjs/package.json | 1 + electron/servers/nextjs/public/card_bg.svg | 5311 +++++++++++++++++ .../nextjs/public/create_presentation.png | Bin 0 -> 232862 bytes .../nextjs/public/final_onboarding.png | Bin 0 -> 128250 bytes .../servers/nextjs/public/image-markup.svg | 9 + electron/servers/nextjs/public/image_mode.png | Bin 0 -> 5966 bytes .../servers/nextjs/public/logo-with-bg.png | Bin 0 -> 5974 bytes .../public/providers/image-provider.png | Bin 0 -> 30564 bytes .../nextjs/public/providers/openai.png | Bin 0 -> 7049 bytes .../store/slices/presentationGeneration.ts | 9 + .../servers/nextjs/store/slices/userConfig.ts | 6 +- electron/servers/nextjs/tailwind.config.ts | 4 +- electron/servers/nextjs/utils/api.ts | 32 +- .../servers/nextjs/utils/pptx_models_utils.ts | 2 +- .../servers/nextjs/utils/providerConstants.ts | 42 + .../servers/nextjs/utils/providerUtils.ts | 12 +- package-lock.json | 57 +- 129 files changed, 14965 insertions(+), 2169 deletions(-) create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardNav.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardSidebar.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/DashboardPage.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/EmptyState.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/Header.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationCard.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationGrid.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationListItem.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/loading.tsx rename electron/servers/nextjs/app/(presentation-generator)/{ => (dashboard)}/dashboard/page.tsx (100%) create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/types.ts create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/layout.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/SettingPage.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/SettingSideBar.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/TextProvider.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/loading.tsx rename electron/servers/nextjs/app/(presentation-generator)/{ => (dashboard)}/settings/page.tsx (100%) create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/templates/components/CreateCustomTemplate.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/templates/components/TemplatePanel.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/templates/loading.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/templates/page.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/ColorPickerComponent.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/CustomTabEmpty.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/FontCard.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/StepIndicator.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/ThemeCard.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/constants.ts create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/index.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/types.ts create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/components/ThemePanel/utils.ts create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/loading.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/(dashboard)/theme/page.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/hooks/useFontLoad.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/presentation/components/NewSlide.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationHeader.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/presentation/components/PresentationMode.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/presentation/components/ThemeSelector.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/services/api/theme.ts create mode 100644 electron/servers/nextjs/app/(presentation-generator)/upload/components/AdvanceSettings.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/upload/components/LanguageSelector.tsx create mode 100644 electron/servers/nextjs/app/(presentation-generator)/upload/components/NumberOfSlide.tsx create mode 100644 electron/servers/nextjs/components/ImageSelectionConfig.tsx create mode 100644 electron/servers/nextjs/components/MarkDownRender.tsx create mode 100644 electron/servers/nextjs/components/OnBoarding/FinalStep.tsx create mode 100644 electron/servers/nextjs/components/OnBoarding/GenerationWithImage.tsx create mode 100644 electron/servers/nextjs/components/OnBoarding/ModeSelectStep.tsx create mode 100644 electron/servers/nextjs/components/OnBoarding/OnBoardingHeader.tsx create mode 100644 electron/servers/nextjs/components/OnBoarding/OnBoardingSlidebar.tsx create mode 100644 electron/servers/nextjs/components/OnBoarding/PresentonMode.tsx create mode 100644 electron/servers/nextjs/public/card_bg.svg create mode 100644 electron/servers/nextjs/public/create_presentation.png create mode 100644 electron/servers/nextjs/public/final_onboarding.png create mode 100644 electron/servers/nextjs/public/image-markup.svg create mode 100644 electron/servers/nextjs/public/image_mode.png create mode 100644 electron/servers/nextjs/public/logo-with-bg.png create mode 100644 electron/servers/nextjs/public/providers/image-provider.png create mode 100644 electron/servers/nextjs/public/providers/openai.png diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardNav.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardNav.tsx new file mode 100644 index 00000000..6185cd7f --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardNav.tsx @@ -0,0 +1,64 @@ +"use client"; + +import { ChevronRight } from 'lucide-react'; +import Link from 'next/link'; +import React, { } from 'react' +import { defaultNavItems } from './DashboardSidebar'; +import { usePathname } from 'next/navigation'; + +const DashboardNav = () => { + const pathname = usePathname(); + const activeTab = pathname.split("?")[0].split("/").pop(); + const activeItem = defaultNavItems.find((i: any) => i.key === activeTab); + + + + + + return ( +
+
+

+ + {activeItem?.label ?? (activeTab && activeTab?.charAt(0).toUpperCase() + activeTab?.slice(1))} +

+
+ + + + {activeTab !== "playground" && activeTab !== "theme" && + + New presentation + New + + } + {activeTab === "theme" && + + New Themes + New + + + } +
+
+
+ ) +} + +export default DashboardNav diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardSidebar.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardSidebar.tsx new file mode 100644 index 00000000..7974bc1f --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/Components/DashboardSidebar.tsx @@ -0,0 +1,128 @@ +"use client"; + +import React from "react"; +import { LayoutDashboard, Star, Brain, Settings, Palette } from "lucide-react"; +import { usePathname } from "next/navigation"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; + + + +export const defaultNavItems = [ + { key: "dashboard" as const, label: "Dashboard", icon: LayoutDashboard }, + { key: "templates" as const, label: "Standard", icon: Star }, + { key: "designs" as const, label: "Smart", icon: Brain }, + + + +]; +export const BelongingNavItems = [ + { key: "settings" as const, label: "Settings", icon: Settings }, +] + +const DashboardSidebar = () => { + + + const pathname = usePathname(); + const activeTab = pathname.split("?")[0].split("/").pop(); + const router = useRouter(); + + + + + return ( + + ); +}; + +export default DashboardSidebar; + + diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/DashboardPage.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/DashboardPage.tsx new file mode 100644 index 00000000..3026da00 --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/DashboardPage.tsx @@ -0,0 +1,111 @@ +"use client"; + +import React, { useState, useEffect } from "react"; + +import { DashboardApi } from "@/app/(presentation-generator)/services/api/dashboard"; +import { PresentationGrid } from "@/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationGrid"; +import Link from "next/link"; +import { ChevronRight } from "lucide-react"; + + + +const DashboardPage: React.FC = () => { + const [presentations, setPresentations] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const loadData = async () => { + await fetchPresentations(); + }; + loadData(); + }, []); + + const fetchPresentations = async () => { + try { + setIsLoading(true); + setError(null); + const data = await DashboardApi.getPresentations(); + data.sort( + (a: any, b: any) => + new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime() + ); + setPresentations(data); + } catch (err) { + setError(null); + setPresentations([]); + } finally { + setIsLoading(false); + } + }; + + const removePresentation = (presentationId: string) => { + setPresentations((prev: any) => + prev ? prev.filter((p: any) => p.id !== presentationId) : [] + ); + }; + + return ( +
+
+
+

+ + Slide Presentations +

+
+ + + + + + New presentation + New + + + {/* { + + New Themes + New + + + } */} +
+
+
+ +
+
+ ); +}; + +export default DashboardPage; diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/EmptyState.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/EmptyState.tsx new file mode 100644 index 00000000..322a30ed --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/EmptyState.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +export const EmptyState = () => { + return ( +
+
+ + + + + + +
+

+ You don't have any presentations yet. +

+

+ Start creating the first one. +

+
+ ); +}; \ No newline at end of file diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/Header.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/Header.tsx new file mode 100644 index 00000000..7177698b --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/Header.tsx @@ -0,0 +1,31 @@ +"use client"; + +import Wrapper from "@/components/Wrapper"; +import React from "react"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { trackEvent, MixpanelEvent } from "@/utils/mixpanel"; +const Header = () => { + const pathname = usePathname(); + return ( +
+ +
+
+ {/* {(pathname !== "/upload" && pathname !== "/dashboard") && } */} + trackEvent(MixpanelEvent.Navigation, { from: pathname, to: "/dashboard" })}> + Presentation logo + +
+ +
+
+
+ ); +}; + +export default Header; diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationCard.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationCard.tsx new file mode 100644 index 00000000..24e1d9d1 --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationCard.tsx @@ -0,0 +1,105 @@ +'use client' +import React from "react"; + +import { Card } from "@/components/ui/card"; +import { DashboardApi } from "@/app/(presentation-generator)/services/api/dashboard"; +import { EllipsisVertical, Star, Trash } from "lucide-react"; +import { + Popover, + PopoverTrigger, + PopoverContent, +} from "@/components/ui/popover"; +import { useRouter } from "next/navigation"; +import { toast } from "sonner"; + +import { useFontLoader } from "@/app/(presentation-generator)/hooks/useFontLoader"; +import SlideScale from "@/app/(presentation-generator)/components/PresentationRender"; +import MarkdownRenderer from "@/components/MarkDownRender"; + +export const PresentationCard = ({ + id, + title, + presentation, + onDeleted +}: { + id: string; + title: string; + presentation: any; + onDeleted?: (presentationId: string) => void; +}) => { + const router = useRouter(); + useFontLoader(presentation.fonts || []); + const handlePreview = (e: React.MouseEvent) => { + e.preventDefault(); + router.push(`/presentation?id=${id}&type=standard`); + }; + + const handleDelete = async (e: React.MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + + + const response = await DashboardApi.deletePresentation(id); + + if (response) { + toast.success("Presentation deleted", { + description: "The presentation has been deleted successfully", + }); + if (onDeleted) { + onDeleted(id); + } + } else { + toast.error("Error deleting presentation"); + } + }; + const firstSlide = presentation?.slides?.[0]; + return ( + +
+ {/*

+ + {presentation.type} +

*/} + + +
+ + +
+ +
+
+
+
+ +
+

+ {new Date(presentation?.created_at).toLocaleDateString()} +

+ +
+ + e.stopPropagation()}> + + + + + + +
+ +
+
+
+ ); +}; diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationGrid.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationGrid.tsx new file mode 100644 index 00000000..0edad0fb --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationGrid.tsx @@ -0,0 +1,124 @@ +import React from "react"; +import { PresentationCard } from "./PresentationCard"; +import { PlusIcon } from "@radix-ui/react-icons"; +import { useRouter } from "next/navigation"; +import { PresentationResponse } from "@/app/(presentation-generator)/services/api/dashboard"; +import { ArrowRight } from "lucide-react"; + +interface PresentationGridProps { + presentations: PresentationResponse[]; + type: "slide" | "video"; + isLoading?: boolean; + error?: string | null; + onPresentationDeleted?: (presentationId: string) => void; +} + +export const PresentationGrid = ({ + presentations, + type, + isLoading = false, + error = null, + onPresentationDeleted, +}: PresentationGridProps) => { + const router = useRouter(); + const handleCreateNewPresentation = () => { + if (type === "slide") { + router.push("/upload"); + } else { + router.push("/editor"); + } + }; + + const ShimmerCard = () => ( +
+
+
+
+
+
+
+ ); + + const CreateNewCard = () => ( +
+ New Presentation +
+ + + + + + + + + + + + + +
+

Create New Presentation

+

Get Started

+
+
+
+ ); + + if (isLoading) { + return ( +
+
+
+
+
+
+
+
+
+
+ {[...Array(15)].map((_, i) => ( + + ))} +
+ ); + } + + if (error) { + return ( +
+ +
+
+

{error}

+ +
+
+
+ ); + } + + return ( +
+ + {presentations && + presentations.length > 0 && + presentations.map((presentation) => ( + + ))} +
+ ); +}; diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationListItem.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationListItem.tsx new file mode 100644 index 00000000..54958ce0 --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/components/PresentationListItem.tsx @@ -0,0 +1,44 @@ +import React from 'react'; + +import { Card, CardContent } from "@/components/ui/card"; +import { Presentation } from '../types'; + +export const PresentationListItem: React.FC = ({ + title, + date, + thumbnail, + type +}) => { + return ( + + +
+ {title} +
+ +
+

{title}

+
+ {/* {formatDistanceToNow(new Date(date), { addSuffix: true })} */} +
+
+ +
+ {type === 'video' ? ( + + + + ) : ( + + + + )} +
+
+
+ ); +}; \ No newline at end of file diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/loading.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/loading.tsx new file mode 100644 index 00000000..919a55ad --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/loading.tsx @@ -0,0 +1,28 @@ +import React from 'react' + +const loading = () => { + return ( +
+
+
+
+
+
+
+
+
+
+ {[...Array(15)].map((_, i) => ( +
+
+
+
+
+
+
+ ))} +
+ ) +} + +export default loading diff --git a/electron/servers/nextjs/app/(presentation-generator)/dashboard/page.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/page.tsx similarity index 100% rename from electron/servers/nextjs/app/(presentation-generator)/dashboard/page.tsx rename to electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/page.tsx diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/types.ts b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/types.ts new file mode 100644 index 00000000..d4b1ce8f --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/dashboard/types.ts @@ -0,0 +1,16 @@ +export interface Presentation { + id: string; + title: string; + date: string; + thumbnail: string; + type: 'video' | 'slide'; +} + +export interface PresentationFilter { + type?: 'video' | 'slide'; + search?: string; + dateRange?: { + start: Date; + end: Date; + }; +} \ No newline at end of file diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/layout.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/layout.tsx new file mode 100644 index 00000000..a1b9172e --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/layout.tsx @@ -0,0 +1,16 @@ +import React from 'react' +import DashboardSidebar from './Components/DashboardSidebar' + +const layout = ({ children }: { children: React.ReactNode }) => { + return ( +
+ +
+ + {children} +
+
+ ) +} + +export default layout \ No newline at end of file diff --git a/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx new file mode 100644 index 00000000..31bc11ea --- /dev/null +++ b/electron/servers/nextjs/app/(presentation-generator)/(dashboard)/settings/ImageProvider.tsx @@ -0,0 +1,355 @@ +import ToolTip from '@/components/ToolTip' +import { Button } from '@/components/ui/button' +import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command' +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' +import { Select, SelectItem, SelectContent, SelectTrigger, SelectValue } from '@/components/ui/select' +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, 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) => ({ + ...prev, + DISABLE_IMAGE_GENERATION: value + })); + } + const input_field_changed = (value: string, field: string) => { + setLlmConfig((prev: any) => ({ + ...prev, + [field]: value + })); + setOpenImageProviderSelect(false); + } + + const getFieldValue = (field?: string) => { + if (!field) return ""; + return (llmConfig as Record)[field] || ""; + }; + + const updateFieldValue = (field: string | undefined, value: string) => { + if (!field) return; + setLlmConfig((prev: any) => ({ + ...prev, + [field]: value, + })); + }; + + const getTextProviderApiField = () => { + if (llmConfig.LLM === "openai") return "OPENAI_API_KEY"; + if (llmConfig.LLM === "google") return "GOOGLE_API_KEY"; + if (llmConfig.LLM === "anthropic") return "ANTHROPIC_API_KEY"; + return ""; + }; + + + + + + const renderQualitySelector = (llmConfig: LLMConfig, input_field_changed: (value: string, field: string) => void) => { + if (llmConfig.IMAGE_PROVIDER === "dall-e-3") { + return ( +
+ +
+ + +
+
+ ); + } + + if (llmConfig.IMAGE_PROVIDER === "gpt-image-1.5") { + return ( +
+ +
+ + +
+
+ ); + } + + return null; + }; + + + + + return ( +
+ {/* API Key Input */} +
+ +
+ handleChangeImageGenerationDisabled(!checked)} + /> +
+ +
+
+ + +
+
+ image-markup +
+

Image Generation Settings

+

+ Choosing where images come from +

+
+
+ +
+ + {!isImageGenerationDisabled && ( + <> + {/* Image Provider Selection */} +
+ +
+ + + + + + + + + No provider found. + + {Object.values(IMAGE_PROVIDERS).map( + (provider, index) => ( + { + input_field_changed(value, "IMAGE_PROVIDER"); + setOpenImageProviderSelect(false); + }} + > + +
+
+
+ + {provider.label} + +
+ + {provider.description} + +
+
+
+ ) + )} +
+
+
+
+
+
+
+ + + + {/* Dynamic API Key Input for Image Provider */} + {llmConfig.IMAGE_PROVIDER && + IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER] && + (() => { + const provider = IMAGE_PROVIDERS[llmConfig.IMAGE_PROVIDER]; + + + + // Show ComfyUI configuration + if (provider.value === "comfyui") { + return ( +
+
+ +
+ { + input_field_changed( + e.target.value, + "COMFYUI_URL" + ); + }} + /> +
+ +
+ +
+ ); + } + + // Show API key input for other providers + return ( +
+ +
+ + updateFieldValue( + provider.apiKeyField, + e.target.value + ) + } + /> + +
+ +
+ ); + })()} + + + )} +
+ {!isImageGenerationDisabled &&
+ + {renderQualitySelector(llmConfig, input_field_changed)} + {llmConfig.IMAGE_PROVIDER === "comfyui" &&
+ +
+