Reworked flow

This commit is contained in:
Djeex
2025-08-16 11:17:15 +02:00
parent 1b0b228273
commit 041db66b3d
5 changed files with 125 additions and 145 deletions

View File

@ -2,49 +2,64 @@ import logging
from pathlib import Path
from flask import Blueprint, request, current_app
from werkzeug.utils import secure_filename
from src.py.builder.gallery_builder import update_gallery, update_hero
# Create a Flask blueprint for upload routes
# --- Create Flask blueprint for upload routes ---
upload_bp = Blueprint("upload", __name__)
# Allowed file extensions for uploads
# --- Allowed file types ---
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "webp"}
# Function to check if a file has an allowed extension
def allowed_file(filename: str) -> bool:
"""Check if the uploaded file has an allowed extension."""
return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
# Function to save uploaded file to a given folder
def save_uploaded_file(file, folder: Path):
folder.mkdir(parents=True, exist_ok=True) # Create folder if it doesn't exist
"""Save an uploaded file to the specified folder."""
folder.mkdir(parents=True, exist_ok=True) # Create folder if not exists
filename = secure_filename(file.filename) # Sanitize filename
file.save(folder / filename) # Save file to folder
file.save(folder / filename) # Save to disk
logging.info(f"[✓] Uploaded {filename} to {folder}")
return filename # Return saved filename
return filename
# Route to handle photo uploads for gallery or hero
@upload_bp.route("/api/<section>/upload", methods=["POST"])
def upload_photo(section: str):
"""
Handle file uploads for gallery or hero section.
Accepts multiple files under 'files'.
"""
# Validate section
if section not in ["gallery", "hero"]:
return {"error": "Invalid section"}, 400
# Check if the request contains a file
if "file" not in request.files:
return {"error": "No file part"}, 400
file = request.files["file"]
# Check if files are provided
if "files" not in request.files:
return {"error": "No files provided"}, 400
files = request.files.getlist("files")
if not files:
return {"error": "No selected files"}, 400
# Check if a file was actually selected
if file.filename == "":
return {"error": "No selected file"}, 400
# Get photos directory from app config
PHOTOS_DIR = current_app.config.get("PHOTOS_DIR")
if not PHOTOS_DIR:
return {"error": "Server misconfiguration"}, 500
# Check file type and save it
if file and allowed_file(file.filename):
PHOTOS_DIR = current_app.config.get("PHOTOS_DIR") # Get base photos directory from config
if not PHOTOS_DIR:
return {"error": "Server misconfiguration"}, 500
folder = PHOTOS_DIR / section # Target folder (gallery or hero)
filename = save_uploaded_file(file, folder)
return {"status": "ok", "filename": filename}
folder = PHOTOS_DIR / section # Target folder
uploaded = []
# If file type is not allowed
return {"error": "File type not allowed"}, 400
# Save each valid file
for file in files:
if file and allowed_file(file.filename):
filename = save_uploaded_file(file, folder)
uploaded.append(filename)
# Update YAML if any files were uploaded
if uploaded:
if section == "gallery":
update_gallery()
else:
update_hero()
return {"status": "ok", "uploaded": uploaded}
return {"error": "No valid files uploaded"}, 400

View File

@ -2,111 +2,106 @@ import logging
from pathlib import Path
from flask import Flask, jsonify, request, send_from_directory, render_template
from src.py.builder.gallery_builder import (
GALLERY_YAML, GALLERY_DIR, HERO_DIR,
load_yaml, save_yaml, get_all_image_paths, update_gallery, update_hero
GALLERY_YAML, load_yaml, save_yaml, update_gallery, update_hero
)
from src.py.webui.upload import upload_bp
# --- Logging configuration ---
# Logs messages to console with INFO level
logging.basicConfig(level=logging.INFO, format="%(message)s")
# --- Flask app setup ---
# WEBUI_PATH points to the web UI folder (templates + static)
WEBUI_PATH = Path(__file__).parents[2] / "webui"
WEBUI_PATH = Path(__file__).parents[2] / "webui" # Path to static/templates
app = Flask(
__name__,
template_folder=WEBUI_PATH, # where Flask looks for templates
static_folder=WEBUI_PATH, # where Flask serves static files
static_url_path="" # URL path prefix for static files
template_folder=WEBUI_PATH,
static_folder=WEBUI_PATH,
static_url_path=""
)
# --- Absolute photos directory ---
# Used by upload.py and deletion endpoints
# --- Photos directory (configurable) ---
PHOTOS_DIR = Path(__file__).resolve().parents[3] / "config" / "photos"
app.config["PHOTOS_DIR"] = PHOTOS_DIR
# --- Register upload blueprint ---
# Handles /api/<section>/upload endpoints for gallery and hero images
app.register_blueprint(upload_bp)
# --- Existing API routes ---
# --- Routes ---
# Serve main page
@app.route("/")
def index():
"""Serve the main HTML page."""
return render_template("index.html")
# Get gallery images (returns JSON array)
@app.route("/api/gallery", methods=["GET"])
def get_gallery():
"""Return JSON list of gallery images from YAML."""
data = load_yaml(GALLERY_YAML)
return jsonify(data.get("gallery", {}).get("images", []))
# Get hero images (returns JSON array)
@app.route("/api/hero", methods=["GET"])
def get_hero():
"""Return JSON list of hero images from YAML."""
data = load_yaml(GALLERY_YAML)
return jsonify(data.get("hero", {}).get("images", []))
# Update gallery images with new JSON data
@app.route("/api/gallery/update", methods=["POST"])
def update_gallery_api():
"""Update gallery images in YAML from frontend JSON."""
images = request.json
data = load_yaml(GALLERY_YAML)
data["gallery"]["images"] = images
save_yaml(data, GALLERY_YAML)
return jsonify({"status": "ok"})
# Update hero images with new JSON data
@app.route("/api/hero/update", methods=["POST"])
def update_hero_api():
"""Update hero images in YAML from frontend JSON."""
images = request.json
data = load_yaml(GALLERY_YAML)
data["hero"]["images"] = images
save_yaml(data, GALLERY_YAML)
return jsonify({"status": "ok"})
# Refresh gallery from the folder (rebuild YAML)
@app.route("/api/gallery/refresh", methods=["POST"])
def refresh_gallery():
"""Refresh gallery YAML from photos/gallery folder."""
update_gallery()
return jsonify({"status": "ok"})
# Refresh hero images from the folder
@app.route("/api/hero/refresh", methods=["POST"])
def refresh_hero():
"""Refresh hero YAML from photos/hero folder."""
update_hero()
return jsonify({"status": "ok"})
# Delete a gallery image file
@app.route("/api/gallery/delete", methods=["POST"])
def delete_gallery_photo():
"""Delete a gallery photo from disk and return status."""
data = request.json
src = data.get("src") # filename only
src = data.get("src")
file_path = PHOTOS_DIR / "gallery" / src
if file_path.exists():
file_path.unlink() # remove the file
file_path.unlink()
return {"status": "ok"}
return {"error": "File not found"}, 404
# Delete a hero image file
@app.route("/api/hero/delete", methods=["POST"])
def delete_hero_photo():
"""Delete a hero photo from disk and return status."""
data = request.json
src = data.get("src") # filename only
src = data.get("src")
file_path = PHOTOS_DIR / "hero" / src
if file_path.exists():
file_path.unlink() # remove the file
file_path.unlink()
return {"status": "ok"}
return {"error": "File not found"}, 404
# Serve photos from /photos/<section>/<filename>
@app.route("/photos/<section>/<path:filename>")
def photos(section, filename):
"""Serve uploaded photos from disk."""
return send_from_directory(PHOTOS_DIR / section, filename)
# --- Main entry point ---
# --- Run server ---
if __name__ == "__main__":
logging.info("Starting WebUI at http://127.0.0.1:5000")
app.run(debug=True)