bfa-dryer-design/app.py

134 lines
4.2 KiB
Python
Raw Normal View History

"""BFA Banana Dryer — HMI Design Collaboration Tool"""
import os
import json
import time
import uuid
from flask import Flask, render_template, request, jsonify, redirect, make_response
app = Flask(__name__)
LAYOUT_DIR = os.path.join(os.path.dirname(__file__), "layouts")
PHOTO_DIR = os.path.join(os.path.dirname(__file__), "static", "photos")
os.makedirs(LAYOUT_DIR, exist_ok=True)
os.makedirs(PHOTO_DIR, exist_ok=True)
CURRENT_LAYOUT = os.path.join(LAYOUT_DIR, "current.json")
def get_layout():
# V2: GrapesJS project JSON stored in current_v2.json
v2_path = os.path.join(LAYOUT_DIR, "current_v2.json")
if os.path.exists(v2_path):
with open(v2_path) as f:
return json.load(f)
# No V2 layout yet — return empty so GrapesJS starts fresh
return {}
def get_v1_layout():
"""Legacy V1 layout for reference"""
if os.path.exists(CURRENT_LAYOUT):
with open(CURRENT_LAYOUT) as f:
return json.load(f)
return {}
def save_layout(layout):
# V2: save GrapesJS project data
v2_path = os.path.join(LAYOUT_DIR, "current_v2.json")
with open(v2_path, "w") as f:
json.dump(layout, f, indent=2)
def save_v1_layout(layout):
"""Legacy V1 save"""
with open(CURRENT_LAYOUT, "w") as f:
json.dump(layout, f, indent=2)
def get_user():
return request.cookies.get("bfa_user", "")
@app.route("/")
def index():
if not get_user():
return redirect("login")
return render_template("editor.html", user=get_user())
@app.route("/login", methods=["GET", "POST"])
def login():
layout = get_layout()
users = layout.get("users", ["Richard", "Rob", "Guido"])
if request.method == "POST":
name = request.form.get("user", "").strip()
if name:
resp = make_response(redirect("./"))
resp.set_cookie("bfa_user", name, max_age=86400*30)
# Add user to layout if new
if name not in users:
layout.setdefault("users", []).append(name)
save_layout(layout)
return resp
return render_template("login.html", users=users)
@app.route("/logout")
def logout():
resp = make_response(redirect("login"))
resp.delete_cookie("bfa_user")
return resp
@app.route("/api/v1html", methods=["GET"])
def api_v1html():
html_path = os.path.join(LAYOUT_DIR, "v1_converted.html")
if os.path.exists(html_path):
with open(html_path) as f:
return f.read(), 200, {'Content-Type': 'text/html'}
return "", 404
@app.route("/api/layout", methods=["GET"])
def api_get_layout():
return jsonify(get_layout())
@app.route("/api/layout", methods=["POST"])
def api_save_layout():
layout = request.json
save_layout(layout)
return jsonify({"ok": True})
@app.route("/api/comment", methods=["POST"])
def api_add_comment():
data = request.json
layout = get_layout()
comment = {
"id": str(uuid.uuid4())[:8],
"target": data["target"],
"user": data.get("user", get_user()),
"time": time.strftime("%Y-%m-%dT%H:%M:%S"),
"text": data["text"]
}
layout.setdefault("comments", []).append(comment)
save_layout(layout)
return jsonify(comment)
@app.route("/api/users", methods=["POST"])
def api_add_user():
name = request.json.get("name", "").strip()
if not name:
return jsonify({"error": "empty name"}), 400
layout = get_layout()
if name not in layout.get("users", []):
layout.setdefault("users", []).append(name)
save_layout(layout)
return jsonify({"ok": True, "users": layout["users"]})
@app.route("/api/photo", methods=["POST"])
def api_upload_photo():
if "file" not in request.files:
return jsonify({"error": "no file"}), 400
f = request.files["file"]
fname = f"{int(time.time())}_{f.filename}"
f.save(os.path.join(PHOTO_DIR, fname))
return jsonify({"filename": fname, "url": f"static/photos/{fname}"})
@app.route("/api/photos", methods=["GET"])
def api_list_photos():
photos = sorted(os.listdir(PHOTO_DIR)) if os.path.exists(PHOTO_DIR) else []
return jsonify([{"filename": p, "url": f"static/photos/{p}"} for p in photos if not p.startswith(".")])
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5001, debug=True)