fix: logs page by the data after parsing
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
||||
import { FitAddon } from '@xterm/addon-fit';
|
||||
import { WebglAddon } from '@xterm/addon-webgl';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import '@xterm/xterm/css/xterm.css';
|
||||
import classNames from 'classnames';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
forwardRef,
|
||||
memo,
|
||||
useEffect,
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react';
|
||||
import { replaceLineRegex } from './config';
|
||||
import './styles/xterm-viewer.less';
|
||||
import useSize from './use-size';
|
||||
|
||||
interface LogsViewerProps {
|
||||
height: number;
|
||||
content?: string;
|
||||
url: string;
|
||||
ref?: any;
|
||||
params?: object;
|
||||
}
|
||||
const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
|
||||
const { height, content, url } = props;
|
||||
const { setChunkRequest } = useSetChunkRequest();
|
||||
const chunkRequedtRef = useRef<any>(null);
|
||||
const scroller = useRef<any>({});
|
||||
const termRef = useRef<any>({});
|
||||
const termwrapRef = useRef<any>({});
|
||||
const fitAddonRef = useRef<any>({});
|
||||
const cacheDataRef = useRef<any>(null);
|
||||
const [logs, setLogs] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const size = useSize(scroller);
|
||||
const logParseWorker = useRef<any>(null);
|
||||
const lineCountRef = useRef(0);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
abort() {
|
||||
chunkRequedtRef.current?.current?.abort?.();
|
||||
logParseWorker.current?.terminate?.();
|
||||
}
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
logParseWorker.current?.terminate?.();
|
||||
|
||||
logParseWorker.current = new Worker(
|
||||
// @ts-ignore
|
||||
new URL('./parse-worker.ts', import.meta.url),
|
||||
{
|
||||
type: 'module'
|
||||
}
|
||||
);
|
||||
|
||||
logParseWorker.current.onmessage = (event: any) => {
|
||||
const { result, lines } = event.data;
|
||||
lineCountRef.current = lines;
|
||||
// setLogs(result.join('\n'));
|
||||
console.log('res+++++++++++', result);
|
||||
const data = result.map((item: any) => item.content);
|
||||
termRef.current?.write?.(data.join('\n'));
|
||||
};
|
||||
|
||||
return () => {
|
||||
if (logParseWorker.current) {
|
||||
logParseWorker.current.terminate();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const throttleScroll = _.throttle(() => {
|
||||
termRef.current?.scrollToBottom?.();
|
||||
}, 100);
|
||||
|
||||
const debounceLoading = _.debounce(() => {
|
||||
setLoading(false);
|
||||
}, 200);
|
||||
|
||||
const updateContent = (inputStr: string) => {
|
||||
const data = inputStr.replace(replaceLineRegex, '\n');
|
||||
cacheDataRef.current = data;
|
||||
setLoading(true);
|
||||
logParseWorker.current.postMessage({
|
||||
inputStr: data
|
||||
});
|
||||
debounceLoading();
|
||||
};
|
||||
|
||||
const fitTerm = () => {
|
||||
fitAddonRef.current?.fit?.();
|
||||
};
|
||||
|
||||
const createChunkConnection = async () => {
|
||||
chunkRequedtRef.current?.current?.cancel?.();
|
||||
chunkRequedtRef.current = setChunkRequest({
|
||||
url,
|
||||
params: {
|
||||
...props.params,
|
||||
watch: true
|
||||
},
|
||||
contentType: 'text',
|
||||
handler: updateContent
|
||||
});
|
||||
};
|
||||
|
||||
const initTerm = () => {
|
||||
termRef.current?.dispose?.();
|
||||
termRef.current = new Terminal({
|
||||
lineHeight: 1.2,
|
||||
fontSize: 13,
|
||||
fontFamily:
|
||||
"monospace,Menlo,Courier,'Courier New',Consolas,Monaco, 'Liberation Mono'",
|
||||
disableStdin: true,
|
||||
convertEol: true,
|
||||
theme: {
|
||||
background: '#1e1e1e',
|
||||
foreground: 'rgba(255,255,255,0.8)'
|
||||
},
|
||||
cursorInactiveStyle: 'none',
|
||||
smoothScrollDuration: 0
|
||||
});
|
||||
fitAddonRef.current = new FitAddon();
|
||||
termRef.current.loadAddon(fitAddonRef.current);
|
||||
termRef.current.loadAddon(new WebglAddon());
|
||||
termRef.current.open(termwrapRef.current);
|
||||
|
||||
// add event
|
||||
// termRef.current.onLineFeed((e: any) => {
|
||||
// if (cacheDataRef.current) {
|
||||
// throttleScroll();
|
||||
// }
|
||||
// });
|
||||
};
|
||||
|
||||
const handleResize = _.throttle(() => {
|
||||
fitTerm();
|
||||
}, 100);
|
||||
|
||||
useEffect(() => {
|
||||
createChunkConnection();
|
||||
return () => {
|
||||
chunkRequedtRef.current?.current?.cancel?.();
|
||||
};
|
||||
}, [url, props.params]);
|
||||
|
||||
useEffect(() => {
|
||||
if (termwrapRef.current) {
|
||||
initTerm();
|
||||
}
|
||||
return () => {
|
||||
termRef.current?.dispose?.();
|
||||
};
|
||||
}, [termwrapRef.current]);
|
||||
|
||||
useEffect(() => {
|
||||
if (size) {
|
||||
handleResize();
|
||||
}
|
||||
}, [size]);
|
||||
|
||||
useEffect(() => {
|
||||
// throttleScroll();
|
||||
}, [logs]);
|
||||
|
||||
return (
|
||||
<div className="logs-viewer-wrap-w2">
|
||||
<div className="wrap" style={{ height: height }} ref={scroller}>
|
||||
<div className={classNames('content')}>
|
||||
<div className="text" ref={termwrapRef}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default memo(LogsViewer);
|
||||
Reference in New Issue
Block a user