From 89c6f25bf1f8728cd714930f3b2f218bc5ae3a1b Mon Sep 17 00:00:00 2001 From: sauravniraula Date: Mon, 19 May 2025 01:07:06 +0545 Subject: [PATCH] fix(nextjs):provider selection error, fix(nextjs):pdf export redirect issue, feat(docker):docker compose working --- Dockerfile | 25 ++++++++++++++---- docker-compose.yml | 5 +--- .../Fraunces/Fraunces-Regular.otf | Bin .../Inria Serif/InriaSerif-Regular.ttf | Bin .../Montserrat/Montserrat-Regular.ttf | Bin .../Satoshi/Satoshi-Regular.otf | Bin .../fastapi/fonts => fonts}/inter/Inter.otf | Bin .../mixins/fetch_presentation_assets.py | 25 +++++++++++------- servers/fastapi/server.py | 2 +- servers/fastapi/server_autoreload.py | 2 +- servers/fastapi/server_test.py | 2 +- .../components/ImageEditor.tsx | 2 +- .../components/slide_layouts/SlideFooter.tsx | 4 +-- .../presentation/components/Header.tsx | 2 +- .../(presentation-generator)/utils/others.ts | 2 +- .../{[filepath] => [...filepath]}/route.ts | 6 +++-- servers/nextjs/app/api/upload-image/route.ts | 4 +-- .../dashboard/components/PresentationCard.tsx | 3 ++- servers/nextjs/components/Home.tsx | 3 +-- start.js | 14 ++++++---- 20 files changed, 63 insertions(+), 38 deletions(-) rename {servers/fastapi/fonts => fonts}/Fraunces/Fraunces-Regular.otf (100%) rename {servers/fastapi/fonts => fonts}/Inria Serif/InriaSerif-Regular.ttf (100%) rename {servers/fastapi/fonts => fonts}/Montserrat/Montserrat-Regular.ttf (100%) rename {servers/fastapi/fonts => fonts}/Satoshi/Satoshi-Regular.otf (100%) rename {servers/fastapi/fonts => fonts}/inter/Inter.otf (100%) rename servers/nextjs/app/api/static/{[filepath] => [...filepath]}/route.ts (89%) diff --git a/Dockerfile b/Dockerfile index 60c8cbf..d9ee83a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,20 +5,35 @@ RUN apt-get update && apt-get install -y \ nodejs \ npm -# Copy the start script and the servers directory +# Create a working directory WORKDIR /app -COPY start.js LICENSE NOTICE ./ -COPY servers ./servers # Install dependencies for FastAPI -WORKDIR /app/servers/fastapi +COPY servers/fastapi/requirements.txt ./ RUN pip install -r requirements.txt + # Install dependencies for Next.js WORKDIR /app/servers/nextjs -RUN npm install && npm run build +COPY servers/nextjs/package.json servers/nextjs/package-lock.json ./ +RUN npm install + +# Install chrome for puppeteer +RUN npx puppeteer browsers install chrome --install-deps + +WORKDIR /app + +# Copy the start script and the servers directory +COPY start.js LICENSE NOTICE ./ +COPY servers ./servers + +# Build the Next.js app +WORKDIR /app/servers/nextjs +RUN npm run build WORKDIR /app +ENV APP_DATA_DIRECTORY=/app/user_data +ENV TEMP_DIRECTORY=/tmp/presenton # Expose the ports for Next.js and FastAPI EXPOSE 3000 8000 diff --git a/docker-compose.yml b/docker-compose.yml index 4bfa310..888ac5e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,4 @@ services: - "3000:3000" - "8000:8000" volumes: - - ./user_data:/app/user_data - environment: - - TEMP_DIRECTORY=/tmp/presenton - - APP_DATA_DIRECTORY=/app/user_data \ No newline at end of file + - ./user_data:/app/user_data \ No newline at end of file diff --git a/servers/fastapi/fonts/Fraunces/Fraunces-Regular.otf b/fonts/Fraunces/Fraunces-Regular.otf similarity index 100% rename from servers/fastapi/fonts/Fraunces/Fraunces-Regular.otf rename to fonts/Fraunces/Fraunces-Regular.otf diff --git a/servers/fastapi/fonts/Inria Serif/InriaSerif-Regular.ttf b/fonts/Inria Serif/InriaSerif-Regular.ttf similarity index 100% rename from servers/fastapi/fonts/Inria Serif/InriaSerif-Regular.ttf rename to fonts/Inria Serif/InriaSerif-Regular.ttf diff --git a/servers/fastapi/fonts/Montserrat/Montserrat-Regular.ttf b/fonts/Montserrat/Montserrat-Regular.ttf similarity index 100% rename from servers/fastapi/fonts/Montserrat/Montserrat-Regular.ttf rename to fonts/Montserrat/Montserrat-Regular.ttf diff --git a/servers/fastapi/fonts/Satoshi/Satoshi-Regular.otf b/fonts/Satoshi/Satoshi-Regular.otf similarity index 100% rename from servers/fastapi/fonts/Satoshi/Satoshi-Regular.otf rename to fonts/Satoshi/Satoshi-Regular.otf diff --git a/servers/fastapi/fonts/inter/Inter.otf b/fonts/inter/Inter.otf similarity index 100% rename from servers/fastapi/fonts/inter/Inter.otf rename to fonts/inter/Inter.otf diff --git a/servers/fastapi/api/routers/presentation/mixins/fetch_presentation_assets.py b/servers/fastapi/api/routers/presentation/mixins/fetch_presentation_assets.py index 671462c..a368bdd 100644 --- a/servers/fastapi/api/routers/presentation/mixins/fetch_presentation_assets.py +++ b/servers/fastapi/api/routers/presentation/mixins/fetch_presentation_assets.py @@ -16,18 +16,25 @@ async def fetch_presentation_assets(self): if isinstance(each_shape, PptxPictureBoxModel): image_path = each_shape.picture.path if image_path.startswith("http"): - image_urls.append(image_path) - parsed_url = unquote(urlparse(image_path).path) - image_name = replace_file_name( - os.path.basename(parsed_url), str(uuid.uuid4()) - ) - image_path = os.path.join(self.temp_dir, image_name) - image_local_paths.append(image_path) + if image_path.startswith("http://localhost:3000/static"): + image_path = image_path.replace( + "http://localhost:3000/static", "" + ) + image_path = "/app" + image_path + print(image_path) + else: + image_urls.append(image_path) + parsed_url = unquote(urlparse(image_path).path) + image_name = replace_file_name( + os.path.basename(parsed_url), str(uuid.uuid4()) + ) + image_path = os.path.join(self.temp_dir, image_name) + image_local_paths.append(image_path) elif image_path.startswith("file://"): image_path = image_path.replace("file:///", "") # Check if it's a Windows path (has colon at index 1) - if not (len(image_path) > 1 and image_path[1] == ':'): - image_path = '/' + image_path + if not (len(image_path) > 1 and image_path[1] == ":"): + image_path = "/" + image_path each_shape.picture.path = image_path each_shape.picture.is_network = False diff --git a/servers/fastapi/server.py b/servers/fastapi/server.py index 3935ca6..40db9df 100644 --- a/servers/fastapi/server.py +++ b/servers/fastapi/server.py @@ -14,4 +14,4 @@ ) args = parser.parse_args() - uvicorn.run("api.main:app", host="127.0.0.1", port=args.port, log_level="info") + uvicorn.run("api.main:app", host="0.0.0.0", port=args.port, log_level="info") diff --git a/servers/fastapi/server_autoreload.py b/servers/fastapi/server_autoreload.py index b0c4e49..4d5c00d 100644 --- a/servers/fastapi/server_autoreload.py +++ b/servers/fastapi/server_autoreload.py @@ -10,5 +10,5 @@ args = parser.parse_args() uvicorn.run( - "api.main:app", host="127.0.0.1", port=args.port, log_level="info", reload=True + "api.main:app", host="0.0.0.0", port=args.port, log_level="info", reload=True ) diff --git a/servers/fastapi/server_test.py b/servers/fastapi/server_test.py index f244605..4b547a5 100644 --- a/servers/fastapi/server_test.py +++ b/servers/fastapi/server_test.py @@ -5,5 +5,5 @@ if __name__ == "__main__": uvicorn.run( - "api.main:app", host="127.0.0.1", port=8000, log_level="info", reload=True + "api.main:app", host="0.0.0.0", port=8000, log_level="info", reload=True ) diff --git a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx index c078448..de66031 100644 --- a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx @@ -555,7 +555,7 @@ const ImageEditor = ({ {`Preview { const getLocalImageUrl = (filePath: string) => { if (!filePath) return ""; if (filePath.startsWith('data:image')) return filePath; - return `file://${filePath}`; + return getStaticFileUrl(filePath); }; const handleEditor = () => { diff --git a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx index a45baec..107a949 100644 --- a/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx +++ b/servers/nextjs/app/(presentation-generator)/presentation/components/Header.tsx @@ -230,7 +230,7 @@ const Header = ({ if (response.ok) { const { path: pdfPath } = await response.json(); const staticFileUrl = getStaticFileUrl(pdfPath); - window.open(staticFileUrl, '_blank'); + window.open(staticFileUrl, '_self'); } else { throw new Error("Failed to export PDF"); } diff --git a/servers/nextjs/app/(presentation-generator)/utils/others.ts b/servers/nextjs/app/(presentation-generator)/utils/others.ts index e1dea8b..591296d 100644 --- a/servers/nextjs/app/(presentation-generator)/utils/others.ts +++ b/servers/nextjs/app/(presentation-generator)/utils/others.ts @@ -224,6 +224,6 @@ export function sanitizeFilename(filename: string): string { export function getStaticFileUrl(filepath: string): string { const pathParts = filepath.split('/'); - const relevantPath = pathParts.slice(1).join('/'); + const relevantPath = pathParts.slice(2).join('/'); return path.join("/static", relevantPath); } \ No newline at end of file diff --git a/servers/nextjs/app/api/static/[filepath]/route.ts b/servers/nextjs/app/api/static/[...filepath]/route.ts similarity index 89% rename from servers/nextjs/app/api/static/[filepath]/route.ts rename to servers/nextjs/app/api/static/[...filepath]/route.ts index fdd62bd..782d165 100644 --- a/servers/nextjs/app/api/static/[filepath]/route.ts +++ b/servers/nextjs/app/api/static/[...filepath]/route.ts @@ -5,15 +5,17 @@ import { NextRequest, NextResponse } from 'next/server'; export async function GET( request: NextRequest, - { params }: { params: { filepath: string } }, + { params }: { params: { filepath: string[] } }, ) { const BASE_DIR = "/app"; + const filepath = params.filepath.join("/"); + if (!params.filepath) { return new NextResponse('No file specified', { status: 400 }); } - const filePath = path.join(BASE_DIR, params.filepath); + const filePath = path.join(BASE_DIR, filepath); if (!fs.existsSync(filePath)) { return new NextResponse('File not found', { status: 404 }); diff --git a/servers/nextjs/app/api/upload-image/route.ts b/servers/nextjs/app/api/upload-image/route.ts index b7d7664..8f8aa7a 100644 --- a/servers/nextjs/app/api/upload-image/route.ts +++ b/servers/nextjs/app/api/upload-image/route.ts @@ -4,7 +4,7 @@ import fs from "fs"; import crypto from "crypto"; -const userDataDir = process.env.APP_DATA_DIRECTORY || '/tmp/presenton-docker/'; +const userDataDir = process.env.APP_DATA_DIRECTORY!; export async function POST(request: NextRequest) { try { @@ -35,7 +35,7 @@ export async function POST(request: NextRequest) { // Return the relative path that can be used in the frontend return NextResponse.json({ success: true, - filePath: `/uploads/${filename}` + filePath: `/app/user_data/uploads/${filename}` }); } catch (error) { console.error("Error saving image:", error); diff --git a/servers/nextjs/app/dashboard/components/PresentationCard.tsx b/servers/nextjs/app/dashboard/components/PresentationCard.tsx index 467442a..bb4c73a 100644 --- a/servers/nextjs/app/dashboard/components/PresentationCard.tsx +++ b/servers/nextjs/app/dashboard/components/PresentationCard.tsx @@ -11,6 +11,7 @@ import { 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"; export const PresentationCard = ({ id, @@ -85,7 +86,7 @@ export const PresentationCard = ({
{thumbnail ? ( {title} diff --git a/servers/nextjs/components/Home.tsx b/servers/nextjs/components/Home.tsx index 0e5a24e..cae9d72 100644 --- a/servers/nextjs/components/Home.tsx +++ b/servers/nextjs/components/Home.tsx @@ -98,7 +98,7 @@ export default function Home() { const router = useRouter(); const [isLoading, setIsLoading] = useState(true); const [config, setConfig] = useState({ - provider: "", + provider: "openai", apiKey: "", textModel: PROVIDER_CONFIGS.openai.textModels[0].value, imageModel: PROVIDER_CONFIGS.openai.imageModels[0].value, @@ -107,7 +107,6 @@ export default function Home() { useEffect(() => { const checkExistingConfig = async () => { try { - // @ts-ignore const savedConfig: UserConfig = await fetch('/api/user-config').then(res => res.json()) // If either API key exists, redirect to upload diff --git a/start.js b/start.js index a8751dd..0d57375 100644 --- a/start.js +++ b/start.js @@ -7,7 +7,7 @@ const fs = require('fs'); const fastapiDir = path.join(__dirname, 'servers/fastapi'); const nextjsDir = path.join(__dirname, 'servers/nextjs'); -const localhost = '127.0.0.1'; +const localhost = '0.0.0.0'; const fastapiPort = 8000; const nextjsPort = 3000; @@ -16,13 +16,17 @@ process.env.NEXT_PUBLIC_FAST_API = `http://${localhost}:${fastapiPort}`; const setupUserConfigFromEnv = () => { const userConfigPath = process.env.USER_CONFIG_PATH; + let existingConfig = {}; + if (fs.existsSync(userConfigPath)) { + existingConfig = JSON.parse(fs.readFileSync(userConfigPath, 'utf8')); + } const userConfig = { - LLM: process.env.LLM, - OPENAI_API_KEY: process.env.OPENAI_API_KEY, - GOOGLE_API_KEY: process.env.GOOGLE_API_KEY, + LLM: process.env.LLM || existingConfig.LLM, + OPENAI_API_KEY: process.env.OPENAI_API_KEY || existingConfig.OPENAI_API_KEY, + GOOGLE_API_KEY: process.env.GOOGLE_API_KEY || existingConfig.GOOGLE_API_KEY, }; fs.writeFileSync(userConfigPath, JSON.stringify(userConfig)); -}; +} const startServers = async () => {