feat: FASE 0 - Setup progetto TieMeasureFlow

Struttura monorepo completa con server FastAPI e client Flask:
- Server: FastAPI + SQLAlchemy 2.0 async + Alembic migrations
- Client: Flask + blueprints (auth, measure, maker, statistics)
- Database: docker-compose MySQL 8.0 + Alembic async config
- Config: pydantic-settings, TailwindCSS, Flask-Babel i18n
- Piano implementazione completo (18 sezioni, 1600 righe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Adriano
2026-02-07 00:16:54 +01:00
commit dbdbb77daf
47 changed files with 2489 additions and 0 deletions
View File
+31
View File
@@ -0,0 +1,31 @@
"""Authentication blueprint - login, logout, profile."""
from flask import Blueprint, render_template, request, redirect, url_for, session, flash
auth_bp = Blueprint("auth", __name__)
@auth_bp.route("/login", methods=["GET", "POST"])
def login():
"""Login page."""
if request.method == "POST":
# TODO: Implement API call to server /api/auth/login
pass
return render_template("auth/login.html")
@auth_bp.route("/logout")
def logout():
"""Logout - clear session."""
session.clear()
return redirect(url_for("auth.login"))
@auth_bp.route("/profile", methods=["GET", "POST"])
def profile():
"""User profile - change display name, language, theme."""
if "user" not in session:
return redirect(url_for("auth.login"))
if request.method == "POST":
# TODO: Implement API call to server /api/auth/me PUT
pass
return render_template("auth/profile.html")
+45
View File
@@ -0,0 +1,45 @@
"""Maker blueprint - recipe creation and editing."""
from flask import Blueprint, render_template, session, redirect, url_for
maker_bp = Blueprint("maker", __name__)
@maker_bp.route("/recipes")
def recipe_list():
"""List all recipes with filters."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("maker/recipe_list.html")
@maker_bp.route("/recipes/new")
@maker_bp.route("/recipes/<int:recipe_id>/edit")
def recipe_editor(recipe_id: int | None = None):
"""Recipe editor - create or edit."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("maker/recipe_editor.html", recipe_id=recipe_id)
@maker_bp.route("/recipes/<int:recipe_id>/tasks")
def task_editor(recipe_id: int):
"""Task/subtask editor with tolerances."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("maker/task_editor.html", recipe_id=recipe_id)
@maker_bp.route("/recipes/<int:recipe_id>/preview")
def recipe_preview(recipe_id: int):
"""Preview recipe as MeasurementTec would see it."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("maker/recipe_preview.html", recipe_id=recipe_id)
@maker_bp.route("/recipes/<int:recipe_id>/versions")
def version_history(recipe_id: int):
"""Version history with diff."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("maker/version_history.html", recipe_id=recipe_id)
+36
View File
@@ -0,0 +1,36 @@
"""MeasurementTec blueprint - recipe selection and measurement execution."""
from flask import Blueprint, render_template, session, redirect, url_for
measure_bp = Blueprint("measure", __name__)
@measure_bp.route("/select")
def select_recipe():
"""Recipe selection page."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("measure/select_recipe.html")
@measure_bp.route("/tasks/<int:recipe_id>")
def task_list(recipe_id: int):
"""Task list for selected recipe."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("measure/task_list.html", recipe_id=recipe_id)
@measure_bp.route("/execute/<int:task_id>")
def task_execute(task_id: int):
"""Execute measurements for a task."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("measure/task_execute.html", task_id=task_id)
@measure_bp.route("/complete/<int:recipe_id>")
def task_complete(recipe_id: int):
"""Task completion summary."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("measure/task_complete.html", recipe_id=recipe_id)
+44
View File
@@ -0,0 +1,44 @@
"""Metrologist blueprint - SPC statistics and dashboards."""
from flask import Blueprint, render_template, session, redirect, url_for
statistics_bp = Blueprint("statistics", __name__)
@statistics_bp.route("/dashboard")
def dashboard():
"""SPC dashboard overview."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("statistics/dashboard.html")
@statistics_bp.route("/control-chart")
def control_chart():
"""X-bar / R control chart."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("statistics/control_chart.html")
@statistics_bp.route("/histogram")
def histogram():
"""Histogram with normal curve."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("statistics/histogram.html")
@statistics_bp.route("/capability")
def capability():
"""Cp/Cpk/Pp/Ppk capability gauge."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("statistics/capability.html")
@statistics_bp.route("/trend")
def trend():
"""Temporal trends and period comparison."""
if "user" not in session:
return redirect(url_for("auth.login"))
return render_template("statistics/trend.html")