mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-20 06:20:57 +00:00
d200030361
Move routes from monolithic server.py (2716 lines) to dedicated route modules (788 lines remaining): - routes/main.py: Homepage, books browser, resources page - routes/misc.py: Search, interlinear landing, random-verse, verse-of-the-day - routes/timeline.py: Biblical timeline page and PDF - routes/about.py: Stats, cross-references index, about page - routes/reading_plans.py: Reading plans index, detail, PDF - routes/topics.py: Topics index and detail - routes/strongs.py: Strong's concordance search and entries This reduces server.py by 71% and improves code organization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
101 lines
3.0 KiB
Python
101 lines
3.0 KiB
Python
"""Topics routes - browse and view topical Bible studies."""
|
|
from fastapi import APIRouter, HTTPException, Request
|
|
from fastapi.responses import HTMLResponse, StreamingResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
|
|
from ..kjv import bible
|
|
from ..topics import get_all_topics, get_topic_with_text
|
|
from ..utils.pdf import WEASYPRINT_AVAILABLE, render_html_to_pdf_async
|
|
|
|
router = APIRouter()
|
|
templates = None
|
|
|
|
|
|
def init_templates(t: Jinja2Templates):
|
|
"""Initialize templates for topics routes."""
|
|
global templates
|
|
templates = t
|
|
|
|
|
|
# =============================================================================
|
|
# Routes
|
|
# =============================================================================
|
|
|
|
@router.get("/topics", response_class=HTMLResponse)
|
|
async def topics_page(request: Request):
|
|
"""Browse topical index of Bible themes"""
|
|
books = bible.get_books()
|
|
topics = get_all_topics()
|
|
|
|
breadcrumbs = [
|
|
{"text": "Home", "url": "/"},
|
|
{"text": "Topics", "url": None}
|
|
]
|
|
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"topics.html",
|
|
{
|
|
"topics": topics,
|
|
"books": books,
|
|
"breadcrumbs": breadcrumbs,
|
|
"pdf_available": WEASYPRINT_AVAILABLE
|
|
}
|
|
)
|
|
|
|
|
|
@router.get("/topics/{topic_name}", response_class=HTMLResponse)
|
|
async def topic_detail(request: Request, topic_name: str):
|
|
"""View verses for a specific topic"""
|
|
books = bible.get_books()
|
|
topic = get_topic_with_text(topic_name)
|
|
|
|
if not topic:
|
|
raise HTTPException(status_code=404, detail="Topic not found")
|
|
|
|
breadcrumbs = [
|
|
{"text": "Home", "url": "/"},
|
|
{"text": "Topics", "url": "/topics"},
|
|
{"text": topic_name, "url": None}
|
|
]
|
|
|
|
return templates.TemplateResponse(
|
|
request,
|
|
"topic_detail.html",
|
|
{
|
|
"topic": topic,
|
|
"topic_name": topic_name,
|
|
"books": books,
|
|
"breadcrumbs": breadcrumbs,
|
|
"pdf_available": WEASYPRINT_AVAILABLE,
|
|
"pdf_url": f"/topics/{topic_name}/pdf" if WEASYPRINT_AVAILABLE else None
|
|
}
|
|
)
|
|
|
|
|
|
@router.get("/topics/{topic_name}/pdf")
|
|
async def topic_detail_pdf(topic_name: str):
|
|
"""Generate a PDF export for a topic detail page."""
|
|
if not WEASYPRINT_AVAILABLE:
|
|
raise HTTPException(
|
|
status_code=503,
|
|
detail="PDF generation is not available. WeasyPrint system libraries are not installed."
|
|
)
|
|
|
|
topic = get_topic_with_text(topic_name)
|
|
if not topic:
|
|
raise HTTPException(status_code=404, detail="Topic not found")
|
|
|
|
html_content = templates.get_template("topic_pdf.html").render(
|
|
topic=topic,
|
|
topic_name=topic_name,
|
|
)
|
|
pdf_buffer = await render_html_to_pdf_async(html_content)
|
|
|
|
filename = f"{topic_name}.pdf"
|
|
return StreamingResponse(
|
|
pdf_buffer,
|
|
media_type="application/pdf",
|
|
headers={"Content-Disposition": f"attachment; filename={filename}"}
|
|
)
|