From 042ef2808a688f0109fbcfdfd3b5a1007d5262ab Mon Sep 17 00:00:00 2001 From: Heinz-Ullrich Rings <ullrich.rings@ilr.rwth-aachen.de> Date: Tue, 22 Oct 2024 15:37:18 +0200 Subject: [PATCH] added to save and load the project list from the backend --- UnicadoGUI/Backend/main.py | 28 ++++++- UnicadoGUI/Backend/requirements.txt | 3 +- UnicadoGUI/Frontend/src/routes/+page.svelte | 45 ++++++++-- UnicadoGUI/Frontend/src/stores/projects.js | 93 ++++++++++++++++++--- 4 files changed, 146 insertions(+), 23 deletions(-) diff --git a/UnicadoGUI/Backend/main.py b/UnicadoGUI/Backend/main.py index 0cd07cd6..79989766 100644 --- a/UnicadoGUI/Backend/main.py +++ b/UnicadoGUI/Backend/main.py @@ -1,11 +1,13 @@ import configparser import json -from fastapi import FastAPI +from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import FileResponse from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import xmltodict from fastapi.encoders import jsonable_encoder +import os +import shutil #FastAPI Backend for UNICADO Gui app = FastAPI() @@ -110,3 +112,27 @@ async def get_csv(file: str): async def get_report(file: str): return FileResponse(f"output_files/reportHTML/{file}") +#location for the porject lists +UPLOAD_DIRECTORY = "./project_lists/" + +if not os.path.exists(UPLOAD_DIRECTORY): + os.makedirs(UPLOAD_DIRECTORY) + +#endpoint to save the project list on the server +@app.post("/projects/") +async def upload_project_list(file: UploadFile = File(...)): + if not file.filename.endswith(".zip"): + raise HTTPException(status_code=400, detail="Only .zip files are allowed") + + file_path = os.path.join(UPLOAD_DIRECTORY, file.filename) + + with open(file_path, "wb") as buffer: + shutil.copyfileobj(file.file, buffer) + + return {"Project list successfully saved"} + +#endpoint to get the project list from the server +@app.get("/projects/") +async def get_project_list(): + file_path = UPLOAD_DIRECTORY + "projects.zip" + return FileResponse(path=file_path, filename="projects.zip", media_type="application/zip") \ No newline at end of file diff --git a/UnicadoGUI/Backend/requirements.txt b/UnicadoGUI/Backend/requirements.txt index 6fef470e..c884f2f8 100644 --- a/UnicadoGUI/Backend/requirements.txt +++ b/UnicadoGUI/Backend/requirements.txt @@ -1,3 +1,4 @@ xmltodict~=0.13.0 fastapi~=0.109.2 -pydantic~=1.10.14 \ No newline at end of file +pydantic~=1.10.14 +python-multipart==0.0.12 \ No newline at end of file diff --git a/UnicadoGUI/Frontend/src/routes/+page.svelte b/UnicadoGUI/Frontend/src/routes/+page.svelte index 2fb0897d..2579143a 100644 --- a/UnicadoGUI/Frontend/src/routes/+page.svelte +++ b/UnicadoGUI/Frontend/src/routes/+page.svelte @@ -1,6 +1,6 @@ <script> import { Button, Styles, Icon, Modal, ModalHeader, ModalBody, ModalFooter} from "@sveltestrap/sveltestrap"; - import { addProject, removeProject, saveProjectsAsZip, loadProjectsFromZip } from '../stores/projects'; + import { addProject, removeProject, saveProjectsAsZip, loadProjectsFromZip, saveProjectsOnServer, loadProjectsFromServer } from '../stores/projects'; let projectName = ''; let projectToRemove = ''; let showModal = false; @@ -16,7 +16,7 @@ function deleteProject() { if (projectToRemove.trim() !== '') { removeProject(projectToRemove); - projectToRemove = ''; // Eingabefeld leeren nach dem Hinzufügen + projectToRemove = ''; } } @@ -28,13 +28,13 @@ showModal = false; } const handleSave = async () => { - try { - await saveProjectsAsZip(); - console.log("Projects saved successfully"); - } catch (error) { - console.error("Error while trying to save the project list", error); + try { + await saveProjectsAsZip(); + console.log("Projects saved successfully"); + } catch (error) { + console.error("Error while trying to save the project list", error); + } } - } function handleFileUpload(/** @type any */event) { const selectedFile = event.target.files[0]; @@ -51,6 +51,26 @@ console.error('file-input not found'); } } + + const triggerFileUpload = async () => { + try { + await saveProjectsOnServer(); + console.log("Project list saved successfully"); + } catch (error) { + console.error("Error while trying to save the project list", error); + } + } + + + const triggerFileDownload = async () => { + try { + await loadProjectsFromServer(); + console.log("Project list Loaded successfully"); + } catch (error) { + console.error("Error while trying to load the project list", error); + } + } + </script> <h1>Welcome to the UNICADO WebApp</h1> @@ -76,6 +96,15 @@ Load project Liste von zip-file </Button> +<Button on:click={triggerFileUpload}> + <Icon name="cloud-upload"/> + Save projects list on the server +</Button> + +<Button on:click={triggerFileDownload}> + <Icon name="cloud-upload"/> + Load project Liste from the server +</Button> {#if showModal} <Modal isOpen={showModal} toggle={closeModal}> <ModalHeader toggle={closeModal}>Add New Project</ModalHeader> diff --git a/UnicadoGUI/Frontend/src/stores/projects.js b/UnicadoGUI/Frontend/src/stores/projects.js index 58a8e136..830e7814 100644 --- a/UnicadoGUI/Frontend/src/stores/projects.js +++ b/UnicadoGUI/Frontend/src/stores/projects.js @@ -72,19 +72,8 @@ export const saveProjectsAsZip = async () => { projectArray = value; })(); - projectArray.forEach((project) => { - const folder = zip.folder(project.name); - - if (folder) { - const fileContent = JSON.stringify({ id: project.id }, null, 2); - folder.file("data.json", fileContent); - } else { - console.error(`Could not create folder for project: ${project.name}`); - } - }); - - const blob = await zip.generateAsync({ type: "blob" }); - const url = URL.createObjectURL(blob); + const zipBlob = await createZipFile(projectArray); + const url = URL.createObjectURL(zipBlob); const a = document.createElement('a'); a.href = url; a.download = 'projects.zip'; @@ -92,10 +81,16 @@ export const saveProjectsAsZip = async () => { URL.revokeObjectURL(url); }; + + /** * Loads the Project List from a zip file */ export const loadProjectsFromZip = (/** @type {File} */ file) => { + loadProjectList(file); +}; + +const loadProjectList = async (/** @type {File} */ file) => { const zip = new JSZip(); zip.loadAsync(file).then(async (zipContent) => { /** @type {Project[]} */ @@ -126,4 +121,76 @@ export const loadProjectsFromZip = (/** @type {File} */ file) => { alert("Error while loading the project list from a file"); console.error(error); }); +} + +/** + * helper function that parse the project zip file and loads it into the userProject list + */ +export const saveProjectsOnServer = async () => { + /** @type {Project[]} */ + let projectArray = []; + userProjects.subscribe(value => { + projectArray = value; + })(); + + const zipBlob = await createZipFile(projectArray); + const formData = new FormData(); + formData.append("file", new Blob([zipBlob]), "projects.zip"); + + try { + const response = await fetch('http://127.0.0.1:8000/projects/', { + method: "POST", + body: formData, + }); + + if (!response.ok) { + throw new Error("Failed to upload ZIP file"); + } + + console.log("ZIP file uploaded successfully"); + } catch (error) { + console.error("Error uploading file:", error); + } +} + +/** + * Function to load the project list from the server + */ +export const loadProjectsFromServer = async () => { + try { + const response = await fetch('http://127.0.0.1:8000/projects/', { + method: "GET", + }); + if (!response.ok) { + throw new Error("Failed to download the project list"); + } + const blob = await response.blob(); + const file = new File([blob], "projects.zip", { type: blob.type }); + + await loadProjectList(file); + } catch (error) { + console.error("Error downloading the project list:", error); + } +} + + +/** + * helper function: + * generates a zip file with all the project files, every project gets its own directory + */ +const createZipFile = async (/** @type {Project[]} */ projects) => { + const zip = new JSZip(); + + projects.forEach((project) => { + const folder = zip.folder(project.name); + + if (folder) { + const fileContent = JSON.stringify({ id: project.id }, null, 2); + folder.file("data.json", fileContent); + } else { + console.error(`Could not create folder for project: ${project.name}`); + } + }); + + return await zip.generateAsync({ type: "blob" }); }; \ No newline at end of file -- GitLab