From 77461a699239ec039d6cdd9c1670870bc117c6b0 Mon Sep 17 00:00:00 2001
From: ali asaria <aliasaria@users.noreply.github.com>
Date: Mon, 3 Feb 2025 15:44:32 -0500
Subject: [PATCH] pull job progress out as separate component

---
 .../Experiment/Train/JobProgress.tsx          | 103 +++++++++++++++
 .../components/Experiment/Train/TrainLoRA.tsx | 124 +-----------------
 2 files changed, 105 insertions(+), 122 deletions(-)
 create mode 100644 src/renderer/components/Experiment/Train/JobProgress.tsx

diff --git a/src/renderer/components/Experiment/Train/JobProgress.tsx b/src/renderer/components/Experiment/Train/JobProgress.tsx
new file mode 100644
index 00000000..c65e6e65
--- /dev/null
+++ b/src/renderer/components/Experiment/Train/JobProgress.tsx
@@ -0,0 +1,103 @@
+import { Chip, IconButton, LinearProgress, Stack, Typography } from '@mui/joy';
+import { StopCircleIcon } from 'lucide-react';
+import dayjs from 'dayjs';
+import relativeTime from 'dayjs/plugin/relativeTime';
+import { jobChipColor } from 'renderer/lib/utils';
+dayjs.extend(relativeTime);
+var duration = require('dayjs/plugin/duration');
+dayjs.extend(duration);
+
+export default function JobProgress({ job }) {
+  return (
+    <Stack>
+      {job?.status == 'RUNNING' ? (
+        <>
+          <Stack direction={'row'} alignItems="center" gap={1}>
+            <Chip
+              sx={{
+                backgroundColor: jobChipColor(job.status),
+                color: 'var(--joy-palette-neutral-800)',
+              }}
+            >
+              {job.status}
+            </Chip>
+            {job.progress == '-1'
+              ? ''
+              : Number.parseFloat(job.progress).toFixed(1) + '%'}
+            <LinearProgress
+              determinate
+              value={job.progress}
+              sx={{ my: 1 }}
+            ></LinearProgress>
+            <IconButton
+              color="danger"
+              onClick={async () => {
+                confirm('Are you sure you want to stop this job?') &&
+                  (await fetch(chatAPI.Endpoints.Jobs.Stop(job.id)));
+              }}
+            >
+              <StopCircleIcon size="20px" />
+            </IconButton>
+          </Stack>
+          {job?.job_data?.start_time && (
+            <>Started: {dayjs(job?.job_data?.start_time).fromNow()}</>
+          )}
+        </>
+      ) : (
+        <Stack direction={'column'} justifyContent={'space-between'}>
+          <>
+            <Chip
+              sx={{
+                backgroundColor: jobChipColor(job.status),
+                color: 'var(--joy-palette-neutral-800)',
+              }}
+            >
+              {job.status}
+              {job.progress == '-1'
+                ? ''
+                : ' - ' + Number.parseFloat(job.progress).toFixed(1) + '%'}
+            </Chip>
+            {job?.job_data?.start_time && (
+              <>Started: {dayjs(job?.job_data?.start_time).fromNow()}</>
+            )}
+            <br />
+            {job?.job_data?.end_time && job?.job_data?.end_time && (
+              <>
+                Completed in:{' '}
+                {dayjs
+                  .duration(
+                    dayjs(job?.job_data?.end_time).diff(
+                      dayjs(job?.job_data?.start_time)
+                    )
+                  )
+                  .humanize()}
+              </>
+            )}
+            <br />
+            {job?.status == 'COMPLETE' &&
+              (job?.job_data?.completion_status ? (
+                <>
+                  Final Training Status:{' '}
+                  {job?.job_data?.completion_status == 'success' ? (
+                    <Typography level="body-sm" color="success">
+                      Success: {job?.job_data?.completion_details}
+                    </Typography>
+                  ) : (
+                    <Typography level="body-sm" color="danger">
+                      Failure: {job?.job_data?.completion_details}
+                    </Typography>
+                  )}
+                </>
+              ) : (
+                /* If we don't have a status, assume it failed */
+                <Typography level="body-sm" color="neutral">
+                  No job completion status. Training may have failed. View
+                  output for details
+                </Typography>
+              ))}
+          </>
+        </Stack>
+      )}
+    </Stack>
+  );
+}
diff --git a/src/renderer/components/Experiment/Train/TrainLoRA.tsx b/src/renderer/components/Experiment/Train/TrainLoRA.tsx
index 66f645b1..83ff9d34 100644
--- a/src/renderer/components/Experiment/Train/TrainLoRA.tsx
+++ b/src/renderer/components/Experiment/Train/TrainLoRA.tsx
@@ -50,6 +50,7 @@ import ViewOutputModalStreaming from './ViewOutputModalStreaming';
 import CurrentDownloadBox from 'renderer/components/currentDownloadBox';
 import DownloadProgressBox from 'renderer/components/Shared/DownloadProgressBox';
 import { jobChipColor } from 'renderer/lib/utils';
+import JobProgress from './JobProgress';
 dayjs.extend(relativeTime);
 var duration = require('dayjs/plugin/duration');
 dayjs.extend(duration);
@@ -451,128 +452,7 @@ export default function TrainLoRA({ experimentInfo }) {
                       </td>
                       <td>{formatJobConfig(job)}</td>
                       <td>
-                        <Stack>
-                          {job?.status == 'RUNNING' ? (
-                            <>
-                              <Stack
-                                direction={'row'}
-                                alignItems="center"
-                                gap={1}
-                              >
-                                <Chip
-                                  sx={{
-                                    backgroundColor: jobChipColor(job.status),
-                                    color: 'var(--joy-palette-neutral-800)',
-                                  }}
-                                >
-                                  {job.status}
-                                </Chip>
-                                {job.progress == '-1'
-                                  ? ''
-                                  : Number.parseFloat(job.progress).toFixed(1) +
-                                    '%'}
-                                <LinearProgress
-                                  determinate
-                                  value={job.progress}
-                                  sx={{ my: 1 }}
-                                ></LinearProgress>
-                                <IconButton
-                                  color="danger"
-                                  onClick={async () => {
-                                    confirm(
-                                      'Are you sure you want to stop this job?'
-                                    ) &&
-                                      (await fetch(
-                                        chatAPI.Endpoints.Jobs.Stop(job.id)
-                                      ));
-                                  }}
-                                >
-                                  <StopCircleIcon size="20px" />
-                                </IconButton>
-                              </Stack>
-                              {job?.job_data?.start_time && (
-                                <>
-                                  Started:{' '}
-                                  {dayjs(job?.job_data?.start_time).fromNow()}
-                                </>
-                              )}
-                            </>
-                          ) : (
-                            <Stack
-                              direction={'column'}
-                              justifyContent={'space-between'}
-                            >
-                              <>
-                                <Chip
-                                  sx={{
-                                    backgroundColor: jobChipColor(job.status),
-                                    color: 'var(--joy-palette-neutral-800)',
-                                  }}
-                                >
-                                  {job.status}
-                                  {job.progress == '-1'
-                                    ? ''
-                                    : ' - ' +
-                                      Number.parseFloat(job.progress).toFixed(
-                                        1
-                                      ) +
-                                      '%'}
-                                </Chip>
-                                {job?.job_data?.start_time && (
-                                  <>
-                                    Started:{' '}
-                                    {dayjs(job?.job_data?.start_time).fromNow()}
-                                  </>
-                                )}
-                                <br />
-                                {job?.job_data?.end_time &&
-                                  job?.job_data?.end_time && (
-                                    <>
-                                      Completed in:{' '}
-                                      {dayjs
-                                        .duration(
-                                          dayjs(job?.job_data?.end_time).diff(
-                                            dayjs(job?.job_data?.start_time)
-                                          )
-                                        )
-                                        .humanize()}
-                                    </>
-                                  )}
-                                <br />
-                                {job?.status == 'COMPLETE' &&
-                                  (job?.job_data?.completion_status ? (
-                                    <>
-                                      Final Training Status:{' '}
-                                      {job?.job_data?.completion_status ==
-                                      'success' ? (
-                                        <Typography
-                                          level="body-sm"
-                                          color="success"
-                                        >
-                                          Success:{' '}
-                                          {job?.job_data?.completion_details}
-                                        </Typography>
-                                      ) : (
-                                        <Typography
-                                          level="body-sm"
-                                          color="danger"
-                                        >
-                                          Failure:{' '}
-                                          {job?.job_data?.completion_details}
-                                        </Typography>
-                                      )}
-                                    </>
-                                  ) : (
-                                    /* If we don't have a status, assume it failed */
-                                    <Typography level="body-sm" color="neutral">
-                                      No job completion status. Training may
-                                      have failed. View output for details
-                                    </Typography>
-                                  ))}
-                              </>
-                            </Stack>
-                          )}
-                        </Stack>
+                        <JobProgress job={job} />
                       </td>
                       <td style={{}}>
                         <ButtonGroup sx={{ justifyContent: 'flex-end' }}>
-- 
GitLab