fix: migrate UI to V2 API and fix admin dashboard
Backend fixes: - Fix markdown generation using correct 'markdown_content' key in tasks.py - Update admin service to return flat data structure matching frontend types - Add task_count and failed_tasks fields to user statistics - Fix top users endpoint to return complete user data Frontend fixes: - Migrate ResultsPage from V1 batch API to V2 task API with polling - Create TaskDetailPage component with markdown preview and download buttons - Refactor ExportPage to support multi-task selection using V2 download endpoints - Fix login infinite refresh loop with concurrency control flags - Create missing Checkbox UI component New features: - Add /tasks/:taskId route for task detail view - Implement multi-task batch export functionality - Add real-time task status polling (2s interval) OpenSpec: - Archive completed proposal 2025-11-17-fix-v2-api-ui-issues - Create result-export and task-management specifications 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -86,22 +86,16 @@ class AdminService:
|
||||
).count()
|
||||
|
||||
return {
|
||||
"users": {
|
||||
"total": total_users,
|
||||
"active": active_users,
|
||||
"active_30d": active_users_30d
|
||||
},
|
||||
"tasks": {
|
||||
"total": total_tasks,
|
||||
"by_status": tasks_by_status,
|
||||
"recent_7d": recent_tasks
|
||||
},
|
||||
"sessions": {
|
||||
"active": active_sessions
|
||||
},
|
||||
"activity": {
|
||||
"logins_7d": recent_logins,
|
||||
"tasks_7d": recent_tasks
|
||||
"total_users": total_users,
|
||||
"active_users": active_users,
|
||||
"total_tasks": total_tasks,
|
||||
"total_sessions": active_sessions,
|
||||
"recent_activity_count": recent_tasks,
|
||||
"task_stats": {
|
||||
"pending": tasks_by_status.get("pending", 0),
|
||||
"processing": tasks_by_status.get("processing", 0),
|
||||
"completed": tasks_by_status.get("completed", 0),
|
||||
"failed": tasks_by_status.get("failed", 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +136,14 @@ class AdminService:
|
||||
)
|
||||
).count()
|
||||
|
||||
# Count failed tasks
|
||||
failed_tasks = db.query(Task).filter(
|
||||
and_(
|
||||
Task.user_id == user.id,
|
||||
Task.status == TaskStatus.FAILED
|
||||
)
|
||||
).count()
|
||||
|
||||
# Count active sessions
|
||||
active_sessions = db.query(UserSession).filter(
|
||||
and_(
|
||||
@@ -152,8 +154,9 @@ class AdminService:
|
||||
|
||||
user_list.append({
|
||||
**user.to_dict(),
|
||||
"total_tasks": task_count,
|
||||
"task_count": task_count,
|
||||
"completed_tasks": completed_tasks,
|
||||
"failed_tasks": failed_tasks,
|
||||
"active_sessions": active_sessions,
|
||||
"is_admin": self.is_admin(user.email)
|
||||
})
|
||||
@@ -177,34 +180,34 @@ class AdminService:
|
||||
Returns:
|
||||
List of top users with counts
|
||||
"""
|
||||
if metric == "completed_tasks":
|
||||
# Top users by completed tasks
|
||||
results = db.query(
|
||||
User,
|
||||
func.count(Task.id).label("task_count")
|
||||
).join(Task).filter(
|
||||
Task.status == TaskStatus.COMPLETED
|
||||
).group_by(User.id).order_by(
|
||||
func.count(Task.id).desc()
|
||||
).limit(limit).all()
|
||||
else:
|
||||
# Top users by total tasks (default)
|
||||
results = db.query(
|
||||
User,
|
||||
func.count(Task.id).label("task_count")
|
||||
).join(Task).group_by(User.id).order_by(
|
||||
func.count(Task.id).desc()
|
||||
).limit(limit).all()
|
||||
# Get top users by total tasks
|
||||
results = db.query(
|
||||
User,
|
||||
func.count(Task.id).label("task_count")
|
||||
).join(Task).group_by(User.id).order_by(
|
||||
func.count(Task.id).desc()
|
||||
).limit(limit).all()
|
||||
|
||||
return [
|
||||
{
|
||||
# Build result list with both task_count and completed_tasks
|
||||
top_users = []
|
||||
for user, task_count in results:
|
||||
# Count completed tasks for this user
|
||||
completed_tasks = db.query(Task).filter(
|
||||
and_(
|
||||
Task.user_id == user.id,
|
||||
Task.status == TaskStatus.COMPLETED
|
||||
)
|
||||
).count()
|
||||
|
||||
top_users.append({
|
||||
"user_id": user.id,
|
||||
"email": user.email,
|
||||
"display_name": user.display_name,
|
||||
"count": count
|
||||
}
|
||||
for user, count in results
|
||||
]
|
||||
"task_count": task_count,
|
||||
"completed_tasks": completed_tasks
|
||||
})
|
||||
|
||||
return top_users
|
||||
|
||||
|
||||
# Singleton instance
|
||||
|
||||
Reference in New Issue
Block a user