feat: serve landing page via Jinja2 with module grid
This commit is contained in:
parent
90d7910500
commit
9e60fbb7cf
70
app/main.py
70
app/main.py
@ -1,4 +1,7 @@
|
|||||||
from fastapi import FastAPI, WebSocket
|
from fastapi import FastAPI, Request, WebSocket
|
||||||
|
from fastapi.responses import HTMLResponse
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
|
|
||||||
@ -9,14 +12,71 @@ app = FastAPI(
|
|||||||
root_path=settings.APP_PREFIX,
|
root_path=settings.APP_PREFIX,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory="app/static"), name="static")
|
||||||
|
templates = Jinja2Templates(directory="app/templates")
|
||||||
|
|
||||||
@app.get("/")
|
MODULES = [
|
||||||
async def root():
|
{
|
||||||
return {"status": "ok", "env": settings.APP_ENV}
|
"icon": "📡",
|
||||||
|
"name": "RSS-Feed Server",
|
||||||
|
"description": "Aggregiert und verteilt Neuigkeiten der Fakultät als standardkonformen RSS 2.0 Feed.",
|
||||||
|
"status": "active",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "📅",
|
||||||
|
"name": "Kalender",
|
||||||
|
"description": "Veranstaltungen, Prüfungstermine und Fristen im iCal-Format.",
|
||||||
|
"status": "planned",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "🔔",
|
||||||
|
"name": "Benachrichtigungen",
|
||||||
|
"description": "Push-Nachrichten und WebSocket-basierte Echtzeit-Alerts für Studierende.",
|
||||||
|
"status": "planned",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "📊",
|
||||||
|
"name": "Auslastung",
|
||||||
|
"description": "Raum- und Ressourcenauslastung der Fakultät in Echtzeit.",
|
||||||
|
"status": "planned",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "📚",
|
||||||
|
"name": "Lehrveranstaltungen",
|
||||||
|
"description": "Stundenplan-API und Kursinformationen aus dem Campus-System.",
|
||||||
|
"status": "planned",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
NAV_ITEMS = [
|
||||||
|
{"label": "Übersicht", "url": "/", "active": True},
|
||||||
|
{"label": "RSS-Feeds", "url": "/rss", "active": False},
|
||||||
|
{"label": "Kalender", "url": "/kalender", "active": False},
|
||||||
|
{"label": "Docs", "url": "/docs", "active": False},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _db_mode() -> str:
|
||||||
|
url = settings.DATABASE_URL
|
||||||
|
return "SQLite (dev)" if url.startswith("sqlite") else "MariaDB (prod)"
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/", response_class=HTMLResponse)
|
||||||
|
async def root(request: Request):
|
||||||
|
return templates.TemplateResponse(
|
||||||
|
request,
|
||||||
|
"index.html",
|
||||||
|
{
|
||||||
|
"nav_items": NAV_ITEMS,
|
||||||
|
"modules": MODULES,
|
||||||
|
"db_mode": _db_mode(),
|
||||||
|
"app_version": "0.1.0",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.websocket("/ws/hello/{name}")
|
@app.websocket("/ws/hello/{name}")
|
||||||
async def websocket_hello(websocket: WebSocket, name: str):
|
async def websocket_hello(websocket: WebSocket, name: str):
|
||||||
await websocket.accept()
|
await websocket.accept()
|
||||||
await websocket.send_text(f"Hello, {name}!")
|
await websocket.send_text(f"Hello, {name}!")
|
||||||
await websocket.close()
|
await websocket.close()
|
||||||
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
31
tests/test_landing.py
Normal file
31
tests/test_landing.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from fastapi.testclient import TestClient
|
||||||
|
from app.main import app
|
||||||
|
|
||||||
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
def test_landing_returns_html():
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "text/html" in response.headers["content-type"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_landing_contains_title():
|
||||||
|
response = client.get("/")
|
||||||
|
assert "University Process Hub" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_landing_contains_rss_module():
|
||||||
|
response = client.get("/")
|
||||||
|
assert "RSS-Feed Server" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_landing_navbar_links_present():
|
||||||
|
response = client.get("/")
|
||||||
|
assert "Übersicht" in response.text
|
||||||
|
assert "RSS-Feeds" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_landing_info_strip_shows_db_mode():
|
||||||
|
response = client.get("/")
|
||||||
|
assert "SQLite" in response.text or "MariaDB" in response.text
|
||||||
Loading…
x
Reference in New Issue
Block a user