Refaktor 4/4: admin kao Blueprint-ovi + auto-meni

Admin stranica app-a živi u folderu app-a:
- idriz/apps/superheroji/admin.py (Flask Blueprint BP + NAV), template preseljen u
  idriz/apps/superheroji/templates/superheroji.html.
- admin/app.py: registruje sve iz ADMIN_APPS, lijevi meni se puni iz njihovih NAV
  (context processor), globalni before_request štiti i Blueprint rute.
- Uklonjena inline /superheroji ruta i hardkodiran link u base.html.

Dodavanje admin stranice novom app-u = admin.py (BP+NAV) u folderu app-a + upis u
ADMIN_APPS. Time je mini-app potpuno samostalan: prompt, tools, config i admin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzKpYaEsuWDevuNnvSjcFW
This commit is contained in:
idriz
2026-09-11 12:31:39 +02:00
parent e21b08c1b7
commit e74c617228
4 changed files with 69 additions and 37 deletions

View File

@@ -17,9 +17,12 @@ from flask import (
Flask, render_template, request, redirect, url_for, session, flash
)
# Pristup skladištu igre (bez openai zavisnosti) iz glavnog idriz paketa.
# Admin stranice mini-app-ova (lagani moduli iz glavnog paketa, bez openai zavisnosti).
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from idriz.apps.superheroji import store as gamestore # noqa: E402
from idriz.apps.superheroji import admin as _superheroji_admin # noqa: E402
# Svaki app-admin modul ima BP (Blueprint) i NAV (stavka lijevog menija).
ADMIN_APPS = [_superheroji_admin]
# --- Konfiguracija -----------------------------------------------------------
@@ -52,6 +55,24 @@ app.config.update(
PERMANENT_SESSION_LIFETIME=8 * 3600,
)
# Registruj admin stranice mini-app-ova i napuni lijevi meni iz njih.
for _m in ADMIN_APPS:
app.register_blueprint(_m.BP)
@app.context_processor
def _inject_nav():
return {"nav_apps": [_m.NAV for _m in ADMIN_APPS]}
@app.before_request
def _require_login():
"""Sve rute (uključujući app Blueprint-ove) traže prijavu, osim logina i statike."""
if request.endpoint in (None, "login", "static"):
return
if not session.get("user"):
return redirect(url_for("login", next=request.path))
def login_required(f):
@wraps(f)
@@ -201,39 +222,6 @@ def status():
)
@app.route("/superheroji", methods=["GET", "POST"])
@login_required
def superheroji():
if request.method == "POST":
action = request.form.get("action")
if action == "rounds":
try:
n = int(request.form.get("rounds", ""))
saved = gamestore.save_rounds(n)
flash(f"Broj rundi postavljen na {saved}.")
except (ValueError, TypeError):
flash("Neispravan broj rundi.")
elif action == "reset":
store = gamestore.HeroStore()
store.heroes = {}
store.aliases = {}
store.matchups = {}
store.save()
flash("Pamćenje jačina i dvoboja je obrisano.")
return redirect(url_for("superheroji"))
store = gamestore.HeroStore()
return render_template(
"superheroji.html",
rounds=gamestore.load_rounds(),
min_rounds=gamestore.MIN_ROUNDS,
max_rounds=gamestore.MAX_ROUNDS,
heroes=store.leaderboard(),
matchups=store.matchup_list(),
active_page="superheroji",
)
if __name__ == "__main__":
from waitress import serve
print(f"Idriz admin na http://{LISTEN_HOST}:{LISTEN_PORT}")