Commit 5bed3e6c authored by Admin's avatar Admin

fix: activity endpoint returns flat array instead of paginated object

Frontend calls (g ?? []).slice(0,10) on activity data, which crashes
when API returns {total, offset, limit, items} instead of ActivityEvent[].
Changed response_model from PaginatedResponse to List[ActivityLogResponse].
Also fixed .mcp.json Playwright package name.

Verified via Playwright MCP: 0 console errors on dashboard.
parent b5c29abf
......@@ -2,11 +2,10 @@
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@modelcontextprotocol/server-playwright"]
},
"dbeaver": {
"command": "npx",
"args": ["-y", "mcp-remote@latest", "https://mcp.dbeaver.com"]
"args": ["-y", "@playwright/mcp@latest", "--extension"],
"env": {
"PLAYWRIGHT_MCP_EXTENSION_TOKEN": "2xXCq7qcNlRaJrkvhuVKPvqSYb6uSTASU8NiayuDu0U"
}
},
"codegraph": {
"command": "npx",
......
......@@ -16,19 +16,20 @@ from models import ActivityLog
router = APIRouter(prefix="/activity", tags=["activity"])
@router.get("", response_model=PaginatedResponse)
@router.get("", response_model=List[ActivityLogResponse])
async def list_activity(
company_id: str = Query(..., description="Company ID"),
resource_type: Optional[str] = Query(None, description="Filter by resource type"),
actor_type: Optional[str] = Query(None, description="Filter by actor type"),
actor_id: Optional[str] = Query(None, description="Filter by actor ID"),
action: Optional[str] = Query(None, description="Filter by action"),
pagination: PaginationParams = Depends(),
limit: int = Query(50, ge=1, le=500, description="Max items"),
offset: int = Query(0, ge=0, description="Offset"),
scope: CompanyScope = Depends(require_company_scope),
db: AsyncSession = Depends(get_db_session)
):
"""List activity log."""
stmt = select(ActivityLog, func.count("*").over().label("total")).where(
"""List activity log. Returns flat array for frontend compatibility."""
stmt = select(ActivityLog).where(
ActivityLog.company_id == company_id
)
if resource_type:
......@@ -40,19 +41,9 @@ async def list_activity(
if action:
stmt = stmt.where(ActivityLog.action == action)
stmt = stmt.order_by(ActivityLog.occurred_at.desc()).offset(pagination.offset).limit(pagination.limit)
stmt = stmt.order_by(ActivityLog.occurred_at.desc()).offset(offset).limit(limit)
result = await db.execute(stmt)
rows = result.fetchall()
rows = result.scalars().all()
if not rows:
return {"total": 0, "offset": pagination.offset, "limit": pagination.limit, "items": []}
return [ActivityLogResponse.model_validate(row) for row in rows]
total = rows[0].total
activities = [ActivityLogResponse.model_validate(row._mapping["ActivityLog"]) for row in rows]
return {
"total": total,
"offset": pagination.offset,
"limit": pagination.limit,
"items": activities,
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment