From b523d586998266d010c88fda2a4194bf0a373c83 Mon Sep 17 00:00:00 2001 From: Jaret Burkett Date: Tue, 14 Oct 2025 14:13:37 -0600 Subject: [PATCH] Added ability to clone an existing job in the ui --- ui/src/app/jobs/new/page.tsx | 18 ++++++++++++++++++ ui/src/components/JobActionBar.tsx | 10 ++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ui/src/app/jobs/new/page.tsx b/ui/src/app/jobs/new/page.tsx index b57495d8..9cce40fa 100644 --- a/ui/src/app/jobs/new/page.tsx +++ b/ui/src/app/jobs/new/page.tsx @@ -26,6 +26,7 @@ export default function TrainingForm() { const router = useRouter(); const searchParams = useSearchParams(); const runId = searchParams.get('id'); + const cloneId = searchParams.get('cloneId'); const [gpuIDs, setGpuIDs] = useState(null); const { settings, isSettingsLoaded } = useSettings(); const { gpuList, isGPUInfoLoaded } = useGPUInfo(); @@ -54,6 +55,23 @@ export default function TrainingForm() { } }, [datasets, settings, isSettingsLoaded, datasetFetchStatus]); + // clone existing job + useEffect(() => { + if (cloneId) { + apiClient + .get(`/api/jobs?id=${cloneId}`) + .then(res => res.data) + .then(data => { + console.log('Clone Training:', data); + setGpuIDs(data.gpu_ids); + const newJobConfig = migrateJobConfig(JSON.parse(data.job_config)); + newJobConfig.config.name = `${newJobConfig.config.name}_copy`; + setJobConfig(newJobConfig); + }) + .catch(error => console.error('Error fetching training:', error)); + } + }, [cloneId]); + useEffect(() => { if (runId) { apiClient diff --git a/ui/src/components/JobActionBar.tsx b/ui/src/components/JobActionBar.tsx index 8ea3611b..7917459c 100644 --- a/ui/src/components/JobActionBar.tsx +++ b/ui/src/components/JobActionBar.tsx @@ -6,6 +6,7 @@ import { Job } from '@prisma/client'; import { startJob, stopJob, deleteJob, getAvaliableJobActions, markJobAsStopped } from '@/utils/jobs'; import { startQueue } from '@/utils/queue'; import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'; +import { redirect } from 'next/navigation'; interface JobActionBarProps { job: Job; @@ -121,10 +122,15 @@ export default function JobActionBar({ - + + + + Clone Job + +
{ let message = `Are you sure you want to mark this job as stopped? This will set the job status to 'stopped' if the status is hung. Only do this if you are 100% sure the job is stopped. This will NOT stop the job.`; openConfirm({