import classNames from 'classnames'; import { isEmpty, throttle } from 'lodash'; import * as React from 'react'; import { BuildDetailsScrollContainerContext } from './BuildDetailsScrollContainerContext'; import { CIReader } from '../CIReader'; import type { ICiBuild } from '../domain'; import { Tooltip, useInterval } from '../../presentation'; import { Spinner } from '../../widgets'; interface ILogResult { logs: string[]; state: 'loaded' | 'loading'; } const INIT_LOG_RESULT: ILogResult = { logs: [], state: 'loading', }; interface IBuildInfoLogsTabProps { build: ICiBuild; } export function BuildInfoLogsTab({ build }: IBuildInfoLogsTabProps) { const [logResult, setLogResult] = React.useState(INIT_LOG_RESULT); const [autoScroll, setAutoScroll] = React.useState(false); const [scrollTop, setScrollTop] = React.useState(0); const logContainerEnd = React.useRef(null); const retrieveOutputLogs = (offset = -1) => { CIReader.getBuildOutput(build.id, offset).then((response) => setLogResult((logResult) => ({ logs: [...logResult.logs, response.log], state: build.isRunning ? 'loading' : 'loaded', })), ); }; const buildDetailsScrollContainer = React.useContext(BuildDetailsScrollContainerContext); React.useEffect(() => { setLogResult(INIT_LOG_RESULT); setAutoScroll(false); retrieveOutputLogs(); }, [build.id]); useInterval(() => { if (build.isRunning) { retrieveOutputLogs(logResult.logs.length); if (autoScroll) { logContainerEnd.current?.scrollIntoView({ behavior: 'smooth' }); } } }, 1000); React.useEffect(() => { const scrollContainer = buildDetailsScrollContainer || window; const scrollHandler = throttle(() => { if (scrollTop > scrollContainer.scrollTop) { setAutoScroll(false); } setScrollTop(scrollContainer.scrollTop); }, 300); scrollContainer.addEventListener('scroll', scrollHandler); return () => { scrollContainer.removeEventListener('scroll', scrollHandler); }; }, [scrollTop, buildDetailsScrollContainer]); const scrollToBottomHandler = () => { if (autoScroll) { setAutoScroll(false); } else { setAutoScroll(true); logContainerEnd.current.scrollIntoView({ behavior: 'smooth' }); } }; if (isEmpty(logResult.logs) && logResult.state === 'loading') { return (
); } return (
            

{logResult.logs.join('')}

); }