mirror of
https://github.com/rowyio/rowy.git
synced 2026-02-23 19:50:01 +01:00
ft build stream: auto scroll to latest log
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
"react-router-dom": "^5.0.1",
|
||||
"react-scripts": "^3.4.3",
|
||||
"react-scroll-sync": "^0.8.0",
|
||||
"react-usestateref": "^1.0.5",
|
||||
"serve": "^11.3.2",
|
||||
"tinymce": "^5.2.0",
|
||||
"typescript": "^3.7.2",
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import useRouter from "hooks/useRouter";
|
||||
import useTable from "hooks/useFiretable/useTable";
|
||||
import { useFiretableContext } from "contexts/FiretableContext";
|
||||
import useStateRef from "react-usestateref";
|
||||
|
||||
import _camelCase from "lodash/camelCase";
|
||||
import _get from "lodash/get";
|
||||
import _find from "lodash/find";
|
||||
import _sortBy from "lodash/sortBy";
|
||||
import _throttle from "lodash/throttle";
|
||||
import moment from "moment";
|
||||
|
||||
import {
|
||||
@@ -57,6 +59,10 @@ const useStyles = makeStyles((theme) => ({
|
||||
width: "100%",
|
||||
backgroundColor: "#1E1E1E",
|
||||
},
|
||||
logPanelProgress: {
|
||||
marginLeft: "3em",
|
||||
marginTop: "1em",
|
||||
},
|
||||
logEntryWrapper: {
|
||||
overflowY: "scroll",
|
||||
maxHeight: "100%",
|
||||
@@ -136,23 +142,88 @@ function LogRow({ logRecord, index }) {
|
||||
}
|
||||
|
||||
function LogPanel(props) {
|
||||
const { logs, status, value, index, ...other } = props;
|
||||
const { logs, status, value, index, isOpen, ...other } = props;
|
||||
const classes = useStyles();
|
||||
|
||||
// useStateRef is necessary to resolve the state syncing issue
|
||||
// https://stackoverflow.com/a/63039797/12208834
|
||||
const [liveStreaming, setLiveStreaming, liveStreamingStateRef] = useStateRef(
|
||||
true
|
||||
);
|
||||
const liveStreamingRef = useRef<any>();
|
||||
const isActive = value === index;
|
||||
|
||||
const handleScroll = _throttle(() => {
|
||||
const target = document.querySelector("#live-stream-target");
|
||||
const scrollBox = document.querySelector("#live-stream-scroll-box");
|
||||
const liveStreamTargetVisible = isTargetInsideBox(target, scrollBox);
|
||||
if (liveStreamTargetVisible !== liveStreamingStateRef.current) {
|
||||
console.log("live streaming:", liveStreamTargetVisible);
|
||||
setLiveStreaming(liveStreamTargetVisible);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
const scrollToLive = () => {
|
||||
const liveStreamTarget = document.querySelector("#live-stream-target");
|
||||
liveStreamTarget?.scrollIntoView?.({
|
||||
behavior: "smooth",
|
||||
});
|
||||
};
|
||||
|
||||
const isTargetInsideBox = (target, box) => {
|
||||
const targetRect = target.getBoundingClientRect();
|
||||
const boxRect = box.getBoundingClientRect();
|
||||
return targetRect.y < boxRect.y + boxRect.height;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (liveStreaming && isActive && status === "BUILDING") {
|
||||
if (!liveStreamingRef.current) {
|
||||
scrollToLive();
|
||||
} else {
|
||||
setTimeout(scrollToLive, 100);
|
||||
}
|
||||
}
|
||||
}, [logs, value]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isActive) {
|
||||
const liveStreamScrollBox = document.querySelector(
|
||||
"#live-stream-scroll-box"
|
||||
);
|
||||
liveStreamScrollBox!.addEventListener("scroll", () => {
|
||||
handleScroll();
|
||||
});
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div
|
||||
role="tabpanel"
|
||||
hidden={value !== index}
|
||||
hidden={!isActive}
|
||||
id={`vertical-tabpanel-${index}`}
|
||||
aria-labelledby={`vertical-tab-${index}`}
|
||||
className={classes.logPanel}
|
||||
{...other}
|
||||
>
|
||||
{value === index && (
|
||||
<Box p={3} className={classes.logEntryWrapper}>
|
||||
<Box
|
||||
p={3}
|
||||
className={classes.logEntryWrapper}
|
||||
id="live-stream-scroll-box"
|
||||
>
|
||||
{logs?.map((log, index) => {
|
||||
return <LogRow logRecord={log} index={index} />;
|
||||
return <LogRow logRecord={log} index={index} key={index} />;
|
||||
})}
|
||||
<div ref={liveStreamingRef} id="live-stream-target">
|
||||
{status === "BUILDING" && (
|
||||
<CircularProgress
|
||||
className={classes.logPanelProgress}
|
||||
size={30}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ height: 10 }} />
|
||||
</Box>
|
||||
)}
|
||||
</div>
|
||||
@@ -238,6 +309,7 @@ export default function TableLogs() {
|
||||
>
|
||||
{collectionState.rows.map((logEntry, index) => (
|
||||
<Tab
|
||||
key={index}
|
||||
label={
|
||||
<Box className={classes.tab}>
|
||||
<Box>
|
||||
@@ -260,6 +332,7 @@ export default function TableLogs() {
|
||||
</Tabs>
|
||||
{collectionState.rows.map((logEntry, index) => (
|
||||
<LogPanel
|
||||
key={index}
|
||||
value={tabIndex}
|
||||
index={index}
|
||||
logs={logEntry?.fullLog}
|
||||
|
||||
@@ -12685,6 +12685,11 @@ react-transition-group@^4.0.0, react-transition-group@^4.4.0:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react-usestateref@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/react-usestateref/-/react-usestateref-1.0.5.tgz#0b5659217022a7e88087875ec1745730940b7882"
|
||||
integrity sha512-Bia+nJDuhmakaUQR6ztVPvZnGz2cV8ZOh9Tlgpc2iZorwc2Li4xcQUICtMwdAms5N9bH8FnPX+mXn91EsExvvg==
|
||||
|
||||
"react@^16.8.0 || ^17.0.0":
|
||||
version "17.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
|
||||
|
||||
Reference in New Issue
Block a user