diff --git a/apps/server/src/routes/projects/index.ts b/apps/server/src/routes/projects/index.ts index df0b558d..24ecef14 100644 --- a/apps/server/src/routes/projects/index.ts +++ b/apps/server/src/routes/projects/index.ts @@ -3,7 +3,7 @@ */ import { Router } from 'express'; -import { FeatureLoader } from '../../services/feature-loader.js'; +import type { FeatureLoader } from '../../services/feature-loader.js'; import type { AutoModeService } from '../../services/auto-mode-service.js'; import type { SettingsService } from '../../services/settings-service.js'; import type { NotificationService } from '../../services/notification-service.js'; diff --git a/apps/server/src/routes/projects/routes/overview.ts b/apps/server/src/routes/projects/routes/overview.ts index 18f6c8b0..dfbbd206 100644 --- a/apps/server/src/routes/projects/routes/overview.ts +++ b/apps/server/src/routes/projects/routes/overview.ts @@ -188,6 +188,7 @@ export function createOverviewHandler( unreadNotificationCount, }; } catch (error) { + logError(error, `Failed to load project status: ${projectRef.name}`); // Return a minimal status for projects that fail to load return { projectId: projectRef.id, diff --git a/apps/ui/src/components/views/dashboard-view.tsx b/apps/ui/src/components/views/dashboard-view.tsx index 842ba251..a8ca953f 100644 --- a/apps/ui/src/components/views/dashboard-view.tsx +++ b/apps/ui/src/components/views/dashboard-view.tsx @@ -579,6 +579,7 @@ export function DashboardView() { size="icon" onClick={() => navigate({ to: '/overview' })} title="Projects Overview" + data-testid="projects-overview-button-mobile" > diff --git a/apps/ui/src/components/views/overview-view.tsx b/apps/ui/src/components/views/overview-view.tsx index 68ae60f5..6a40ed0d 100644 --- a/apps/ui/src/components/views/overview-view.tsx +++ b/apps/ui/src/components/views/overview-view.tsx @@ -501,7 +501,12 @@ export function OverviewView() { {/* Footer timestamp */}
- Last updated: {new Date(overview.generatedAt).toLocaleTimeString()} + Last updated:{' '} + {new Date(overview.generatedAt).toLocaleTimeString(undefined, { + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + })}
)} diff --git a/apps/ui/src/components/views/overview/project-status-card.tsx b/apps/ui/src/components/views/overview/project-status-card.tsx index 490d880b..a2f2565c 100644 --- a/apps/ui/src/components/views/overview/project-status-card.tsx +++ b/apps/ui/src/components/views/overview/project-status-card.tsx @@ -87,8 +87,17 @@ export function ProjectStatusCard({ project, onProjectClick }: ProjectStatusCard } }, [project, onProjectClick, upsertAndSetCurrentProject, navigate]); + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + handleClick(); + } + }; + return (
diff --git a/apps/ui/src/components/views/overview/recent-activity-feed.tsx b/apps/ui/src/components/views/overview/recent-activity-feed.tsx index 0f797a1c..9eb80189 100644 --- a/apps/ui/src/components/views/overview/recent-activity-feed.tsx +++ b/apps/ui/src/components/views/overview/recent-activity-feed.tsx @@ -120,16 +120,19 @@ export function RecentActivityFeed({ activities, maxItems = 10 }: RecentActivity const handleActivityClick = useCallback( async (activity: RecentActivity) => { try { - const initResult = await initializeProject( - // We need to find the project path - use projectId as workaround - // In real implementation, this would look up the path from projects list - activity.projectId - ); - - // Navigate to the project - const projectPath = activity.projectId; + // Get project path from the activity (projectId is actually the path in our data model) + const projectPath = activity.projectPath || activity.projectId; const projectName = activity.projectName; + const initResult = await initializeProject(projectPath); + + if (!initResult.success) { + toast.error('Failed to initialize project', { + description: initResult.error || 'Unknown error', + }); + return; + } + upsertAndSetCurrentProject(projectPath, projectName); if (activity.featureId) { @@ -147,6 +150,16 @@ export function RecentActivityFeed({ activities, maxItems = 10 }: RecentActivity [navigate, upsertAndSetCurrentProject] ); + const handleActivityKeyDown = useCallback( + (e: React.KeyboardEvent, activity: RecentActivity) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + handleActivityClick(activity); + } + }, + [handleActivityClick] + ); + if (displayActivities.length === 0) { return (
@@ -166,8 +179,12 @@ export function RecentActivityFeed({ activities, maxItems = 10 }: RecentActivity return (
handleActivityClick(activity)} + onKeyDown={(e) => handleActivityKeyDown(e, activity)} + aria-label={`${config.label}: ${activity.featureName || activity.message} in ${activity.projectName}`} data-testid={`activity-item-${activity.id}`} > {/* Icon */} diff --git a/apps/ui/src/components/views/overview/running-agents-panel.tsx b/apps/ui/src/components/views/overview/running-agents-panel.tsx index e2d9413c..9f61166c 100644 --- a/apps/ui/src/components/views/overview/running-agents-panel.tsx +++ b/apps/ui/src/components/views/overview/running-agents-panel.tsx @@ -11,7 +11,7 @@ import { initializeProject } from '@/lib/project-init'; import { toast } from 'sonner'; import { cn } from '@/lib/utils'; import type { ProjectStatus } from '@automaker/types'; -import { Bot, Activity, Folder, ArrowRight } from 'lucide-react'; +import { Bot, Activity, GitBranch, ArrowRight } from 'lucide-react'; import { Button } from '@/components/ui/button'; interface RunningAgentsPanelProps { @@ -65,6 +65,16 @@ export function RunningAgentsPanel({ projects }: RunningAgentsPanelProps) { [navigate, upsertAndSetCurrentProject] ); + const handleAgentKeyDown = useCallback( + (e: React.KeyboardEvent, agent: RunningAgentInfo) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + handleAgentClick(agent); + } + }, + [handleAgentClick] + ); + if (runningAgents.length === 0) { return (
@@ -80,8 +90,12 @@ export function RunningAgentsPanel({ projects }: RunningAgentsPanelProps) { {runningAgents.map((agent) => (
handleAgentClick(agent)} + onKeyDown={(e) => handleAgentKeyDown(e, agent)} + aria-label={`View running agent for ${agent.projectName}`} data-testid={`running-agent-${agent.projectId}`} > {/* Animated icon */} @@ -111,7 +125,7 @@ export function RunningAgentsPanel({ projects }: RunningAgentsPanelProps) { )} {agent.activeBranch && ( - + {agent.activeBranch} )} diff --git a/apps/ui/src/hooks/use-multi-project-status.ts b/apps/ui/src/hooks/use-multi-project-status.ts index ab377795..2282ec7e 100644 --- a/apps/ui/src/hooks/use-multi-project-status.ts +++ b/apps/ui/src/hooks/use-multi-project-status.ts @@ -64,7 +64,7 @@ async function fetchProjectsOverview(): Promise { const data = await response.json(); if (!data.success) { - throw new Error(data.error?.message || 'Failed to fetch project overview'); + throw new Error(data.error || 'Failed to fetch project overview'); } return {