mirror of
https://github.com/ansible/awx.git
synced 2026-02-23 14:05:59 -03:30
Adds logic to try to keep visible page accurate in follow mode
This commit is contained in:
@@ -38,6 +38,7 @@ import { HostStatusBar, OutputToolbar } from './shared';
|
|||||||
import getRowRangePageSize from './shared/jobOutputUtils';
|
import getRowRangePageSize from './shared/jobOutputUtils';
|
||||||
import { getJobModel, isJobRunning } from '../../../util/jobs';
|
import { getJobModel, isJobRunning } from '../../../util/jobs';
|
||||||
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
import useRequest, { useDismissableError } from '../../../util/useRequest';
|
||||||
|
import useInterval from '../../../util/useInterval';
|
||||||
import {
|
import {
|
||||||
parseQueryString,
|
parseQueryString,
|
||||||
mergeParams,
|
mergeParams,
|
||||||
@@ -297,12 +298,13 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
const listRef = useRef(null);
|
const listRef = useRef(null);
|
||||||
const previousWidth = useRef(0);
|
const previousWidth = useRef(0);
|
||||||
const jobSocketCounter = useRef(0);
|
const jobSocketCounter = useRef(0);
|
||||||
const interval = useRef(null);
|
|
||||||
const isMounted = useIsMounted();
|
const isMounted = useIsMounted();
|
||||||
|
const scrollTop = useRef(0);
|
||||||
|
const scrollHeight = useRef(0);
|
||||||
|
const currentlyLoading = useRef([]);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const [contentError, setContentError] = useState(null);
|
const [contentError, setContentError] = useState(null);
|
||||||
const [cssMap, setCssMap] = useState({});
|
const [cssMap, setCssMap] = useState({});
|
||||||
const [currentlyLoading, setCurrentlyLoading] = useState([]);
|
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||||
const [hostEvent, setHostEvent] = useState({});
|
const [hostEvent, setHostEvent] = useState({});
|
||||||
const [isHostModalOpen, setIsHostModalOpen] = useState(false);
|
const [isHostModalOpen, setIsHostModalOpen] = useState(false);
|
||||||
@@ -310,7 +312,17 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
const [showCancelModal, setShowCancelModal] = useState(false);
|
const [showCancelModal, setShowCancelModal] = useState(false);
|
||||||
const [remoteRowCount, setRemoteRowCount] = useState(0);
|
const [remoteRowCount, setRemoteRowCount] = useState(0);
|
||||||
const [results, setResults] = useState({});
|
const [results, setResults] = useState({});
|
||||||
const [isFollowEnabled, setIsFollowModeEnabled] = useState(false);
|
const [isFollowModeEnabled, setIsFollowModeEnabled] = useState(
|
||||||
|
isJobRunning(job.status)
|
||||||
|
);
|
||||||
|
const [isMonitoringWebsocket, setIsMonitoringWebsocket] = useState(false);
|
||||||
|
|
||||||
|
useInterval(
|
||||||
|
() => {
|
||||||
|
monitorJobSocketCounter();
|
||||||
|
},
|
||||||
|
isMonitoringWebsocket ? 5000 : null
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadJobEvents();
|
loadJobEvents();
|
||||||
@@ -331,14 +343,15 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
interval.current = setInterval(() => monitorJobSocketCounter(), 5000);
|
setIsMonitoringWebsocket(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return function cleanup() {
|
return function cleanup() {
|
||||||
if (ws) {
|
if (ws) {
|
||||||
ws.close();
|
ws.close();
|
||||||
}
|
}
|
||||||
clearInterval(interval.current);
|
setIsMonitoringWebsocket(false);
|
||||||
|
isMounted.current = false;
|
||||||
};
|
};
|
||||||
}, [location.search]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [location.search]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
@@ -346,7 +359,23 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
if (listRef.current?.recomputeRowHeights) {
|
if (listRef.current?.recomputeRowHeights) {
|
||||||
listRef.current.recomputeRowHeights();
|
listRef.current.recomputeRowHeights();
|
||||||
}
|
}
|
||||||
}, [currentlyLoading, cssMap, remoteRowCount]);
|
}, [currentlyLoading.current, cssMap, remoteRowCount]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (jobStatus && !isJobRunning(jobStatus)) {
|
||||||
|
if (jobSocketCounter.current > remoteRowCount && isMounted.current) {
|
||||||
|
setRemoteRowCount(jobSocketCounter.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMonitoringWebsocket) {
|
||||||
|
setIsMonitoringWebsocket(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFollowModeEnabled) {
|
||||||
|
setTimeout(() => setIsFollowModeEnabled(false), 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [jobStatus]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
error: cancelError,
|
error: cancelError,
|
||||||
@@ -382,14 +411,14 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
} = useDismissableError(deleteError);
|
} = useDismissableError(deleteError);
|
||||||
|
|
||||||
const monitorJobSocketCounter = () => {
|
const monitorJobSocketCounter = () => {
|
||||||
|
if (jobSocketCounter.current > remoteRowCount && isMounted.current) {
|
||||||
|
setRemoteRowCount(jobSocketCounter.current);
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
jobSocketCounter.current === remoteRowCount &&
|
jobSocketCounter.current === remoteRowCount &&
|
||||||
!isJobRunning(job.status)
|
!isJobRunning(job.status)
|
||||||
) {
|
) {
|
||||||
clearInterval(interval.current);
|
setIsMonitoringWebsocket(false);
|
||||||
}
|
|
||||||
if (jobSocketCounter.current > remoteRowCount && isMounted.current) {
|
|
||||||
setRemoteRowCount(jobSocketCounter.current);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -398,9 +427,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
|
|
||||||
if (isMounted.current) {
|
if (isMounted.current) {
|
||||||
setHasContentLoading(true);
|
setHasContentLoading(true);
|
||||||
setCurrentlyLoading(prevCurrentlyLoading =>
|
currentlyLoading.current = currentlyLoading.current.concat(loadRange);
|
||||||
prevCurrentlyLoading.concat(loadRange)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -466,8 +493,8 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
} finally {
|
} finally {
|
||||||
if (isMounted.current) {
|
if (isMounted.current) {
|
||||||
setHasContentLoading(false);
|
setHasContentLoading(false);
|
||||||
setCurrentlyLoading(prevCurrentlyLoading =>
|
currentlyLoading.current = currentlyLoading.current.filter(
|
||||||
prevCurrentlyLoading.filter(n => !loadRange.includes(n))
|
n => !loadRange.includes(n)
|
||||||
);
|
);
|
||||||
loadRange.forEach(n => {
|
loadRange.forEach(n => {
|
||||||
cache.clear(n);
|
cache.clear(n);
|
||||||
@@ -480,7 +507,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
if (results[index]) {
|
if (results[index]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return currentlyLoading.includes(index);
|
return currentlyLoading.current.includes(index);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleHostEventClick = hostEventToOpen => {
|
const handleHostEventClick = hostEventToOpen => {
|
||||||
@@ -493,6 +520,9 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const rowRenderer = ({ index, parent, key, style }) => {
|
const rowRenderer = ({ index, parent, key, style }) => {
|
||||||
|
if (listRef.current && isFollowModeEnabled) {
|
||||||
|
setTimeout(() => scrollToRow(remoteRowCount - 1), 0);
|
||||||
|
}
|
||||||
let actualLineTextHtml = [];
|
let actualLineTextHtml = [];
|
||||||
if (results[index]) {
|
if (results[index]) {
|
||||||
const { lineTextHtml } = getLineTextHtml(results[index]);
|
const { lineTextHtml } = getLineTextHtml(results[index]);
|
||||||
@@ -545,9 +575,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (isMounted.current) {
|
if (isMounted.current) {
|
||||||
setCurrentlyLoading(prevCurrentlyLoading =>
|
currentlyLoading.current = currentlyLoading.current.concat(loadRange);
|
||||||
prevCurrentlyLoading.concat(loadRange)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
@@ -574,8 +602,8 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
...prevCssMap,
|
...prevCssMap,
|
||||||
...newResultsCssMap,
|
...newResultsCssMap,
|
||||||
}));
|
}));
|
||||||
setCurrentlyLoading(prevCurrentlyLoading =>
|
currentlyLoading.current = currentlyLoading.current.filter(
|
||||||
prevCurrentlyLoading.filter(n => !loadRange.includes(n))
|
n => !loadRange.includes(n)
|
||||||
);
|
);
|
||||||
loadRange.forEach(n => {
|
loadRange.forEach(n => {
|
||||||
cache.clear(n);
|
cache.clear(n);
|
||||||
@@ -585,7 +613,9 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const scrollToRow = rowIndex => {
|
const scrollToRow = rowIndex => {
|
||||||
listRef.current.scrollToRow(rowIndex);
|
if (listRef.current) {
|
||||||
|
listRef.current.scrollToRow(rowIndex);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleScrollPrevious = () => {
|
const handleScrollPrevious = () => {
|
||||||
@@ -659,25 +689,26 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleFollowToggle = () => {
|
const handleFollowToggle = () => {
|
||||||
if (isFollowEnabled) {
|
if (isFollowModeEnabled) {
|
||||||
setIsFollowModeEnabled(false);
|
setIsFollowModeEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
setIsFollowModeEnabled(true);
|
setIsFollowModeEnabled(true);
|
||||||
scrollToRow(remoteRowCount - 1);
|
scrollToRow(remoteRowCount - 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleScroll = () => {
|
|
||||||
if (listRef?.current?.Grid?._renderedRowStopIndex < remoteRowCount - 1) {
|
const handleScroll = e => {
|
||||||
|
if (
|
||||||
|
isFollowModeEnabled &&
|
||||||
|
scrollTop.current > e.scrollTop &&
|
||||||
|
scrollHeight.current === e.scrollHeight
|
||||||
|
) {
|
||||||
setIsFollowModeEnabled(false);
|
setIsFollowModeEnabled(false);
|
||||||
}
|
}
|
||||||
|
scrollTop.current = e.scrollTop;
|
||||||
|
scrollHeight.current = e.scrollHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isFollowEnabled) {
|
|
||||||
scrollToRow(remoteRowCount);
|
|
||||||
}
|
|
||||||
}, [remoteRowCount, isFollowEnabled]);
|
|
||||||
|
|
||||||
const renderSearchComponent = () => (
|
const renderSearchComponent = () => (
|
||||||
<Search
|
<Search
|
||||||
qsConfig={QS_CONFIG}
|
qsConfig={QS_CONFIG}
|
||||||
@@ -786,10 +817,10 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
</ToolbarToggleGroup>
|
</ToolbarToggleGroup>
|
||||||
{isJobRunning(job.status) ? (
|
{isJobRunning(job.status) ? (
|
||||||
<Button
|
<Button
|
||||||
variant={isFollowEnabled ? 'secondary' : 'primary'}
|
variant={isFollowModeEnabled ? 'secondary' : 'primary'}
|
||||||
onClick={handleFollowToggle}
|
onClick={handleFollowToggle}
|
||||||
>
|
>
|
||||||
{isFollowEnabled ? t`Unfollow` : t`Follow`}
|
{isFollowModeEnabled ? t`Unfollow` : t`Follow`}
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
</SearchToolbarContent>
|
</SearchToolbarContent>
|
||||||
@@ -800,7 +831,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
|
|||||||
onScrollNext={handleScrollNext}
|
onScrollNext={handleScrollNext}
|
||||||
onScrollPrevious={handleScrollPrevious}
|
onScrollPrevious={handleScrollPrevious}
|
||||||
/>
|
/>
|
||||||
<OutputWrapper cssMap={cssMap} isFollowEnabled={isFollowEnabled}>
|
<OutputWrapper cssMap={cssMap}>
|
||||||
<InfiniteLoader
|
<InfiniteLoader
|
||||||
isRowLoaded={isRowLoaded}
|
isRowLoaded={isRowLoaded}
|
||||||
loadMoreRows={loadMoreRows}
|
loadMoreRows={loadMoreRows}
|
||||||
|
|||||||
Reference in New Issue
Block a user