Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 4,014 Bytes
f555806 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
import useJobsList from '@/hooks/useJobsList';
import Link from 'next/link';
import UniversalTable, { TableColumn } from '@/components/UniversalTable';
import { JobConfig, JobRecord } from '@/types';
import JobActionBar from './JobActionBar';
import HFJobStatus from './HFJobStatus';
interface JobsTableProps {
onlyActive?: boolean;
}
export default function JobsTable({ onlyActive = false }: JobsTableProps) {
const { jobs, status, refreshJobs } = useJobsList(onlyActive);
const isLoading = status === 'loading';
const columns: TableColumn[] = [
{
title: 'Name',
key: 'name',
render: (row: JobRecord) => {
const jobConfig: JobConfig = JSON.parse(row.job_config);
const isHFJob = jobConfig.is_hf_job;
return (
<div className="flex items-center gap-2">
<Link href={`/jobs/${row.id}`} className="font-medium whitespace-nowrap">
{row.name}
</Link>
{isHFJob && (
<span className="text-xs bg-blue-600 text-white px-2 py-1 rounded">
HF Cloud
</span>
)}
</div>
);
},
},
{
title: 'Steps',
key: 'steps',
render: (row: JobRecord) => {
const jobConfig: JobConfig = JSON.parse(row.job_config);
const isHFJob = jobConfig.is_hf_job;
if (isHFJob) {
return (
<span className="text-sm text-gray-400">
Cloud Training
</span>
);
}
const totalSteps = jobConfig.config.process[0].train.steps;
return (
<div className="flex items-center">
<span>
{row.step} / {totalSteps}
</span>
<div className="w-16 bg-gray-700 rounded-full h-1.5 ml-2">
<div
className="bg-blue-500 h-1.5 rounded-full"
style={{ width: `${(row.step / totalSteps) * 100}%` }}
></div>
</div>
</div>
);
},
},
{
title: 'GPU',
key: 'gpu_ids',
render: (row: JobRecord) => {
const jobConfig: JobConfig = JSON.parse(row.job_config);
const isHFJob = jobConfig.is_hf_job;
if (isHFJob) {
return (
<span className="text-sm">
{jobConfig.hardware || row.gpu_ids}
</span>
);
}
return <span>{row.gpu_ids}</span>;
},
},
{
title: 'Status',
key: 'status',
render: (row: JobRecord) => {
const jobConfig: JobConfig = JSON.parse(row.job_config);
const isHFJob = jobConfig.is_hf_job;
if (isHFJob) {
if (jobConfig.hf_job_id) {
// HF Job that has been submitted
return (
<HFJobStatus
hfJobId={jobConfig.hf_job_id}
hfJobUrl={jobConfig.hf_job_url}
/>
);
} else {
// HF Job that hasn't been submitted yet
return (
<span className="text-yellow-400">
Pending Submission
</span>
);
}
}
// Local job status
let statusClass = 'text-gray-400';
if (row.status === 'completed') statusClass = 'text-green-400';
if (row.status === 'failed') statusClass = 'text-red-400';
if (row.status === 'running') statusClass = 'text-blue-400';
return <span className={statusClass}>{row.status}</span>;
},
},
{
title: 'Info',
key: 'info',
className: 'truncate max-w-xs',
},
{
title: 'Actions',
key: 'actions',
className: 'text-right',
render: (row: JobRecord) => {
return <JobActionBar job={row} onRefresh={refreshJobs} />;
},
},
];
return <UniversalTable columns={columns} rows={jobs} isLoading={isLoading} onRefresh={refreshJobs} />;
}
|