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>
  );
}