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 =>
()
)}
-
-
-
+
+
);