Skip to content
This repository was archived by the owner on Jun 23, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
- ./user_data:/app/user_data
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion servers/fastapi/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
2 changes: 1 addition & 1 deletion servers/fastapi/server_autoreload.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
2 changes: 1 addition & 1 deletion servers/fastapi/server_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ const ImageEditor = ({
<img
src={
image
? `file://${image}`
? getStaticFileUrl(image)
: ""
}
alt={`Preview ${index + 1}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Camera, Loader2, Plus } from "lucide-react";
import { toast } from "@/hooks/use-toast";
import { useSelector } from "react-redux";
import { RootState } from "@/store/store";
import { isDarkColor } from "../../utils/others";
import { getStaticFileUrl, isDarkColor } from "../../utils/others";
import { defaultFooterProperties, useFooterContext } from "../../context/footerContext";
import { FooterProperties } from "../../services/footerService";

Expand Down Expand Up @@ -219,7 +219,7 @@ const SlideFooter: React.FC = () => {
const getLocalImageUrl = (filePath: string) => {
if (!filePath) return "";
if (filePath.startsWith('data:image')) return filePath;
return `file://${filePath}`;
return getStaticFileUrl(filePath);
};

const handleEditor = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down
4 changes: 2 additions & 2 deletions servers/nextjs/app/api/upload-image/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion servers/nextjs/app/dashboard/components/PresentationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -85,7 +86,7 @@ export const PresentationCard = ({
<div className="relative border-2 border-gray-200 aspect-[16/9] rounded-[8px] overflow-hidden">
{thumbnail ? (
<img
src={`file://${thumbnail}`}
src={getStaticFileUrl(thumbnail)}
alt={title}
className="object-cover h-full w-full"
/>
Expand Down
3 changes: 1 addition & 2 deletions servers/nextjs/components/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default function Home() {
const router = useRouter();
const [isLoading, setIsLoading] = useState(true);
const [config, setConfig] = useState<ConfigState>({
provider: "",
provider: "openai",
apiKey: "",
textModel: PROVIDER_CONFIGS.openai.textModels[0].value,
imageModel: PROVIDER_CONFIGS.openai.imageModels[0].value,
Expand All @@ -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
Expand Down
14 changes: 9 additions & 5 deletions start.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 () => {

Expand Down