From cbe86f548ad78d281f59bc505aa43fcbd30c3c77 Mon Sep 17 00:00:00 2001 From: Jon Drews Date: Mon, 13 Feb 2023 23:50:51 -0500 Subject: [PATCH] implement pausing of log tailing when use scrolls up --- web/src/LogStationLogViewer.jsx | 71 ++++++++++++++++++++++++++++----- web/src/MainLayout.jsx | 9 +---- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/web/src/LogStationLogViewer.jsx b/web/src/LogStationLogViewer.jsx index b3d6fe7..84bcacb 100644 --- a/web/src/LogStationLogViewer.jsx +++ b/web/src/LogStationLogViewer.jsx @@ -1,10 +1,55 @@ 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 ( + + ); + }; + return ( { data={props.data} theme={'dark'} isTextWrapped={true} - toolbar={ - - - - - - - - }/> + innerRef={logViewerRef} + scrollToRow={selectedScrollToRow} + onScroll={onScroll} + footer={isPaused && } + //TODO: disabled search for now. Will come back to it. + // toolbar={ + // + // + // + // + // + // + // + // } + /> ); }; diff --git a/web/src/MainLayout.jsx b/web/src/MainLayout.jsx index 1191bb3..90cd2ab 100644 --- a/web/src/MainLayout.jsx +++ b/web/src/MainLayout.jsx @@ -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 ( - {/**/ - /*TODO: use value and onChange to populate tabs dynamically and make them do stuff*/} { {[...props.logFiles.keys()].map(logFile => () )} - - - + + );