Spaces:
Paused
Paused
| 'use client'; | |
| import { useHFJobStatus } from '@/hooks/useHFJobStatus'; | |
| import { ExternalLink, RefreshCw } from 'lucide-react'; | |
| import { Button } from '@headlessui/react'; | |
| interface HFJobStatusProps { | |
| hfJobId: string; | |
| hfJobUrl?: string; | |
| hfJobNamespace?: string; | |
| } | |
| const extractNamespaceFromUrl = (url?: string) => { | |
| if (!url) { | |
| return undefined; | |
| } | |
| try { | |
| const match = url.match(/\/jobs\/([^\/]+)\//); | |
| return match?.[1]; | |
| } catch (error) { | |
| console.warn('Failed to derive HF job namespace from URL:', error); | |
| return undefined; | |
| } | |
| }; | |
| export default function HFJobStatus({ hfJobId, hfJobUrl, hfJobNamespace }: HFJobStatusProps) { | |
| const derivedNamespace = hfJobNamespace || extractNamespaceFromUrl(hfJobUrl); | |
| const { status, loading, error } = useHFJobStatus(hfJobId, derivedNamespace); | |
| if (error) { | |
| return ( | |
| <div className="flex items-center gap-2"> | |
| <span className="text-xs text-red-400">Status Error</span> | |
| {hfJobUrl && ( | |
| <a | |
| href={hfJobUrl} | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="text-blue-400 hover:text-blue-300" | |
| title="Check logs on HF Jobs" | |
| > | |
| <ExternalLink size={14} /> | |
| </a> | |
| )} | |
| </div> | |
| ); | |
| } | |
| if (loading && !status) { | |
| return ( | |
| <div className="flex items-center gap-2"> | |
| <RefreshCw size={14} className="animate-spin" /> | |
| <span className="text-xs text-gray-400">Checking...</span> | |
| </div> | |
| ); | |
| } | |
| if (!status) { | |
| return ( | |
| <div className="flex items-center gap-2"> | |
| <span className="text-xs text-gray-400">Unknown</span> | |
| {hfJobUrl && ( | |
| <a | |
| href={hfJobUrl} | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="text-blue-400 hover:text-blue-300" | |
| title="Check logs on HF Jobs" | |
| > | |
| <ExternalLink size={14} /> | |
| </a> | |
| )} | |
| </div> | |
| ); | |
| } | |
| const getStatusColor = (statusStage: string) => { | |
| switch (statusStage.toUpperCase()) { | |
| case 'RUNNING': | |
| return 'text-blue-400'; | |
| case 'COMPLETED': | |
| case 'SUCCESS': | |
| return 'text-green-400'; | |
| case 'FAILED': | |
| case 'ERROR': | |
| return 'text-red-400'; | |
| case 'PENDING': | |
| case 'QUEUED': | |
| return 'text-yellow-400'; | |
| case 'CANCELLED': | |
| case 'STOPPED': | |
| return 'text-gray-400'; | |
| default: | |
| return 'text-gray-400'; | |
| } | |
| }; | |
| const getStatusLabel = (statusStage: string) => { | |
| switch (statusStage.toUpperCase()) { | |
| case 'RUNNING': | |
| return 'Running'; | |
| case 'COMPLETED': | |
| return 'Completed'; | |
| case 'FAILED': | |
| return 'Failed'; | |
| case 'PENDING': | |
| return 'Pending'; | |
| case 'QUEUED': | |
| return 'Queued'; | |
| case 'CANCELLED': | |
| return 'Cancelled'; | |
| case 'STOPPED': | |
| return 'Stopped'; | |
| default: | |
| return statusStage; | |
| } | |
| }; | |
| return ( | |
| <div className="flex items-center gap-2"> | |
| <div className="flex items-center gap-1"> | |
| {loading && <RefreshCw size={12} className="animate-spin" />} | |
| <span className={`text-xs font-medium ${getStatusColor(status.status)}`}> | |
| {getStatusLabel(status.status)} | |
| </span> | |
| </div> | |
| {hfJobUrl && ( | |
| <a | |
| href={hfJobUrl} | |
| target="_blank" | |
| rel="noopener noreferrer" | |
| className="text-blue-400 hover:text-blue-300" | |
| title={`Check logs on HF Jobs (${status.flavor})`} | |
| > | |
| <ExternalLink size={14} /> | |
| </a> | |
| )} | |
| </div> | |
| ); | |
| } | |