@@ -8,12 +8,31 @@ import FormControl from '@mui/joy/FormControl';
88import  FormLabel  from  '@mui/joy/FormLabel' ; 
99import  Input  from  '@mui/joy/Input' ; 
1010import  Textarea  from  '@mui/joy/Textarea' ; 
11- import  {  ModalClose ,  ModalDialog ,  Sheet ,  Stack ,  Typography  }  from  '@mui/joy' ; 
11+ import  { 
12+   FormHelperText , 
13+   ModalClose , 
14+   ModalDialog , 
15+   Sheet , 
16+   Stack , 
17+   Typography , 
18+ }  from  '@mui/joy' ; 
1219import  {  FolderIcon  }  from  'lucide-react' ; 
20+ import  {  Editor  }  from  '@monaco-editor/react' ; 
21+ import  fairyflossTheme  from  '../../Shared/fairyfloss.tmTheme.js' ; 
1322
1423import  *  as  chatAPI  from  'renderer/lib/transformerlab-api-sdk' ; 
1524import  {  useNotification  }  from  'renderer/components/Shared/NotificationSystem' ; 
1625import  {  SafeJSONParse  }  from  'renderer/components/Shared/SafeJSONParse' ; 
26+ import  {  useRef  }  from  'react' ; 
27+ 
28+ const  {  parseTmTheme }  =  require ( 'monaco-themes' ) ; 
29+ 
30+ function  setTheme ( editor : any ,  monaco : any )  { 
31+   const  themeData  =  parseTmTheme ( fairyflossTheme ) ; 
32+ 
33+   monaco . editor . defineTheme ( 'my-theme' ,  themeData ) ; 
34+   monaco . editor . setTheme ( 'my-theme' ) ; 
35+ } 
1736
1837type  EditTaskModalProps  =  { 
1938  open : boolean ; 
@@ -40,6 +59,9 @@ export default function EditTaskModal({
4059  const  [ setup ,  setSetup ]  =  React . useState ( '' ) ; 
4160  const  [ saving ,  setSaving ]  =  React . useState ( false ) ; 
4261
62+   const  setupEditorRef  =  useRef < any > ( null ) ; 
63+   const  commandEditorRef  =  useRef < any > ( null ) ; 
64+ 
4365  React . useEffect ( ( )  =>  { 
4466    if  ( ! task )  return ; 
4567    setTitle ( task . name  ||  '' ) ; 
@@ -54,23 +76,48 @@ export default function EditTaskModal({
5476    setSetup ( cfg . setup  !=  null  ? String ( cfg . setup )  : '' ) ; 
5577  } ,  [ task ] ) ; 
5678
79+   // Keep Monaco editors in sync if the state changes after mount 
80+   React . useEffect ( ( )  =>  { 
81+     if  ( 
82+       setupEditorRef . current  && 
83+       typeof  setupEditorRef . current . setValue  ===  'function' 
84+     )  { 
85+       setupEditorRef . current . setValue ( setup  ??  '' ) ; 
86+     } 
87+   } ,  [ setup ] ) ; 
88+ 
89+   React . useEffect ( ( )  =>  { 
90+     if  ( 
91+       commandEditorRef . current  && 
92+       typeof  commandEditorRef . current . setValue  ===  'function' 
93+     )  { 
94+       commandEditorRef . current . setValue ( command  ??  '' ) ; 
95+     } 
96+   } ,  [ command ] ) ; 
97+ 
5798  const  handleSubmit  =  async  ( e : React . FormEvent )  =>  { 
5899    e . preventDefault ( ) ; 
100+ 
101+     const  setupValue  = 
102+       setupEditorRef ?. current ?. getValue ?.( )  ??  ( setup  ||  undefined ) ; 
103+     const  commandValue  = 
104+       commandEditorRef ?. current ?. getValue ?.( )  ??  ( command  ||  undefined ) ; 
105+ 
59106    if  ( ! task )  return ; 
60-     if  ( ! command )  { 
107+     if  ( ! commandValue )  { 
61108      addNotification ( {  type : 'warning' ,  message : 'Command is required'  } ) ; 
62109      return ; 
63110    } 
64111    setSaving ( true ) ; 
65112    const  config  =  { 
66113      cluster_name : clusterName , 
67-       command, 
114+       command :  commandValue , 
68115      cpus : cpus  ||  undefined , 
69116      memory : memory  ||  undefined , 
70117      disk_space : diskSpace  ||  undefined , 
71118      accelerators : accelerators  ||  undefined , 
72119      num_nodes : numNodes  ? parseInt ( numNodes ,  10 )  : undefined , 
73-       setup : setup  ||  undefined , 
120+       setup : setupValue  ||  undefined , 
74121    }  as  any ; 
75122
76123    const  body  =  { 
@@ -115,6 +162,28 @@ export default function EditTaskModal({
115162    } 
116163  } ; 
117164
165+   function  handleSetupEditorDidMount ( editor : any ,  monaco : any )  { 
166+     setupEditorRef . current  =  editor ; 
167+     setTheme ( editor ,  monaco ) ; 
168+     // initialize editor with current setup state 
169+     try  { 
170+       editor . setValue ( setup  ??  '' ) ; 
171+     }  catch  ( e )  { 
172+       // ignore if setValue not available 
173+     } 
174+   } 
175+ 
176+   function  handleCommandEditorDidMount ( editor : any ,  monaco : any )  { 
177+     commandEditorRef . current  =  editor ; 
178+     setTheme ( editor ,  monaco ) ; 
179+     // initialize editor with current command state 
180+     try  { 
181+       editor . setValue ( command  ??  '' ) ; 
182+     }  catch  ( e )  { 
183+       // ignore if setValue not available 
184+     } 
185+   } 
186+ 
118187  return  ( 
119188    < Modal  open = { open }  onClose = { onClose } > 
120189      < ModalDialog 
@@ -201,22 +270,59 @@ export default function EditTaskModal({
201270
202271            < FormControl  sx = { {  mt : 2  } } > 
203272              < FormLabel > Setup Command</ FormLabel > 
204-               < Textarea 
273+               { /*  <Textarea
205274                minRows={2} 
206275                value={setup} 
207276                onChange={(e) => setSetup(e.target.value)} 
208277                placeholder="Setup commands (optional) that runs before task is run. e.g. pip install -r requirements.txt" 
278+               /> */ } 
279+               < Editor 
280+                 defaultLanguage = "shell" 
281+                 theme = "my-theme" 
282+                 defaultValue = { setup } 
283+                 height = "6rem" 
284+                 options = { { 
285+                   minimap : { 
286+                     enabled : false , 
287+                   } , 
288+                   fontSize : 18 , 
289+                   cursorStyle : 'block' , 
290+                   wordWrap : 'on' , 
291+                 } } 
292+                 onMount = { handleSetupEditorDidMount } 
209293              /> 
294+               < FormHelperText > 
295+                 e.g. < code > pip install -r requirements.txt</ code > 
296+               </ FormHelperText > 
210297            </ FormControl > 
211298
212299            < FormControl  required  sx = { {  mt : 2  } } > 
213300              < FormLabel > Command</ FormLabel > 
214-               < Textarea 
301+               { /*  <Textarea
215302                minRows={4} 
216303                value={command} 
217304                onChange={(e) => setCommand(e.target.value)} 
218305                placeholder="e.g. python train.py --epochs 10" 
306+               /> */ } 
307+ 
308+               < Editor 
309+                 defaultLanguage = "shell" 
310+                 theme = "my-theme" 
311+                 defaultValue = { command } 
312+                 height = "8rem" 
313+                 options = { { 
314+                   minimap : { 
315+                     enabled : false , 
316+                   } , 
317+                   fontSize : 18 , 
318+                   cursorStyle : 'block' , 
319+                   wordWrap : 'on' , 
320+                 } } 
321+                 onMount = { handleCommandEditorDidMount } 
219322              /> 
323+               < FormHelperText > 
324+                 e.g. < code > python train.py --epochs 10</ code > 
325+               </ FormHelperText > 
220326            </ FormControl > 
221327
222328            { /* Show uploaded directory indicator if present */ } 
0 commit comments