112 lines
3.8 KiB
Python
112 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from flask import Flask
|
|
|
|
from config import Config
|
|
|
|
from .cli import register_cli, seed_badges
|
|
from .extensions import csrf, db, login_manager
|
|
from .forms import QuickTaskForm
|
|
from .routes import auth, main, scoreboard, settings, tasks
|
|
from .routes.main import load_icon_svg
|
|
from .services.app_settings import get_quick_task_config
|
|
from .services.badges import sync_existing_badges
|
|
from .services.bootstrap import ensure_schema_and_admins
|
|
from .services.dates import MONTH_NAMES, local_now
|
|
from .services.monthly import archive_months_missing_up_to_previous
|
|
|
|
|
|
def create_app(config_class: type[Config] = Config) -> Flask:
|
|
app = Flask(__name__, static_folder="static", template_folder="templates")
|
|
app.config.from_object(config_class)
|
|
|
|
manifest_path = Path(app.root_path).parent / "CloudronManifest.json"
|
|
try:
|
|
app.config["APP_VERSION"] = json.loads(manifest_path.read_text(encoding="utf-8")).get("version", "0.0.0")
|
|
except FileNotFoundError:
|
|
app.config["APP_VERSION"] = "0.0.0"
|
|
|
|
app.config["DATA_DIR"].mkdir(parents=True, exist_ok=True)
|
|
app.config["UPLOAD_FOLDER"].mkdir(parents=True, exist_ok=True)
|
|
|
|
db.init_app(app)
|
|
login_manager.init_app(app)
|
|
csrf.init_app(app)
|
|
|
|
with app.app_context():
|
|
db.create_all()
|
|
ensure_schema_and_admins()
|
|
seed_badges()
|
|
sync_existing_badges()
|
|
|
|
register_cli(app)
|
|
|
|
app.register_blueprint(main.bp)
|
|
app.register_blueprint(auth.bp)
|
|
app.register_blueprint(tasks.bp)
|
|
app.register_blueprint(scoreboard.bp)
|
|
app.register_blueprint(settings.bp)
|
|
|
|
app.jinja_env.globals["icon_svg"] = lambda name: load_icon_svg(name, app.static_folder)
|
|
|
|
@app.before_request
|
|
def ensure_archives():
|
|
archive_months_missing_up_to_previous()
|
|
|
|
@app.context_processor
|
|
def inject_globals():
|
|
quick_task_form = QuickTaskForm(prefix="quick")
|
|
quick_task_config = get_quick_task_config()
|
|
quick_task_form.effort.choices = [
|
|
(key, values["label"])
|
|
for key, values in quick_task_config.items()
|
|
]
|
|
def asset_version(filename: str) -> int:
|
|
path = Path(app.static_folder) / filename
|
|
try:
|
|
return int(path.stat().st_mtime)
|
|
except FileNotFoundError:
|
|
return 1
|
|
|
|
return {
|
|
"app_name": app.config["APP_NAME"],
|
|
"app_version": app.config["APP_VERSION"],
|
|
"nav_items": [
|
|
("tasks.my_tasks", "Meine Aufgaben", "house"),
|
|
("tasks.all_tasks", "Alle", "list"),
|
|
("tasks.create", "Neu", "plus"),
|
|
("tasks.calendar_view", "Kalender", "calendar"),
|
|
("scoreboard.index", "Highscore", "trophy"),
|
|
("settings.index", "Optionen", "gear"),
|
|
],
|
|
"mobile_nav_items": [
|
|
("tasks.my_tasks", "Meine Aufgaben", "house"),
|
|
("tasks.all_tasks", "Alle Aufgaben", "list"),
|
|
("tasks.calendar_view", "Kalender", "calendar"),
|
|
("scoreboard.index", "Highscore", "trophy"),
|
|
("settings.index", "Optionen", "gear"),
|
|
],
|
|
"icon_svg": lambda name: load_icon_svg(name, app.static_folder),
|
|
"asset_version": asset_version,
|
|
"now_local": local_now(),
|
|
"quick_task_form": quick_task_form,
|
|
"quick_task_config": quick_task_config,
|
|
}
|
|
|
|
@app.template_filter("date_de")
|
|
def date_de(value):
|
|
return value.strftime("%d.%m.%Y") if value else "—"
|
|
|
|
@app.template_filter("datetime_de")
|
|
def datetime_de(value):
|
|
return value.strftime("%d.%m.%Y, %H:%M") if value else "—"
|
|
|
|
@app.template_filter("month_name")
|
|
def month_name(value):
|
|
return MONTH_NAMES[value]
|
|
|
|
return app
|