Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 4,012 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 |
import Link from 'next/link';
import { Eye, Trash2, Pen, Play, Pause, ExternalLink, Upload } from 'lucide-react';
import { Button } from '@headlessui/react';
import { openConfirm } from '@/components/ConfirmModal';
import { startJob, stopJob, deleteJob, getAvaliableJobActions } from '@/utils/jobs';
import { JobConfig, JobRecord } from '@/types';
interface JobActionBarProps {
job: JobRecord;
onRefresh?: () => void;
afterDelete?: () => void;
hideView?: boolean;
className?: string;
}
export default function JobActionBar({ job, onRefresh, afterDelete, className, hideView }: JobActionBarProps) {
const { canStart, canStop, canDelete, canEdit } = getAvaliableJobActions(job);
// Check if this is an HF Job and extract monitoring URL
let jobConfig: JobConfig | null = null;
let hfJobUrl: string | null = null;
let isHFJob = false;
let hfJobSubmitted = false;
try {
jobConfig = JSON.parse(job.job_config);
isHFJob = jobConfig?.is_hf_job || false;
hfJobSubmitted = !!jobConfig?.hf_job_id;
hfJobUrl = jobConfig?.hf_job_url;
} catch (e) {
// Ignore parsing errors
}
if (!afterDelete) afterDelete = onRefresh;
return (
<div className={`${className}`}>
{isHFJob && !hfJobSubmitted && (
<Link
href={`/jobs/new?id=${job.id}`}
className="ml-2 text-yellow-400 hover:text-yellow-300 inline-block"
title="Submit to HF Jobs"
>
<Upload size={16} />
</Link>
)}
{canStart && !isHFJob && (
<Button
onClick={async () => {
if (!canStart) return;
await startJob(job.id);
if (onRefresh) onRefresh();
}}
className={`ml-2 opacity-100`}
>
<Play />
</Button>
)}
{canStop && !isHFJob && (
<Button
onClick={() => {
if (!canStop) return;
openConfirm({
title: 'Stop Job',
message: `Are you sure you want to stop the job "${job.name}"? You CAN resume later.`,
type: 'info',
confirmText: 'Stop',
onConfirm: async () => {
await stopJob(job.id);
if (onRefresh) onRefresh();
},
});
}}
className={`ml-2 opacity-100`}
>
<Pause />
</Button>
)}
{!hideView && (
<Link href={`/jobs/${job.id}`} className="ml-2 text-gray-200 hover:text-gray-100 inline-block">
<Eye />
</Link>
)}
{hfJobUrl && (
<a
href={hfJobUrl}
target="_blank"
rel="noopener noreferrer"
className="ml-2 text-blue-400 hover:text-blue-300 inline-block"
title="Monitor on HF Jobs"
>
<ExternalLink size={16} />
</a>
)}
{canEdit && (
<Link href={`/jobs/new?id=${job.id}`} className="ml-2 hover:text-gray-100 inline-block">
<Pen />
</Link>
)}
<Button
onClick={() => {
let message = `Are you sure you want to delete the job "${job.name}"? This will also permanently remove it from your disk.`;
if (job.status === 'running') {
message += ' WARNING: The job is currently running. You should stop it first if you can.';
}
openConfirm({
title: 'Delete Job',
message: message,
type: 'warning',
confirmText: 'Delete',
onConfirm: async () => {
if (job.status === 'running') {
try {
await stopJob(job.id);
} catch (e) {
console.error('Error stopping job before deleting:', e);
}
}
await deleteJob(job.id);
if (afterDelete) afterDelete();
},
});
}}
className={`ml-2 opacity-100`}
>
<Trash2 />
</Button>
</div>
);
}
|