Browse Source

corrected bugs in the overlay manager

Nicole Portas 1 tháng trước cách đây
mục cha
commit
1e6b018d4c
2 tập tin đã thay đổi với 55 bổ sung30 xóa
  1. 49 24
      overlay_manager/main.py
  2. 6 6
      overlay_manager/templates/edit.html

+ 49 - 24
overlay_manager/main.py

@@ -1,32 +1,34 @@
 import os
 import shutil
+import logging
+import tempfile
 from fastapi import FastAPI, Request, File, UploadFile, Form
-from fastapi.responses import HTMLResponse, RedirectResponse
+from fastapi.responses import HTMLResponse, RedirectResponse, FileResponse
 from fastapi.templating import Jinja2Templates
 from fastapi.staticfiles import StaticFiles
 
-app = FastAPI()
+# Setup logging
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger("overlay-manager")
+
+# root_path ensures FastAPI knows it lives at /patch-manager/
+app = FastAPI(root_path="/patch-manager")
 
-# Failsafe: Create the directory inside the container if it somehow gets missed
 os.makedirs("static", exist_ok=True)
 app.mount("/static", StaticFiles(directory="static"), name="static")
-
 templates = Jinja2Templates(directory="templates")
 
-# The persistent directory for your custom code
 OVERLAY_DIR = "/srv"
 
 @app.get("/", response_class=HTMLResponse)
 async def index(request: Request):
     files = []
-    dirs = set([""]) # Always include the root directory as an option
+    dirs = set([""])
     if os.path.exists(OVERLAY_DIR):
         for root, dirnames, filenames in os.walk(OVERLAY_DIR):
-            # Calculate the relative directory path
             rel_root = os.path.relpath(root, OVERLAY_DIR)
             if rel_root != ".":
                 dirs.add(rel_root)
-                
             for filename in filenames:
                 rel_path = os.path.relpath(os.path.join(root, filename), OVERLAY_DIR)
                 files.append(rel_path)
@@ -34,9 +36,21 @@ async def index(request: Request):
     return templates.TemplateResponse("index.html", {
         "request": request, 
         "files": sorted(files),
-        "dirs": sorted(list(dirs)) # Pass the sorted directories to the template dropdown
+        "dirs": sorted(list(dirs))
     })
 
+@app.get("/download-all")
+async def download_all():
+    """Zips the entire /srv directory and serves it as a backup."""
+    with tempfile.TemporaryDirectory() as tmpdir:
+        zip_base = os.path.join(tmpdir, "backup")
+        shutil.make_archive(zip_base, 'zip', OVERLAY_DIR)
+        return FileResponse(
+            path=f"{zip_base}.zip", 
+            filename="ardupilot_overlays_backup.zip",
+            media_type='application/zip'
+        )
+
 @app.post("/upload")
 async def upload_file(file: UploadFile = File(...), target_path: str = Form("")):
     save_dir = os.path.join(OVERLAY_DIR, target_path.strip("/"))
@@ -44,38 +58,49 @@ async def upload_file(file: UploadFile = File(...), target_path: str = Form(""))
     file_location = os.path.join(save_dir, file.filename)
     with open(file_location, "wb+") as file_object:
         shutil.copyfileobj(file.file, file_object)
-        
-    return RedirectResponse(url="/patch-manager/", status_code=303)
+    return RedirectResponse(url="./", status_code=303)
 
 @app.post("/create_folder")
 async def create_folder(folder_path: str = Form(...)):
     save_dir = os.path.join(OVERLAY_DIR, folder_path.strip("/"))
     os.makedirs(save_dir, exist_ok=True)
-    return RedirectResponse(url="/patch-manager/", status_code=303)
+    return RedirectResponse(url="./", status_code=303)
 
 @app.post("/delete")
 async def delete_file(filepath: str = Form(...)):
-    target = os.path.join(OVERLAY_DIR, filepath)
+    target = os.path.join(OVERLAY_DIR, filepath.lstrip("/"))
     if os.path.exists(target):
-        os.remove(target)
-        target_dir = os.path.dirname(target)
-        if not os.listdir(target_dir) and target_dir != OVERLAY_DIR:
-            os.rmdir(target_dir)
-    return RedirectResponse(url="/patch-manager/", status_code=303)
+        if os.path.isdir(target):
+            shutil.rmtree(target)
+        else:
+            os.remove(target)
+    return RedirectResponse(url="./", status_code=303)
 
 @app.get("/edit", response_class=HTMLResponse)
 async def edit_file(request: Request, filepath: str):
-    target = os.path.join(OVERLAY_DIR, filepath)
-    content = ""
-    if os.path.exists(target):
+    clean_path = filepath.lstrip("/")
+    target = os.path.join(OVERLAY_DIR, clean_path)
+    logger.info(f"Attempting to edit: {target}")
+
+    if not os.path.exists(target):
+        return HTMLResponse(content=f"<h1>404 Not Found</h1><p>File {target} missing.</p><a href='./'>Back</a>", status_code=404)
+
+    try:
         with open(target, "r", encoding="utf-8", errors="ignore") as f:
             content = f.read()
-    return templates.TemplateResponse("edit.html", {"request": request, "filepath": filepath, "content": content})
+    except Exception as e:
+        return HTMLResponse(content=f"<h1>Error</h1><p>{str(e)}</p>", status_code=500)
+
+    return templates.TemplateResponse("edit.html", {
+        "request": request, 
+        "filepath": filepath, 
+        "content": content
+    })
 
 @app.post("/edit")
 async def save_file(filepath: str = Form(...), content: str = Form(...)):
-    target = os.path.join(OVERLAY_DIR, filepath)
+    target = os.path.join(OVERLAY_DIR, filepath.lstrip("/"))
     if os.path.exists(target):
         with open(target, "w", encoding="utf-8") as f:
             f.write(content)
-    return RedirectResponse(url="/patch-manager/", status_code=303)
+    return RedirectResponse(url="./", status_code=303)

+ 6 - 6
overlay_manager/templates/edit.html

@@ -10,22 +10,22 @@
     <nav class="navbar navbar-dark shadow-sm py-2 mb-4" style="background-color: #0B61A4;">
         <div class="container">
             <span class="navbar-brand mb-0 h4"><i class="bi bi-pencil-square me-2"></i>Overlay Editor</span>
-            <a href="/" class="btn btn-outline-light btn-sm"><i class="bi bi-arrow-left me-1"></i>Back to Manager</a>
+            <a href="./" class="btn btn-outline-light btn-sm"><i class="bi bi-arrow-left me-1"></i>Back to Manager</a>
         </div>
     </nav>
 
     <div class="container">
-        <div class="card shadow border-0 rounded-3">
+        <div class="card shadow border-0 rounded-3 mb-5">
             <div class="card-header bg-white pt-3 pb-2 d-flex justify-content-between align-items-center">
                 <span class="font-monospace fw-bold text-primary">{{ filepath }}</span>
             </div>
             <div class="card-body p-0">
-                <form action="/edit" method="post">
+                <form action="edit" method="post">
                     <input type="hidden" name="filepath" value="{{ filepath }}">
-                    <textarea name="content" class="form-control border-0 font-monospace text-bg-dark rounded-0 p-3" rows="25" style="resize: none;" spellcheck="false">{{ content }}</textarea>
-                    
+                    <textarea name="content" class="form-control border-0 font-monospace text-bg-dark rounded-0 p-3" rows="25" style="resize: vertical; background-color: #1e1e1e; color: #d4d4d4;">{{ content }}</textarea>
+
                     <div class="p-3 bg-light text-end rounded-bottom-3">
-                        <a href="/" class="btn btn-secondary me-2">Cancel</a>
+                        <a href="./" class="btn btn-secondary me-2">Cancel</a>
                         <button type="submit" class="btn btn-success fw-bold"><i class="bi bi-save2-fill me-2"></i>Commit Changes</button>
                     </div>
                 </form>