Ryan Malloy bec1606c86 Add comprehensive documentation system and tool call tracking
## Documentation System
- Create complete documentation hub at /dashboard/docs with:
  - Getting Started guide with quick setup and troubleshooting
  - Hook Setup Guide with platform-specific configurations
  - API Reference with all endpoints and examples
  - FAQ with searchable questions and categories
- Add responsive design with interactive features
- Update navigation in base template

## Tool Call Tracking
- Add ToolCall model for tracking Claude Code tool usage
- Create /api/tool-calls endpoints for recording and analytics
- Add tool_call hook type with auto-session detection
- Include tool calls in project statistics and recalculation
- Track tool names, parameters, execution time, and success rates

## Project Enhancements
- Add project timeline and statistics pages (fix 404 errors)
- Create recalculation script for fixing zero statistics
- Update project stats to include tool call counts
- Enhance session model with tool call relationships

## Infrastructure
- Switch from requirements.txt to pyproject.toml/uv.lock
- Add data import functionality for claude.json files
- Update database connection to include all new models
- Add comprehensive API documentation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-11 05:58:27 -06:00

122 lines
4.4 KiB
Python

"""
Dashboard web interface routes.
"""
from fastapi import APIRouter, Request, Depends
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
from sqlalchemy.ext.asyncio import AsyncSession
from app.database.connection import get_db
dashboard_router = APIRouter()
templates = Jinja2Templates(directory="app/dashboard/templates")
@dashboard_router.get("/dashboard", response_class=HTMLResponse)
async def dashboard_home(request: Request, db: AsyncSession = Depends(get_db)):
"""Main dashboard page."""
return templates.TemplateResponse("dashboard.html", {
"request": request,
"title": "Claude Code Project Tracker"
})
@dashboard_router.get("/dashboard/projects", response_class=HTMLResponse)
async def dashboard_projects(request: Request, db: AsyncSession = Depends(get_db)):
"""Projects overview page."""
return templates.TemplateResponse("projects.html", {
"request": request,
"title": "Projects - Claude Code Tracker"
})
@dashboard_router.get("/dashboard/analytics", response_class=HTMLResponse)
async def dashboard_analytics(request: Request, db: AsyncSession = Depends(get_db)):
"""Analytics and insights page."""
return templates.TemplateResponse("analytics.html", {
"request": request,
"title": "Analytics - Claude Code Tracker"
})
@dashboard_router.get("/dashboard/conversations", response_class=HTMLResponse)
async def dashboard_conversations(request: Request, db: AsyncSession = Depends(get_db)):
"""Conversation search and history page."""
return templates.TemplateResponse("conversations.html", {
"request": request,
"title": "Conversations - Claude Code Tracker"
})
@dashboard_router.get("/dashboard/import", response_class=HTMLResponse)
async def dashboard_import(request: Request, db: AsyncSession = Depends(get_db)):
"""Data import page."""
return templates.TemplateResponse("import.html", {
"request": request,
"title": "Import Data - Claude Code Tracker"
})
@dashboard_router.get("/dashboard/projects/{project_id}/timeline", response_class=HTMLResponse)
async def dashboard_project_timeline(request: Request, project_id: int, db: AsyncSession = Depends(get_db)):
"""Project timeline page."""
return templates.TemplateResponse("project_timeline.html", {
"request": request,
"title": f"Timeline - Project {project_id}",
"project_id": project_id
})
@dashboard_router.get("/dashboard/projects/{project_id}/stats", response_class=HTMLResponse)
async def dashboard_project_stats(request: Request, project_id: int, db: AsyncSession = Depends(get_db)):
"""Project statistics page."""
return templates.TemplateResponse("project_stats.html", {
"request": request,
"title": f"Statistics - Project {project_id}",
"project_id": project_id
})
@dashboard_router.get("/dashboard/docs", response_class=HTMLResponse)
async def dashboard_docs(request: Request, db: AsyncSession = Depends(get_db)):
"""Documentation overview page."""
return templates.TemplateResponse("docs/index.html", {
"request": request,
"title": "Documentation - Claude Code Tracker"
})
@dashboard_router.get("/dashboard/docs/{section}", response_class=HTMLResponse)
async def dashboard_docs_section(request: Request, section: str, db: AsyncSession = Depends(get_db)):
"""Documentation section pages."""
# Map section names to templates and titles
sections = {
"getting-started": {
"template": "docs/getting-started.html",
"title": "Getting Started - Claude Code Tracker"
},
"hook-setup": {
"template": "docs/hook-setup.html",
"title": "Hook Setup Guide - Claude Code Tracker"
},
"api-reference": {
"template": "docs/api-reference.html",
"title": "API Reference - Claude Code Tracker"
},
"faq": {
"template": "docs/faq.html",
"title": "FAQ - Claude Code Tracker"
}
}
if section not in sections:
from fastapi import HTTPException
raise HTTPException(status_code=404, detail=f"Documentation section '{section}' not found")
section_info = sections[section]
return templates.TemplateResponse(section_info["template"], {
"request": request,
"title": section_info["title"],
"section": section
})