diff --git a/project/backend/coordinator/Dockerfile b/project/backend/coordinator/Dockerfile new file mode 100644 index 0000000..1a8fe43 --- /dev/null +++ b/project/backend/coordinator/Dockerfile @@ -0,0 +1,21 @@ +# 1. Python-Image verwenden +FROM python:3.11-alpine + +# 2. Arbeitsverzeichnis im Container setzen +WORKDIR /app + +# 3. production-style server mit gunicorn +RUN pip install gunicorn eventlet + +# 4. requirements.txt kopieren und Pakete installieren +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + + +# 5. Quellcode kopieren (z.B. app.py) +COPY . . + +ENV PYTHONUNBUFFERED=1 +EXPOSE 5000 + +CMD ["gunicorn", "--worker-class", "eventlet", "-w", "1", "--bind", "0.0.0.0:5000", "app:app"] diff --git a/project/backend/coordinator/controller/__init__.py b/project/backend/coordinator/controller/__init__.py index 256d5f2..5b758cb 100644 --- a/project/backend/coordinator/controller/__init__.py +++ b/project/backend/coordinator/controller/__init__.py @@ -1,9 +1,11 @@ from controller.spacy_contoller import spacy_controller from controller.kpi_setting_controller import kpi_setting_controller from controller.pitch_book_controller import pitch_book_controller +from controller.progress_controller import progress_controller def register_routes(app): app.register_blueprint(kpi_setting_controller) app.register_blueprint(pitch_book_controller) app.register_blueprint(spacy_controller) + app.register_blueprint(progress_controller) diff --git a/project/backend/coordinator/controller/progress_controller.py b/project/backend/coordinator/controller/progress_controller.py new file mode 100644 index 0000000..90db4df --- /dev/null +++ b/project/backend/coordinator/controller/progress_controller.py @@ -0,0 +1,19 @@ +from flask import Blueprint, request, jsonify + +from controller.socketIO import socketio +progress_controller = Blueprint("progress", __name__, url_prefix="/api/progress") + + +@progress_controller.route("/", methods=["POST"]) +def progress(): + data = request.get_json() + + if 'id' not in data or 'progress' not in data: + return jsonify({"error": "Missing required fields. [id, progress]"}), 400 + + if not isinstance(data['progress'], (int, float)) or data['progress'] < 0 or data['progress'] >= 100: + return jsonify({"error": "Invalid progress value"}), 400 + + socketio.emit("progress", {"id": data["id"], "progress": data["progress"]}) + # Process the data and return a response + return jsonify({"message": "Progress updated"}) diff --git a/project/frontend/biome.json b/project/frontend/biome.json index 55240aa..2e91202 100644 --- a/project/frontend/biome.json +++ b/project/frontend/biome.json @@ -12,7 +12,7 @@ }, "formatter": { "enabled": true, - "indentStyle": "space" + "indentStyle": "tab" }, "organizeImports": { "enabled": true diff --git a/project/frontend/bun.lockb b/project/frontend/bun.lockb index 676011c..d5b3409 100755 Binary files a/project/frontend/bun.lockb and b/project/frontend/bun.lockb differ diff --git a/project/frontend/src/components/UploadPage.tsx b/project/frontend/src/components/UploadPage.tsx index c4a57d0..4373676 100644 --- a/project/frontend/src/components/UploadPage.tsx +++ b/project/frontend/src/components/UploadPage.tsx @@ -4,175 +4,175 @@ import { useNavigate } from "@tanstack/react-router"; import { useCallback, useEffect, useState } from "react"; import FileUpload from "react-material-file-upload"; import { socket } from "../socket"; -import { CircularProgressWithLabel } from "./circularProgressWithLabel"; +import { CircularProgressWithLabel } from "./CircularProgressWithLabel"; const PROGRESS = false; export default function UploadPage() { - const [files, setFiles] = useState([]); - const [pageId, setPageId] = useState(null); - const [loadingState, setLoadingState] = useState(null); - const fileTypes = ["pdf"]; - const navigate = useNavigate(); + const [files, setFiles] = useState([]); + const [pageId, setPageId] = useState(null); + const [loadingState, setLoadingState] = useState(null); + const fileTypes = ["pdf"]; + const navigate = useNavigate(); - const uploadFile = useCallback(async () => { - const formData = new FormData(); - formData.append("file", files[0]); - const response = await fetch("http://localhost:5050/api/pitch_book", { - method: "POST", - body: formData, - }); + const uploadFile = useCallback(async () => { + const formData = new FormData(); + formData.append("file", files[0]); + const response = await fetch("http://localhost:5050/api/pitch_book", { + method: "POST", + body: formData, + }); - if (response.ok) { - console.log("File uploaded successfully"); - const data = await response.json(); - console.log(data); - setPageId(data.id); - setLoadingState(0); + if (response.ok) { + console.log("File uploaded successfully"); + const data = await response.json(); + console.log(data); + setPageId(data.id); + setLoadingState(0); - !PROGRESS && - navigate({ - to: "/extractedResult/$pitchBook", - params: { pitchBook: data.id }, - }); - } else { - console.error("Failed to upload file"); - } - }, [files, navigate]); + !PROGRESS && + navigate({ + to: "/extractedResult/$pitchBook", + params: { pitchBook: data.id }, + }); + } else { + console.error("Failed to upload file"); + } + }, [files, navigate]); - const onConnection = useCallback(() => { - console.log("connected"); - }, []); + const onConnection = useCallback(() => { + console.log("connected"); + }, []); - const onProgress = useCallback( - (progress: { id: number; progress: number }) => { - console.log("Progress:", progress); - console.log(pageId); - if (Number(pageId) === progress.id) { - setLoadingState(progress.progress); + const onProgress = useCallback( + (progress: { id: number; progress: number }) => { + console.log("Progress:", progress); + console.log(pageId); + if (Number(pageId) === progress.id) { + setLoadingState(progress.progress); - if (progress.progress === 100) { - navigate({ - to: "/extractedResult/$pitchBook", - params: { pitchBook: progress.id.toString() }, - }); - } - } - }, - [pageId, navigate], - ); + if (progress.progress === 100) { + navigate({ + to: "/extractedResult/$pitchBook", + params: { pitchBook: progress.id.toString() }, + }); + } + } + }, + [pageId, navigate], + ); - useEffect(() => { - socket.on("connect", onConnection); - socket.on("progress", onProgress); - return () => { - socket.off("connect", onConnection); - socket.off("progress", onProgress); - }; - }, [onConnection, onProgress]); + useEffect(() => { + socket.on("connect", onConnection); + socket.on("progress", onProgress); + return () => { + socket.off("connect", onConnection); + socket.off("progress", onProgress); + }; + }, [onConnection, onProgress]); - return ( - <> - {PROGRESS && ( - ({ color: "#fff", zIndex: theme.zIndex.drawer + 1 })} - open={pageId !== null && loadingState !== null} - > - - - )} - - - navigate({ to: "/config" })}> - - - - - - - - - - - - ); + return ( + <> + {PROGRESS && ( + ({ color: "#fff", zIndex: theme.zIndex.drawer + 1 })} + open={pageId !== null && loadingState !== null} + > + + + )} + + + navigate({ to: "/config" })}> + + + + + + + + + + + + ); } diff --git a/project/frontend/src/components/pdfViewer.tsx b/project/frontend/src/components/pdfViewer.tsx index 3c25e13..87e1edc 100644 --- a/project/frontend/src/components/pdfViewer.tsx +++ b/project/frontend/src/components/pdfViewer.tsx @@ -7,88 +7,87 @@ import ArrowCircleRightIcon from "@mui/icons-material/ArrowCircleRight"; import { Box, IconButton } from "@mui/material"; interface PDFViewerProps { - pitchBookId: string; + pitchBookId: string; } - export default function PDFViewer({ pitchBookId }: PDFViewerProps) { - const [numPages, setNumPages] = useState(null); - const [pageNumber, setPageNumber] = useState(1); - const [containerWidth, setContainerWidth] = useState(null); - const containerRef = useRef(null); + const [numPages, setNumPages] = useState(null); + const [pageNumber, setPageNumber] = useState(1); + const [containerWidth, setContainerWidth] = useState(null); + const containerRef = useRef(null); - const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => { - setNumPages(numPages); - }; + const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => { + setNumPages(numPages); + }; - useEffect(() => { - const updateWidth = () => { - if (containerRef.current) { - setContainerWidth(containerRef.current.offsetWidth); - } - }; + useEffect(() => { + const updateWidth = () => { + if (containerRef.current) { + setContainerWidth(containerRef.current.offsetWidth); + } + }; - updateWidth(); - window.addEventListener("resize", updateWidth); - return () => window.removeEventListener("resize", updateWidth); - }, []); + updateWidth(); + window.addEventListener("resize", updateWidth); + return () => window.removeEventListener("resize", updateWidth); + }, []); - return ( - - - - console.error("Es gab ein Fehler beim Laden des PDFs:", error) - } - onSourceError={(error) => console.error("Ungültige PDF:", error)} - > - {containerWidth && ( - - )} - - - - setPageNumber((p) => p - 1)} - > - - - - {pageNumber} / {numPages} - - = (numPages || 1)} - onClick={() => setPageNumber((p) => p + 1)} - > - - - - - ); + return ( + + + + console.error("Es gab ein Fehler beim Laden des PDFs:", error) + } + onSourceError={(error) => console.error("Ungültige PDF:", error)} + > + {containerWidth && ( + + )} + + + + setPageNumber((p) => p - 1)} + > + + + + {pageNumber} / {numPages} + + = (numPages || 1)} + onClick={() => setPageNumber((p) => p + 1)} + > + + + + + ); }