import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { formatDistanceToNow } from 'date-fns'; import { X, CheckCircle, XCircle, Clock, AlertCircle, Play, Pause, HelpCircle, Ban, Timer, GitBranch, User, ExternalLink } from 'lucide-react'; import { WorkflowRun } from '../types/github'; import { ApiService } from '../services/api'; interface WorkflowRunsModalProps { isOpen: boolean; onClose: () => void; repository: { owner: string; name: string; } | null; } const getStatusIcon = (status: string, conclusion: string | null) => { switch (status) { case 'in_progress': return ; case 'queued': case 'requested': case 'pending': return ; case 'waiting': return ; case 'completed': switch (conclusion) { case 'success': return ; case 'failure': return ; case 'cancelled': return ; case 'action_required': return ; case 'neutral': return ; case 'skipped': return ; case 'stale': return ; case 'timed_out': return ; default: return ; } default: return ; } }; const getStatusText = (status: string, conclusion: string | null) => { if (status === 'completed' && conclusion) { return conclusion.charAt(0).toUpperCase() + conclusion.slice(1); } return status.charAt(0).toUpperCase() + status.slice(1); }; export const WorkflowRunsModal: React.FC = ({ isOpen, onClose, repository }) => { const [runs, setRuns] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const apiService = useMemo(() => new ApiService(), []); const handleBackdropClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget) { onClose(); } }; const fetchWorkflowRuns = useCallback(async () => { if (!repository) return; setLoading(true); setError(null); try { const response = await apiService.getRepositoryWorkflowRuns(repository.owner, repository.name); setRuns(response); } catch (error) { console.error('Error fetching workflow runs:', error); setError('Failed to fetch workflow runs'); } finally { setLoading(false); } }, [repository, apiService]); useEffect(() => { if (isOpen && repository) { fetchWorkflowRuns(); } }, [isOpen, repository, fetchWorkflowRuns]); if (!isOpen) return null; return ( {repository?.owner}/{repository?.name} Recent workflow runs {loading ? ( ) : error ? ( {error} ) : runs.length === 0 ? ( No workflow runs found ) : ( {runs.map((run) => ( {getStatusIcon(run.status, run.conclusion)} {run.display_title} {getStatusText(run.status, run.conclusion)} • #{run.run_number} Branch: {run.head_branch} Author: {run.actor.login} Commit: {run.head_commit && ( <> {run.head_commit.id.substring(0, 7)} {run.head_commit.message} > )} {formatDistanceToNow(new Date(run.created_at), { addSuffix: true })} ))} )} ); };
Recent workflow runs
{error}
No workflow runs found
{getStatusText(run.status, run.conclusion)} • #{run.run_number}
Commit: