@@ -135,8 +135,46 @@ export default function Tasks({ subtype }: { subtype?: string }) {
135135 } ;
136136 } , [ pendingJobsStorageKey ] ) ;
137137
138+ // Listen for custom event to open job output modal from interactive modals
139+ useEffect ( ( ) => {
140+ const handleOpenJobOutput = ( e : Event ) => {
141+ const customEvent = e as CustomEvent < { jobId : number } > ;
142+ const jobId = customEvent . detail ?. jobId ;
143+ if ( jobId && jobId !== - 1 ) {
144+ // Close the interactive modal first
145+ setInteractiveJobForModal ( - 1 ) ;
146+ // Wait for the modal to close (MUI modals have transition animations)
147+ // Use a longer delay to ensure the interactive modal fully closes
148+ // before opening the output modal to avoid z-index/stacking issues
149+ setTimeout ( ( ) => {
150+ setViewOutputFromJob ( jobId ) ;
151+ } , 300 ) ; // 300ms should be enough for modal close animation
152+ }
153+ } ;
154+
155+ const eventName = 'tflab-open-job-output' ;
156+ window . addEventListener ( eventName , handleOpenJobOutput ) ;
157+
158+ return ( ) => {
159+ window . removeEventListener ( eventName , handleOpenJobOutput ) ;
160+ } ;
161+ } , [ ] ) ;
162+
138163 const isInteractivePage = subtype === 'interactive' ;
139164
165+ // Define the callback outside the IIFE to ensure it's always available
166+ const handleOpenOutputFromInteractive = useCallback (
167+ ( outputJobId : number ) => {
168+ // Close the interactive modal first
169+ setInteractiveJobForModal ( - 1 ) ;
170+ // Wait for modal close animation, then open output modal
171+ setTimeout ( ( ) => {
172+ setViewOutputFromJob ( outputJobId ) ;
173+ } , 300 ) ;
174+ } ,
175+ [ interactiveJobForModal ] ,
176+ ) ;
177+
140178 const handleOpen = ( ) => {
141179 if ( isInteractivePage ) {
142180 setInteractiveModalOpen ( true ) ;
@@ -1092,6 +1130,7 @@ export default function Tasks({ subtype }: { subtype?: string }) {
10921130 < InteractiveJupyterModal
10931131 jobId = { interactiveJobForModal }
10941132 setJobId = { ( jobId : number ) => setInteractiveJobForModal ( jobId ) }
1133+ onOpenOutput = { handleOpenOutputFromInteractive }
10951134 />
10961135 ) ;
10971136 }
@@ -1101,15 +1140,21 @@ export default function Tasks({ subtype }: { subtype?: string }) {
11011140 < InteractiveVllmModal
11021141 jobId = { interactiveJobForModal }
11031142 setJobId = { ( jobId : number ) => setInteractiveJobForModal ( jobId ) }
1143+ onOpenOutput = { handleOpenOutputFromInteractive }
11041144 />
11051145 ) ;
11061146 }
11071147
11081148 if ( interactiveType === 'ssh' ) {
1149+ console . log (
1150+ '[Tasks] Rendering InteractiveSshModal with onOpenOutput:' ,
1151+ handleOpenOutputFromInteractive ,
1152+ ) ;
11091153 return (
11101154 < InteractiveSshModal
11111155 jobId = { interactiveJobForModal }
11121156 setJobId = { ( jobId : number ) => setInteractiveJobForModal ( jobId ) }
1157+ onOpenOutput = { handleOpenOutputFromInteractive }
11131158 />
11141159 ) ;
11151160 }
@@ -1119,6 +1164,7 @@ export default function Tasks({ subtype }: { subtype?: string }) {
11191164 < InteractiveOllamaModal
11201165 jobId = { interactiveJobForModal }
11211166 setJobId = { ( jobId : number ) => setInteractiveJobForModal ( jobId ) }
1167+ onOpenOutput = { handleOpenOutputFromInteractive }
11221168 />
11231169 ) ;
11241170 }
@@ -1127,6 +1173,7 @@ export default function Tasks({ subtype }: { subtype?: string }) {
11271173 < InteractiveVSCodeModal
11281174 jobId = { interactiveJobForModal }
11291175 setJobId = { ( jobId : number ) => setInteractiveJobForModal ( jobId ) }
1176+ onOpenOutput = { handleOpenOutputFromInteractive }
11301177 />
11311178 ) ;
11321179 } ) ( ) }
0 commit comments