1- import  React ,  {  useState ,  useEffect ,   useCallback  }  from  'react' ; 
1+ import  React ,  {  useState ,  useCallback  }  from  'react' ; 
22import  Sheet  from  '@mui/joy/Sheet' ; 
33
44import  {  Button ,  LinearProgress ,  Stack ,  Typography  }  from  '@mui/joy' ; 
55
66import  dayjs  from  'dayjs' ; 
77import  relativeTime  from  'dayjs/plugin/relativeTime' ; 
88import  {  PlusIcon  }  from  'lucide-react' ; 
9+ import  useSWR  from  'swr' ; 
910
1011import  *  as  chatAPI  from  'renderer/lib/transformerlab-api-sdk' ; 
1112import  {  useExperimentInfo  }  from  'renderer/lib/ExperimentInfoContext' ; 
13+ import  {  fetcher  }  from  'renderer/lib/transformerlab-api-sdk' ; 
1214import  TaskTemplateList  from  './TaskTemplateList' ; 
1315import  JobsList  from  './JobsList' ; 
1416import  NewTaskModal  from  './NewTaskModal' ; 
@@ -22,64 +24,54 @@ dayjs.extend(relativeTime);
2224export  default  function  Tasks ( )  { 
2325  const  [ modalOpen ,  setModalOpen ]  =  useState ( false ) ; 
2426  const  [ isSubmitting ,  setIsSubmitting ]  =  useState ( false ) ; 
25-   const  [ tasks ,  setTasks ]  =  useState ( [ ] ) ; 
26-   const  [ jobs ,  setJobs ]  =  useState ( [ ] ) ; 
27-   const  [ loading ,  setLoading ]  =  useState ( false ) ; 
27+   const  [ viewOutputFromJob ,  setViewOutputFromJob ]  =  useState ( - 1 ) ; 
2828  const  [ currentTensorboardForModal ,  setCurrentTensorboardForModal ]  = 
2929    useState ( - 1 ) ; 
30-   const  [ viewOutputFromJob ,  setViewOutputFromJob ]  =  useState ( - 1 ) ; 
30+   const  [ viewCheckpointsFromJob ,  setViewCheckpointsFromJob ]  =  useState ( - 1 ) ; 
31+   const  [ viewEvalImagesFromJob ,  setViewEvalImagesFromJob ]  =  useState ( - 1 ) ; 
32+   const  [ viewOutputFromSweepJob ,  setViewOutputFromSweepJob ]  =  useState ( false ) ; 
3133  const  {  experimentInfo }  =  useExperimentInfo ( ) ; 
3234
3335  const  handleOpen  =  ( )  =>  setModalOpen ( true ) ; 
3436  const  handleClose  =  ( )  =>  setModalOpen ( false ) ; 
3537
36-   const  fetchTasks  =  async  ( )  =>  { 
37-     if  ( ! experimentInfo ?. id )  return ; 
38- 
39-     try  { 
40-       const  response  =  await  chatAPI . authenticatedFetch ( 
41-         chatAPI . Endpoints . Tasks . List ( ) , 
42-       ) ; 
43-       const  data  =  await  response . json ( ) ; 
44- 
45-       // Filter for remote tasks in this experiment only 
46-       const  remoteTasks  =  data . filter ( 
47-         ( task : any )  => 
48-           task . remote_task  ===  true  &&  task . experiment_id  ===  experimentInfo . id , 
49-       ) ; 
50-       setTasks ( remoteTasks ) ; 
51-     }  catch  ( error )  { 
52-       // eslint-disable-next-line no-console 
53-       console . error ( 'Error fetching tasks:' ,  error ) ; 
54-     } 
55-   } ; 
56- 
57-   const  fetchJobs  =  async  ( )  =>  { 
58-     if  ( ! experimentInfo ?. id )  return ; 
38+   // Fetch tasks with useSWR 
39+   const  { 
40+     data : allTasks , 
41+     error : tasksError , 
42+     isLoading : tasksIsLoading , 
43+     mutate : tasksMutate , 
44+   }  =  useSWR ( 
45+     experimentInfo ?. id  ? chatAPI . Endpoints . Tasks . List ( )  : null , 
46+     fetcher , 
47+   ) ; 
5948
60-     try  { 
61-       const  response  =  await  chatAPI . authenticatedFetch ( 
62-         chatAPI . Endpoints . Jobs . GetJobsOfType ( experimentInfo . id ,  'REMOTE' ,  '' ) , 
63-       ) ; 
64-       const  data  =  await  response . json ( ) ; 
65-       setJobs ( data ) ; 
66-     }  catch  ( error )  { 
67-       // eslint-disable-next-line no-console 
68-       console . error ( 'Error fetching jobs:' ,  error ) ; 
69-     } 
70-   } ; 
49+   // Filter tasks for remote tasks in this experiment only 
50+   const  tasks  = 
51+     allTasks ?. filter ( 
52+       ( task : any )  => 
53+         task . remote_task  ===  true  &&  task . experiment_id  ===  experimentInfo ?. id , 
54+     )  ||  [ ] ; 
7155
72-   const  fetchData  =  useCallback ( async  ( )  =>  { 
73-     setLoading ( true ) ; 
74-     await  Promise . all ( [ fetchTasks ( ) ,  fetchJobs ( ) ] ) ; 
75-     setLoading ( false ) ; 
76-   } ,  [ experimentInfo ?. id ] ) ; 
56+   // Fetch jobs with automatic polling 
57+   const  { 
58+     data : jobs , 
59+     error : jobsError , 
60+     isLoading : jobsIsLoading , 
61+     mutate : jobsMutate , 
62+   }  =  useSWR ( 
63+     experimentInfo ?. id 
64+       ? chatAPI . Endpoints . Jobs . GetJobsOfType ( experimentInfo . id ,  'REMOTE' ,  '' ) 
65+       : null , 
66+     fetcher , 
67+     { 
68+       refreshInterval : 3000 ,  // Poll every 3 seconds for job status updates 
69+       revalidateOnFocus : false ,  // Don't refetch when window regains focus 
70+       revalidateOnReconnect : true ,  // Refetch when network reconnects 
71+     } , 
72+   ) ; 
7773
78-   useEffect ( ( )  =>  { 
79-     if  ( experimentInfo ?. id )  { 
80-       fetchData ( ) ; 
81-     } 
82-   } ,  [ experimentInfo ?. id ,  fetchData ] ) ; 
74+   const  loading  =  tasksIsLoading  ||  jobsIsLoading ; 
8375
8476  const  handleDeleteTask  =  async  ( taskId : string )  =>  { 
8577    if  ( ! experimentInfo ?. id )  return ; 
@@ -101,7 +93,7 @@ export default function Tasks() {
10193        // eslint-disable-next-line no-alert 
10294        alert ( 'Task deleted successfully!' ) ; 
10395        // Refresh the data to remove the deleted task 
104-         await  fetchData ( ) ; 
96+         await  tasksMutate ( ) ; 
10597      }  else  { 
10698        // eslint-disable-next-line no-alert 
10799        alert ( 'Failed to delete task. Please try again.' ) ; 
@@ -134,7 +126,7 @@ export default function Tasks() {
134126        // eslint-disable-next-line no-alert 
135127        alert ( 'Job deleted successfully!' ) ; 
136128        // Refresh the data to remove the deleted job 
137-         await  fetchData ( ) ; 
129+         await  jobsMutate ( ) ; 
138130      }  else  { 
139131        // eslint-disable-next-line no-alert 
140132        alert ( 'Failed to delete job. Please try again.' ) ; 
@@ -187,7 +179,7 @@ export default function Tasks() {
187179        alert ( 'Task launched successfully!' ) ; 
188180        setModalOpen ( false ) ; 
189181        // Refresh the data to show the new task and job 
190-         await  fetchData ( ) ; 
182+         await  Promise . all ( [ tasksMutate ( ) ,   jobsMutate ( ) ] ) ; 
191183      }  else  { 
192184        // eslint-disable-next-line no-alert 
193185        alert ( `Error: ${ result . message }  ) ; 
@@ -272,7 +264,7 @@ export default function Tasks() {
272264      </ Sheet > 
273265      < ViewOutputModalStreaming 
274266        jobId = { viewOutputFromJob } 
275-         setJobId = { ( jobId )  =>  setViewOutputFromJob ( jobId   as   number ) } 
267+         setJobId = { ( jobId :  number )  =>  setViewOutputFromJob ( jobId ) } 
276268      /> 
277269    </ Sheet > 
278270  ) ; 
0 commit comments