Initial commit

This commit is contained in:
Tie 2026-04-01 21:13:58 +02:00
commit b22231c8b6
40 changed files with 2443 additions and 0 deletions

131
frontend/routes/admin.py Normal file
View file

@ -0,0 +1,131 @@
from fastapi import APIRouter, Request, HTTPException
from fastapi.responses import HTMLResponse
import api_client
import config
import json
from pathlib import Path
router = APIRouter()
@router.get("/backend-config", response_class=HTMLResponse)
async def backend_config(request: Request):
"""Affiche le formulaire de configuration du backend"""
current_backend_url = config.BACKEND_URL
current_potree_url = config.POTREE_URL
return request.app.state.templates.TemplateResponse(
"partials/backend_config.html",
{"request": request, "current_backend_url": current_backend_url, "current_potree_url": current_potree_url},
)
@router.post("/backend-config", response_class=HTMLResponse)
async def save_backend_config(request: Request):
"""Sauvegarde les nouvelles URLs du backend et Potree"""
form_data = await request.form()
new_backend_url = form_data.get("backend_url", "").strip().rstrip("/")
new_potree_url = form_data.get("potree_url", "").strip().rstrip("/")
if not new_backend_url:
return request.app.state.templates.TemplateResponse(
"partials/backend_config.html",
{"request": request, "current_backend_url": config.BACKEND_URL, "current_potree_url": config.POTREE_URL, "error": "URL du backend vide"},
)
# Sauvegarder dans le fichier JSON
config_file = Path(__file__).parent.parent / "config" / "backend.json"
config_file.parent.mkdir(parents=True, exist_ok=True)
config_data = {}
if new_backend_url:
config_data["backend_url"] = new_backend_url
if new_potree_url:
config_data["potree_url"] = new_potree_url
with open(config_file, "w") as f:
json.dump(config_data, f, indent=2)
# Mettre à jour les variables module
config.BACKEND_URL = new_backend_url
config.POTREE_URL = new_potree_url
return request.app.state.templates.TemplateResponse(
"partials/backend_config.html",
{"request": request, "current_backend_url": new_backend_url, "current_potree_url": new_potree_url, "success": True},
)
@router.get("/list", response_class=HTMLResponse)
async def admin_list(request: Request):
"""Affiche la liste de tous les nuages de points"""
pointclouds = await api_client.list_pointclouds()
return request.app.state.templates.TemplateResponse(
"partials/cloud_list.html",
{"request": request, "pointclouds": pointclouds},
)
@router.get("/debug/{pc_id}", response_class=HTMLResponse)
async def admin_debug(request: Request, pc_id: str):
"""Affiche les informations de debug pour un nuage"""
debug_info = await api_client.get_debug(pc_id)
return request.app.state.templates.TemplateResponse(
"partials/debug_panel.html",
{"request": request, "pc_id": pc_id, "data": debug_info},
)
@router.delete("/delete/{pc_id}", response_class=HTMLResponse)
async def admin_delete(request: Request, pc_id: str):
"""Supprime un nuage de points"""
try:
result = await api_client.delete_pointcloud(pc_id)
return request.app.state.templates.TemplateResponse(
"partials/upload_result.html",
{"request": request, "result": {
"id": pc_id,
"filename": f"{pc_id}.las",
"size_mb": 0,
"conversion_time_seconds": 0,
}, "error": None},
)
except Exception as e:
return request.app.state.templates.TemplateResponse(
"partials/upload_result.html",
{"request": request, "error": str(e), "result": None},
)
@router.post("/crop/{pc_id}", response_class=HTMLResponse)
async def admin_crop(request: Request, pc_id: str, box: dict):
"""
Crop le nuage de points avec PDAL.
Args:
pc_id: ID du nuage de points à cropper
box: dict avec les coordonnées de la box 3D
{"minX", "minY", "minZ", "maxX", "maxY", "maxZ"}
"""
try:
result = await api_client.crop_pointcloud(pc_id, box)
if result.get("ok"):
return request.app.state.templates.TemplateResponse(
"partials/upload_result.html",
{"request": request, "result": {
"id": result.get("id"),
"filename": f"{pc_id}_cropped.las",
"size_mb": result.get("size_mb", 0),
"conversion_time_seconds": result.get("conversion_time_seconds", 0),
}, "error": None},
)
else:
return request.app.state.templates.TemplateResponse(
"partials/upload_result.html",
{"request": request, "error": result.get("detail", "Erreur inconnue"), "result": None},
)
except Exception as e:
return request.app.state.templates.TemplateResponse(
"partials/upload_result.html",
{"request": request, "error": str(e), "result": None},
)