@@ -8,7 +8,7 @@ import { Terminal } from '@xterm/xterm';
88import { Container , Header , ListEmptyMessage , Loader , TextContent } from 'components' ;
99
1010import { useAppSelector } from 'hooks' ;
11- import { useGetProjectLogsQuery } from 'services/project' ;
11+ import { useLazyGetProjectLogsQuery } from 'services/project' ;
1212
1313import { selectSystemMode } from 'App/slice' ;
1414
@@ -22,10 +22,50 @@ export const Logs: React.FC<IProps> = ({ className, projectName, runName, jobSub
2222 const { t } = useTranslation ( ) ;
2323 const appliedTheme = useAppSelector ( selectSystemMode ) ;
2424
25- const terminalInstance = useRef < Terminal > ( new Terminal ( ) ) ;
26-
25+ const terminalInstance = useRef < Terminal > ( new Terminal ( { scrollback : 10000000 } ) ) ;
2726 const fitAddonInstance = useRef < FitAddon > ( new FitAddon ( ) ) ;
2827 const [ logsData , setLogsData ] = useState < ILogItem [ ] > ( [ ] ) ;
28+ const [ isLoading , setIsLoading ] = useState ( false ) ;
29+
30+ const [ getProjectLogs ] = useLazyGetProjectLogsQuery ( ) ;
31+
32+ const writeDataToTerminal = ( logs : ILogItem [ ] ) => {
33+ logs . forEach ( ( logItem ) => {
34+ terminalInstance . current . write ( logItem . message ) ;
35+ } ) ;
36+
37+ fitAddonInstance . current . fit ( ) ;
38+ } ;
39+
40+ const getNextLogItems = ( nextToken ?: string ) => {
41+ setIsLoading ( true ) ;
42+
43+ if ( ! jobSubmissionId ) {
44+ return ;
45+ }
46+
47+ getProjectLogs ( {
48+ project_name : projectName ,
49+ run_name : runName ,
50+ descending : false ,
51+ job_submission_id : jobSubmissionId ?? '' ,
52+ next_token : nextToken ,
53+ limit : LIMIT_LOG_ROWS ,
54+ } )
55+ . unwrap ( )
56+ . then ( ( response ) => {
57+ setLogsData ( ( old ) => [ ...old , ...response . logs ] ) ;
58+
59+ writeDataToTerminal ( response . logs ) ;
60+
61+ if ( response . next_token ) {
62+ getNextLogItems ( response . next_token ) ;
63+ } else {
64+ setIsLoading ( false ) ;
65+ }
66+ } )
67+ . catch ( ( ) => setIsLoading ( false ) ) ;
68+ } ;
2969
3070 useEffect ( ( ) => {
3171 if ( appliedTheme === Mode . Light ) {
@@ -45,6 +85,8 @@ export const Logs: React.FC<IProps> = ({ className, projectName, runName, jobSub
4585 useEffect ( ( ) => {
4686 terminalInstance . current . loadAddon ( fitAddonInstance . current ) ;
4787
88+ getNextLogItems ( ) ;
89+
4890 const onResize = ( ) => {
4991 fitAddonInstance . current . fit ( ) ;
5092 } ;
@@ -56,50 +98,27 @@ export const Logs: React.FC<IProps> = ({ className, projectName, runName, jobSub
5698 } ;
5799 } , [ ] ) ;
58100
59- const {
60- data : fetchData ,
61- isLoading,
62- isFetching : isFetchingLogs ,
63- } = useGetProjectLogsQuery (
64- {
65- project_name : projectName ,
66- run_name : runName ,
67- descending : true ,
68- job_submission_id : jobSubmissionId ?? '' ,
69- limit : LIMIT_LOG_ROWS ,
70- } ,
71- {
72- skip : ! jobSubmissionId ,
73- } ,
74- ) ;
75-
76- useEffect ( ( ) => {
77- if ( fetchData ) {
78- const reversed = [ ...fetchData ] . reverse ( ) ;
79- setLogsData ( ( old ) => [ ...reversed , ...old ] ) ;
80- }
81- } , [ fetchData ] ) ;
82-
83101 useEffect ( ( ) => {
84102 const element = document . getElementById ( 'terminal' ) ;
85103
86- if ( logsData . length && terminalInstance . current && element ) {
104+ if ( terminalInstance . current && element ) {
87105 terminalInstance . current . open ( element ) ;
88-
89- logsData . forEach ( ( logItem ) => {
90- terminalInstance . current . write ( logItem . message ) ;
91- } ) ;
92-
93- fitAddonInstance . current . fit ( ) ;
94106 }
95- } , [ logsData ] ) ;
107+ } , [ ] ) ;
96108
97109 return (
98110 < div className = { classNames ( styles . logs , className ) } >
99- < Container header = { < Header variant = "h2" > { t ( 'projects.run.log' ) } </ Header > } >
111+ < Container
112+ header = {
113+ < Header variant = "h2" >
114+ < div className = { styles . headerContainer } >
115+ { t ( 'projects.run.log' ) }
116+ < Loader show = { isLoading } padding = { 'n' } className = { classNames ( styles . loader ) } loadingText = { '' } />
117+ </ div >
118+ </ Header >
119+ }
120+ >
100121 < TextContent >
101- < Loader padding = { 'n' } className = { classNames ( styles . loader , { show : isLoading || isFetchingLogs } ) } />
102-
103122 { ! isLoading && ! logsData . length && (
104123 < ListEmptyMessage
105124 title = { t ( 'projects.run.log_empty_message_title' ) }
0 commit comments