diff --git a/src/components/logs-viewer/index.tsx b/src/components/logs-viewer/index.tsx index 9f1f7fc4..f736e0d1 100644 --- a/src/components/logs-viewer/index.tsx +++ b/src/components/logs-viewer/index.tsx @@ -33,44 +33,67 @@ const LogsViewer: React.FC = (props) => { updateScrollerPosition(); }, [logsContent]); + const ansiEscapeRegex = /(\x1B\[[0-9;]*[A-Za-z])+$/; + const endsWithAnsiEscapeSequence = useCallback((str: string) => { - const ansiEscapeRegex = /\x1B\[[0-9;]*[A-Za-z]$/; return ansiEscapeRegex.test(str); }, []); const getCursorUpLines = useCallback((str: string) => { - const match = str.match(/\x1B\[(\d*)A$/); + const matches = str.match(/(?:\x1B\[A)+$/); + + return matches ? matches[0].length / 3 : 0; + }, []); + + const removeDot = useCallback((str: string) => { + return str.replace(/^\(.*?\)/, ''); + }, []); + const replaceAnsiEscapeSequence = useCallback((str: string) => { + const res = str.replace(ansiEscapeRegex, ''); + return removeDot(res); + }, []); - if (match) { - return match[1] === '' ? 1 : parseInt(match[1], 10); - } else { - return null; + const handleRControl = useCallback((str: string) => { + if (str.includes('\r')) { + const parts = str.split('\r'); + const lastLine = parts[parts.length - 1]; + return lastLine; } + return str; }, []); const parseHtmlStr = useCallback((logStr: string) => { const result: string[] = []; - const lines = logStr?.split?.('\n'); - + const lines = logStr.split('\n').filter((line) => line.trim() !== ''); + // const lines = text; lines.forEach((line: string, index: number) => { const upCount = getCursorUpLines(line); + console.log('line=========1', { + line, + upCount, + result + }); if (endsWithAnsiEscapeSequence(line)) { + const newLine = handleRControl(line); + const val = removeDot(newLine); + if (result.length < upCount) { + result.push(''); + } if (upCount) { + console.log('line=========0', { + line, + upCount, + result + }); const placeIndex = result.length - upCount; - result[placeIndex] = line; + result[placeIndex] = replaceAnsiEscapeSequence(val); } else { - result.push(line); + result.push(val); } } else { - if (line.includes('\r')) { - const parts = line.split('\r'); - const lastLine = parts[parts.length - 1]; - result.push(lastLine); - } else { - result.push(line); - } + const val = handleRControl(line); + result.push(val); } }); - return result.map((item) => { return convert.toHtml(item); }); diff --git a/src/components/logs-viewer/text.ts b/src/components/logs-viewer/text.ts new file mode 100644 index 00000000..22ebaa60 --- /dev/null +++ b/src/components/logs-viewer/text.ts @@ -0,0 +1,186 @@ +export default [ + '2024-09-11T20:09:42+08:00 - gpustack.worker.downloaders - INFO - Downloading model leafspark/Reflection-Llama-3.1-70B-GGUF/Reflection-Llama-3.1-70B.fp16*.gguf', + '\rFetching 4 files: 0%| | 0/4 [00:00 = ({ value: modelSourceMap.huggingface_value, key: 'huggingface', icon: , - onClick: () => { + onClick: (e: any) => { setOpenDeployModal({ show: true, width: 'calc(100vw - 220px)', @@ -143,11 +143,13 @@ const Models: React.FC = ({ value: modelSourceMap.ollama_library_value, key: 'ollama_library', icon: , - onClick: () => { - setOpenDeployModal({ - show: true, - width: 600, - source: modelSourceMap.ollama_library_value + onClick: (e: any) => { + setOpenDeployModal(() => { + return { + show: true, + width: 600, + source: modelSourceMap.ollama_library_value + }; }); } } @@ -242,7 +244,7 @@ const Models: React.FC = ({ const handleCreateModel = useCallback(async (data: FormData) => { try { - console.log('data:', data); + console.log('data:', data, openDeployModal); await createModel({ data }); setOpenDeployModal({ diff --git a/src/pages/resources/components/update-labels.tsx b/src/pages/resources/components/update-labels.tsx index 5fbaf75c..50480ae3 100644 --- a/src/pages/resources/components/update-labels.tsx +++ b/src/pages/resources/components/update-labels.tsx @@ -37,7 +37,7 @@ const UpdateLabels: React.FC = (props) => { return ( + icon: }, { label: 'common.button.delete',