@@ -8,7 +8,7 @@ import Typography from '@mui/joy/Typography';
88import Box from '@mui/joy/Box' ;
99import IconButton from '@mui/joy/IconButton' ;
1010import Button from '@mui/joy/Button' ;
11- import { useState } from 'react' ;
11+ import { useMemo , useState } from 'react' ;
1212import {
1313 RectangleVerticalIcon ,
1414 Edit2 ,
@@ -19,71 +19,58 @@ import {
1919
2020import { useExperimentInfo } from 'renderer/lib/ExperimentInfoContext' ;
2121import TaskModal from './TaskModal' ;
22- import TaskGallery from './TaskGallery' ;
22+ import * as chatAPI from 'renderer/lib/transformerlab-api-sdk' ;
23+ import useSWR from 'swr' ;
24+ import Chip from '@mui/joy/Chip' ;
2325
2426export default function TaskLibrary ( { } ) {
2527 const { experimentInfo } = useExperimentInfo ( ) ;
2628
27- const initialTasks = [
28- {
29- id : 'finetune-llama-3' ,
30- title : 'Fine-tune LLaMA 3' ,
31- description :
32- 'Adapt LLaMA 3 to your domain by training on curated, domain-specific data to improve accuracy, tone, and task performance.' ,
33- } ,
34- {
35- id : 'nanochat' ,
36- title : "Train Karpathy's NanoChat" ,
37- description :
38- 'Build a compact conversational agent optimized for low-latency and on-device usage, suitable for simple chat, FAQ, and assistant workflows.' ,
39- } ,
40- {
41- id : 'finetune-unsloth' ,
42- title : 'Fine-tune with UnSloth' ,
43- description :
44- 'Use the UnSloth toolkit to fine-tune models efficiently with smart optimization and resource-aware schedules for faster iterations.' ,
45- } ,
46- {
47- id : 'finetune-gpt-oss' ,
48- title : 'Finetune OpenAI GPT-OSS' ,
49- description : 'Finetune OpenAIs GPT-OSS model.' ,
50- } ,
51- {
52- id : 'yolo-object-detection' ,
53- title : 'YOLO Object Detection Training' ,
54- description :
55- 'Train a YOLO-based detector to localize and classify objects in images, tuned for real-time performance and practical deployment.' ,
56- } ,
57- ] ;
58-
59- const [ tasks , setTasks ] = useState ( initialTasks ) ;
29+ const { data : localTasksResp } = useSWR (
30+ chatAPI . getAPIFullPath ( 'tasks.getAll' ) ,
31+ chatAPI . fetcher
32+ ) ;
33+ const { data : galleryResp } = useSWR (
34+ chatAPI . getAPIFullPath ( 'tasks.gallery' ) ,
35+ chatAPI . fetcher
36+ ) ;
37+
38+ const tasks = useMemo ( ( ) => {
39+ const local = Array . isArray ( localTasksResp ) ? localTasksResp : [ ] ;
40+ const gallery = galleryResp ?. data ?? [ ] ;
41+ const galleryMapped = gallery . map ( ( g ) => ( {
42+ id : `gallery:${ g . subdir || g . id || g . name } ` ,
43+ title : g . name || g . title || g . task_name || 'Task' ,
44+ description : g . description || '' ,
45+ _isGallery : true ,
46+ _subdir : g . subdir ,
47+ } ) ) ;
48+ return [ ...galleryMapped , ...local ] ;
49+ } , [ localTasksResp , galleryResp ] ) ;
6050
6151 // modal state to show TaskModal when creating/viewing a task
6252 const [ modalOpen , setModalOpen ] = useState ( false ) ;
6353 const [ modalTask , setModalTask ] = useState < any | null > ( null ) ;
64- // gallery state for importing examples
65- const [ galleryOpen , setGalleryOpen ] = useState ( false ) ;
6654
6755 const handleCloseModal = ( ) => {
6856 setModalOpen ( false ) ;
6957 setModalTask ( null ) ;
7058 } ;
7159
72- const handleImportExample = ( ) => {
73- // open the example gallery
74- setGalleryOpen ( true ) ;
75- } ;
76-
77- const handleSelectExample = ( example : any ) => {
78- // add selected example to tasks and close gallery
79- const newTask = {
80- id : example . id || `imported-${ Date . now ( ) } ` ,
81- title : example . title ,
82- description : example . description ,
83- yaml : example . yaml ,
84- } ;
85- setTasks ( ( prev ) => [ newTask , ...prev ] ) ;
86- setGalleryOpen ( false ) ;
60+ const handleImportFromGallery = async ( subdir : string ) => {
61+ const url = chatAPI . getAPIFullPath ( 'tasks.importFromGallery' ) ;
62+ const form = new URLSearchParams ( ) ;
63+ form . set ( 'subdir' , subdir ) ;
64+ // experimentId optional; if available in context add it
65+ if ( experimentInfo ?. id ) form . set ( 'experiment_id' , experimentInfo . id ) ;
66+ await fetch ( url , {
67+ method : 'POST' ,
68+ headers : {
69+ 'Content-Type' : 'application/x-www-form-urlencoded' ,
70+ } ,
71+ body : form . toString ( ) ,
72+ credentials : 'include' ,
73+ } ) ;
8774 } ;
8875
8976 const handleCreate = ( ) => {
@@ -131,15 +118,7 @@ export default function TaskLibrary({}) {
131118 >
132119 < h2 style = { { margin : 0 } } > Task Library</ h2 >
133120 < Box sx = { { display : 'flex' , gap : 1 } } >
134- < Button
135- size = "sm"
136- variant = "outlined"
137- onClick = { handleImportExample }
138- aria-label = "Import example"
139- startDecorator = { < FilePlus size = { 14 } /> }
140- >
141- Import Example
142- </ Button >
121+ { /* Removed Import Example button; gallery shows inline */ }
143122
144123 < Button
145124 size = "sm"
@@ -159,7 +138,7 @@ export default function TaskLibrary({}) {
159138 pt : 2 ,
160139 } }
161140 >
162- { tasks . map ( ( task ) => (
141+ { tasks . map ( ( task : any ) => (
163142 < ListItem
164143 key = { task . id }
165144 sx = { {
@@ -175,10 +154,17 @@ export default function TaskLibrary({}) {
175154 </ ListItemDecorator >
176155
177156 < ListItemContent sx = { { minWidth : 0 } } >
178- < Typography fontWeight = "lg" > { task . title } </ Typography >
157+ < Typography fontWeight = "lg" > { task . title || task . name } </ Typography >
179158 < Typography level = "body2" textColor = "text.tertiary" >
180159 { task . description }
181160 </ Typography >
161+ { task . _isGallery && (
162+ < Box sx = { { mt : 0.5 } } >
163+ < Chip size = "sm" color = "primary" variant = "soft" >
164+ Gallery
165+ </ Chip >
166+ </ Box >
167+ ) }
182168 </ ListItemContent >
183169
184170 < Box
@@ -190,6 +176,7 @@ export default function TaskLibrary({}) {
190176 alignSelf : 'start' ,
191177 } }
192178 >
179+ { ! task . _isGallery && (
193180 < IconButton
194181 size = "sm"
195182 variant = "plain"
@@ -199,7 +186,9 @@ export default function TaskLibrary({}) {
199186 >
200187 < Edit2 size = { 16 } />
201188 </ IconButton >
189+ ) }
202190
191+ { ! task . _isGallery && (
203192 < IconButton
204193 size = "sm"
205194 variant = "plain"
@@ -209,6 +198,18 @@ export default function TaskLibrary({}) {
209198 >
210199 < Trash2 size = { 16 } />
211200 </ IconButton >
201+ ) }
202+
203+ { task . _isGallery && (
204+ < Button
205+ size = "sm"
206+ variant = "outlined"
207+ onClick = { ( ) => handleImportFromGallery ( task . _subdir || task . id . split ( ':' ) [ 1 ] ) }
208+ startDecorator = { < FilePlus size = { 12 } /> }
209+ >
210+ Import
211+ </ Button >
212+ ) }
212213 </ Box >
213214 </ ListItem >
214215 ) ) }
@@ -221,12 +222,7 @@ export default function TaskLibrary({}) {
221222 task = { modalTask }
222223 onSave = { handleSave }
223224 />
224- { /* Example gallery modal */ }
225- < TaskGallery
226- open = { galleryOpen }
227- onClose = { ( ) => setGalleryOpen ( false ) }
228- onSelect = { handleSelectExample }
229- />
225+ { /* Gallery modal removed; items shown inline in list */ }
230226 </ Sheet >
231227 ) ;
232228}
0 commit comments