Skip to content

Commit

Permalink
implement pausing of log tailing when use scrolls up
Browse files Browse the repository at this point in the history
  • Loading branch information
jdrews committed Feb 14, 2023
1 parent df5119f commit cbe86f5
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
71 changes: 61 additions & 10 deletions web/src/LogStationLogViewer.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,77 @@
import React from 'react';
import {LogViewer, LogViewerSearch} from '@patternfly/react-log-viewer';
import { Toolbar, ToolbarContent, ToolbarItem } from '@patternfly/react-core';
import {Button, Toolbar, ToolbarContent, ToolbarItem} from '@patternfly/react-core';
import "@patternfly/react-core/dist/styles/base.css";
import OutlinedPlayCircleIcon from "@patternfly/react-icons/dist/esm/icons/outlined-play-circle-icon";

const LogStationLogViewer = (props) => {

// isPaused: control for whether a user has scrolled up (paused)
// this isPaused effectively stops the webapp from pinning to the bottom of the log
const [isPaused, setIsPaused] = React.useState(false);

// selectedScrollToRow: the row in the log that the LogViewer should scroll to (via prop scrollToRow)
// when set to undefined, the scrollToRow prop will do nothing
const [selectedScrollToRow, setSelectedScrollToRow] = React.useState(undefined)

// reference for the LogViewer component
const logViewerRef = React.useRef();

React.useEffect(() => {
if (!isPaused) {
if (logViewerRef && logViewerRef.current) {
setSelectedScrollToRow(props.data.length) // scroll down to the end of the log file
}
}
}, [isPaused, props.data.length]);

const onScroll = ({ scrollOffsetToBottom, _scrollDirection, scrollUpdateWasRequested }) => {
if (!scrollUpdateWasRequested) {
if (scrollOffsetToBottom > 0) { // if we're not at the bottom
setIsPaused(true); // pause log
setSelectedScrollToRow(undefined) // stop the pinning/tailing to the bottom via prop scrollToRow
} else {
setIsPaused(false); // tail the log (pin to the bottom of log)
}
}
};

// shows a button on the bottom that lets you resume tailing the log if you scrolled up / paused
const FooterButton = () => {
const handleClick = _e => {
setIsPaused(false);
};
return (
<Button onClick={handleClick} isBlock>
<OutlinedPlayCircleIcon />
resume
{/*resume {linesBehind === 0 ? null : `and show ${linesBehind} lines`}*/}
</Button>
);
};

return (
<LogViewer hasLineNumbers={false}
height={'100%'}
width={'100%'}
data={props.data}
theme={'dark'}
isTextWrapped={true}
toolbar={
<Toolbar>
<ToolbarContent>
<ToolbarItem>
<LogViewerSearch minSearchChars={2} placeholder={" search"}/>
</ToolbarItem>
</ToolbarContent>
</Toolbar>
}/>
innerRef={logViewerRef}
scrollToRow={selectedScrollToRow}
onScroll={onScroll}
footer={isPaused && <FooterButton />}
//TODO: disabled search for now. Will come back to it.
// toolbar={
// <Toolbar>
// <ToolbarContent>
// <ToolbarItem>
// <LogViewerSearch minSearchChars={2} placeholder={" search"}/>
// </ToolbarItem>
// </ToolbarContent>
// </Toolbar>
// }
/>
);
};

Expand Down
9 changes: 2 additions & 7 deletions web/src/MainLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,10 @@ const MainLayout = (props) => {
setSelectedLogFile(newLogFile);
};

//TODO: Figure out how to wrap this in a tabular header that shows the file and lets you swap between files
// Might be able to have this react class be instantiated within a larger react class that handles the file tabs and switching
return (
<Container disableGutters maxWidth="false" sx={{width: '100%', height: '100vh'}}>
<Box sx={{borderBottom: 1, borderColor: 'divider', height: '8vh', m: 0, p: 0}}>
<Tabs value={selectedLogFile} aria-label="log selector bar" textColor="secondary" indicatorColor="secondary" onChange={handleLogSelection}>
{/*<Tabs value={value} onChange={handleChange} aria-label="basic tabs example">*/
/*TODO: use value and onChange to populate tabs dynamically and make them do stuff*/}
<Tab key="0" value="0" label="logstation" disabled={true} disableRipple={true} {...a11yProps("0")}
sx={{
color: '#ffffff !important',
Expand All @@ -40,11 +36,10 @@ const MainLayout = (props) => {
{[...props.logFiles.keys()].map(logFile =>
(<Tab key={logFile} value={logFile} label={logFile} {...a11yProps(logFile)} sx={{color: '#ffffff', background: '#222', textTransform: 'unset'}}/>)
)}

</Tabs>
</Box>
<Box sx={{width: '100%', height: '92vh'}} className="LogViewer">
<LogStationLogViewer data={props.logFiles.get(selectedLogFile)}/>
<Box sx={{width: '100%', height: '92vh'}} className="LogViewerBox">
<LogStationLogViewer data={props.logFiles.get(selectedLogFile) ?? []}/>
</Box>
</Container>
);
Expand Down

0 comments on commit cbe86f5

Please sign in to comment.