Moved the job action bar to a shred component

This commit is contained in:
Jaret Burkett
2025-02-22 12:20:14 -07:00
parent a7a9c11d9e
commit ed84c19205
4 changed files with 110 additions and 95 deletions

View File

@@ -9,6 +9,8 @@ import { startJob, stopJob } from '@/utils/jobs';
import SampleImages from '@/components/SampleImages';
import JobOverview from '@/components/JobOverview';
import { JobConfig } from '@/types';
import { redirect } from 'next/navigation';
import JobActionBar from '@/components/JobActionBar';
type PageKey = 'overview' | 'samples';
@@ -28,21 +30,12 @@ export default function JobPage({ params }: { params: { jobID: string } }) {
const { job, status, refreshJob } = useJob(jobID, 5000);
const [pageKey, setPageKey] = useState<PageKey>('overview');
const numSamples = useMemo(() => {
if (job?.job_config) {
const jobConfig = JSON.parse(job.job_config) as JobConfig;
const sampleConfig = jobConfig.config.process[0].sample;
return sampleConfig.prompts.length;
}
return 10;
}, [job]);
return (
<>
{/* Fixed top bar */}
<TopBar>
<div>
<Button className="text-gray-500 dark:text-gray-300 px-3 mt-1" onClick={() => history.back()}>
<Button className="text-gray-500 dark:text-gray-300 px-3 mt-1" onClick={() => redirect('/jobs')}>
<FaChevronLeft />
</Button>
</div>
@@ -50,27 +43,15 @@ export default function JobPage({ params }: { params: { jobID: string } }) {
<h1 className="text-lg">Job: {job?.name}</h1>
</div>
<div className="flex-1"></div>
{job?.status === 'running' && (
<Button
onClick={async () => {
await stopJob(jobID);
refreshJob();
{job && (
<JobActionBar
job={job}
onRefresh={refreshJob}
hideView
afterDelete={() => {
redirect('/jobs');
}}
className="bg-red-500 text-white px-4 py-1 rounded-sm"
>
Stop
</Button>
)}
{(job?.status === 'stopped' || job?.status === 'error') && (
<Button
onClick={async () => {
await startJob(jobID);
refreshJob();
}}
className="bg-green-800 text-white px-4 py-1 rounded-sm"
>
Start
</Button>
/>
)}
</TopBar>
<MainContent className="pt-24">

View File

@@ -0,0 +1,87 @@
import Link from 'next/link';
import { Eye, Trash2, Pen, Play, Pause } from 'lucide-react';
import { Button } from '@headlessui/react';
import { openConfirm } from '@/components/ConfirmModal';
import { Job } from '@prisma/client';
import { startJob, stopJob, deleteJob, getAvaliableJobActions } from '@/utils/jobs';
interface JobActionBarProps {
job: Job;
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);
if (!afterDelete) afterDelete = onRefresh;
return (
<div className={`${className}`}>
{canStart && (
<Button
onClick={async () => {
if (!canStart) return;
await startJob(job.id);
if (onRefresh) onRefresh();
}}
className={`ml-2 opacity-100`}
>
<Play />
</Button>
)}
{canStop && (
<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>
)}
{canEdit && (
<Link href={`/jobs/new?id=${job.id}`} className="ml-2 hover:text-gray-100 inline-block">
<Pen />
</Link>
)}
{canDelete && (
<Button
onClick={() => {
if (!canDelete) return;
openConfirm({
title: 'Delete Job',
message: `Are you sure you want to delete the job "${job.name}"? This will also permanently remove it from your disk.`,
type: 'warning',
confirmText: 'Delete',
onConfirm: async () => {
await deleteJob(job.id);
if (afterDelete) afterDelete();
},
});
}}
className={`ml-2 opacity-100`}
>
<Trash2 />
</Button>
)}
</div>
);
}

View File

@@ -6,6 +6,7 @@ import { Eye, Trash2, Pen, Play, Pause } from 'lucide-react';
import { Button } from '@headlessui/react';
import { openConfirm } from '@/components/ConfirmModal';
import { startJob, stopJob, deleteJob, getAvaliableJobActions } from '@/utils/jobs';
import JobActionBar from './JobActionBar';
interface JobsTableProps {}
@@ -71,71 +72,7 @@ export default function JobsTable(props: JobsTableProps) {
key: 'actions',
className: 'text-right',
render: row => {
const { canDelete, canEdit, canStop, canStart } = getAvaliableJobActions(row);
return (
<div>
{canStart && (
<Button
onClick={async () => {
if (!canStart) return;
await startJob(row.id);
refreshJobs();
}}
className={`ml-2 opacity-100`}
>
<Play />
</Button>
)}
{canStop && (
<Button
onClick={() => {
if (!canStop) return;
openConfirm({
title: 'Stop Job',
message: `Are you sure you want to stop the job "${row.name}"? You CAN resume later.`,
type: 'info',
confirmText: 'Stop',
onConfirm: async () => {
await stopJob(row.id);
refreshJobs();
},
});
}}
className={`ml-2 opacity-100`}
>
<Pause />
</Button>
)}
<Link href={`/jobs/${row.id}`} className="ml-2 text-gray-200 hover:text-gray-100 inline-block">
<Eye />
</Link>
{canEdit && (
<Link href={`/jobs/new?id=${row.id}`} className="ml-2 hover:text-gray-100 inline-block">
<Pen />
</Link>
)}
{canDelete && (
<Button
onClick={() => {
if (!canDelete) return;
openConfirm({
title: 'Delete Job',
message: `Are you sure you want to delete the job "${row.name}"? This will also permanently remove it from your disk.`,
type: 'warning',
confirmText: 'Delete',
onConfirm: async () => {
await deleteJob(row.id);
refreshJobs();
},
});
}}
className={`ml-2 opacity-100`}
>
<Trash2 />
</Button>
)}
</div>
);
return <JobActionBar job={row} onRefresh={refreshJobs} />;
},
},
];

View File

@@ -63,3 +63,13 @@ export const getAvaliableJobActions = (job: Job) => {
}
return { canDelete, canEdit, canStop, canStart };
};
export const getNumberOfSamples = (job: Job) => {
const jobConfig = getJobConfig(job);
return jobConfig.config.process[0].sample?.prompts?.length || 0;
}
export const getTotalSteps = (job: Job) => {
const jobConfig = getJobConfig(job);
return jobConfig.config.process[0].train.steps;
}