diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index f0d20ee6b8a049d3ef6e4eacb919575895bcc87b..fb894c3ceb8c786ea112ea7f3b41dba69cabfbe9 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -15,6 +15,7 @@ import * as chatAPI from 'renderer/lib/transformerlab-api-sdk'; import useSWR from 'swr'; import XtermJSDrawer from './components/Connect/XtermJS'; +import OutputTerminal from './components/OutputTerminal'; // import OutputTerminal from './components/OutputTerminal'; // import AutoUpdateModal from './components/AutoUpdateModal'; @@ -27,7 +28,7 @@ export default function App() { const [sshConnection, setSSHConnection] = useState(null); - const [drawerOpen, setDrawerOpen] = useState(false); + const [logsDrawerOpen, setLogsDrawerOpen] = useState(false); useEffect(() => { async function getSavedExperimentId() { @@ -84,13 +85,18 @@ export default function App() { width: '100dvw', overflow: 'hidden', gridTemplateColumns: '220px 1fr', - gridTemplateRows: '60px 5fr 0fr', - gridTemplateAreas: ` + gridTemplateRows: logsDrawerOpen ? '60px 5fr 1fr' : '60px 5fr 0.01fr', + gridTemplateAreas: logsDrawerOpen + ? ` + "sidebar header" + "sidebar main" + "sidebar footer" + ` + : ` "sidebar header" "sidebar main" "sidebar footer" `, - // backgroundColor: (theme) => theme.vars.palette.background.surface, })} > @@ -105,7 +111,8 @@ export default function App() { <Sidebar experimentInfo={experimentInfo} setExperimentId={setExperimentId} - setDrawerOpen={setDrawerOpen} + logsDrawerOpen={logsDrawerOpen} + setLogsDrawerOpen={setLogsDrawerOpen} /> <Box sx={{ @@ -130,19 +137,19 @@ export default function App() { experimentInfoMutate={experimentInfoMutate} /> </Box> - {/* <OutputTerminal /> */} + <OutputTerminal /> <LoginModal setServer={setConnection} connection={connection} - setTerminalDrawerOpen={setDrawerOpen} + setTerminalDrawerOpen={setLogsDrawerOpen} setSSHConnection={setSSHConnection} /> </Box> - <XtermJSDrawer + {/* <XtermJSDrawer sshConnection={sshConnection} drawerOpen={drawerOpen} setDrawerOpen={setDrawerOpen} - /> + /> */} </CssVarsProvider> ); } diff --git a/src/renderer/components/Nav/Sidebar.tsx b/src/renderer/components/Nav/Sidebar.tsx index 2401413840b3a3bb20ba02506ac6bd21fae92ce0..d9d3ec7c8d79b8f5b01c48e86c43cd52e9867a44 100644 --- a/src/renderer/components/Nav/Sidebar.tsx +++ b/src/renderer/components/Nav/Sidebar.tsx @@ -22,6 +22,7 @@ import { FolderSearch2Icon, TextIcon, RectangleEllipsisIcon, + LogsIcon, } from 'lucide-react'; import { ButtonGroup, IconButton, Sheet, Tooltip } from '@mui/joy'; @@ -39,7 +40,8 @@ import ColorSchemeToggle from './ColorSchemeToggle'; export default function Sidebar({ experimentInfo, setExperimentId, - setDrawerOpen, + logsDrawerOpen, + setLogsDrawerOpen, }) { const { models, isError, isLoading } = useModelStatus(); const { outdatedPluginsCount } = usePluginStatus(experimentInfo); @@ -269,6 +271,14 @@ export default function Sidebar({ <SettingsIcon strokeWidth={1} /> </IconButton> </Tooltip> + <Tooltip title="Logs"> + <IconButton + variant="plain" + onClick={() => setLogsDrawerOpen(!logsDrawerOpen)} + > + <LogsIcon strokeWidth={1} /> + </IconButton> + </Tooltip> </ButtonGroup> </List> </Sheet> diff --git a/src/renderer/components/OutputTerminal/index.tsx b/src/renderer/components/OutputTerminal/index.tsx index 204d97aadd0d5bf26f1f5a1448a3158a1861827d..61034bacde7158b6021f4f7ac4f6aae72120189d 100644 --- a/src/renderer/components/OutputTerminal/index.tsx +++ b/src/renderer/components/OutputTerminal/index.tsx @@ -1,40 +1,69 @@ -import { Sheet } from '@mui/joy'; -import { useEffect } from 'react'; +import { Box, Sheet } from '@mui/joy'; +import { FitAddon } from '@xterm/addon-fit'; +import { Terminal } from '@xterm/xterm'; +import { useEffect, useRef } from 'react'; export default function OutputTerminal({}) { + const terminalRef = useRef(null); + let term: Terminal | null = null; + + const fitAddon = new FitAddon(); + + function handleResize() { + fitAddon.fit(); + } + useEffect(() => { - var source = new EventSource('http://pop-os:8338/stream-logs'); + // This is hardcoded to local for now -- just building + var source = new EventSource('http://localhost:8338/server/stream_log'); source.onmessage = function (event) { - var logs = document.getElementById('logs'); - logs.innerHTML += event.data + '<br>'; - // Scroll to bottom - logs.scrollTop = document.getElementById('logs').scrollHeight; + // console.log(event.data); + // var logs = document.getElementById('logs'); + // logs.innerHTML += event.data + '<br>'; + // // Scroll to bottom + // logs.scrollTop = document.getElementById('logs').scrollHeight; + + if (term !== null) { + console.log(event.data); + const lines = JSON.parse(event.data); + console.log(lines); + lines.forEach((line: string) => { + term.writeln(line); + if (terminalRef.current) { + terminalRef.current.scrollIntoView({ behavior: 'smooth' }); + } + }); + } + window.addEventListener('resize', handleResize); }; + term = new Terminal(); + term.loadAddon(fitAddon); + + if (terminalRef.current) term.open(terminalRef.current); + fitAddon.fit(); + + window.addEventListener('resize', handleResize); + return () => { + term?.dispose(); source.close(); + window.removeEventListener('resize', handleResize); }; }); return ( - <Sheet - sx={{ - gridArea: 'footer', - display: 'flex', - overflow: 'auto', - flexDirection: 'column', - border: '10px solid red', - }} - > - <div - id="logs" - style={{ - backgroundColor: 'black', - color: 'white', - overflowX: 'hidden', - overflowY: 'auto', + <Box sx={{ height: '100%', overflow: 'hidden' }}> + <Sheet + sx={{ + gridArea: 'terminal', + height: '100%', + overflow: 'auto', + backgroundColor: '#222', + // color: 'white', }} - ></div> - </Sheet> + ref={terminalRef} + ></Sheet> + </Box> ); }