JobOutput: add 'waiting for job' and 'no results found' messages

This commit is contained in:
Keith J. Grant 2022-03-07 10:04:11 -08:00
parent eb52095670
commit 4080007ced
4 changed files with 101 additions and 36 deletions

View File

@ -1,6 +1,5 @@
import React from 'react';
import { t } from '@lingui/macro';
import {
Title,
EmptyState,
@ -9,9 +8,14 @@ import {
} from '@patternfly/react-core';
import { CubesIcon } from '@patternfly/react-icons';
const ContentEmpty = ({ title = '', message = '' }) => (
<EmptyState variant="full">
<EmptyStateIcon icon={CubesIcon} />
const ContentEmpty = ({
title = '',
message = '',
icon = CubesIcon,
className = '',
}) => (
<EmptyState variant="full" className={className}>
<EmptyStateIcon icon={icon} />
<Title size="lg" headingLevel="h3">
{title || t`No items found.`}
</Title>

View File

@ -0,0 +1,36 @@
import React, { useEffect } from 'react';
import 'styled-components/macro';
import { t } from '@lingui/macro';
import { SearchIcon } from '@patternfly/react-icons';
import ContentEmpty from 'components/ContentEmpty';
export default function EmptyOutput({
hasQueryParams,
isJobRunning,
onUnmount,
}) {
let title;
let message;
let icon;
useEffect(() => onUnmount);
if (hasQueryParams) {
title = t`The search filter did not produce any results…`;
message = t`Please try another search using the filter above`;
icon = SearchIcon;
} else if (isJobRunning) {
title = t`Waiting for job output…`;
} else {
title = t`No output found for this job.`;
}
return (
<ContentEmpty
css="height: 100%"
title={title}
message={message}
icon={icon}
/>
);
}

View File

@ -17,11 +17,15 @@ function JobEvent({
isCollapsed,
onToggleCollapsed,
hasChildren,
jobStatus,
}) {
const numOutputLines = lineTextHtml?.length || 0;
useEffect(() => {
measure();
}, [numOutputLines, isCollapsed, measure]);
const timeout = setTimeout(measure, 0);
return () => {
clearTimeout(timeout);
};
}, [numOutputLines, isCollapsed, measure, jobStatus]);
let toggleLineIndex = -1;
if (hasChildren) {

View File

@ -30,6 +30,7 @@ import JobEventSkeleton from './JobEventSkeleton';
import PageControls from './PageControls';
import HostEventModal from './HostEventModal';
import JobOutputSearch from './JobOutputSearch';
import EmptyOutput from './EmptyOutput';
import { HostStatusBar, OutputToolbar } from './shared';
import getLineTextHtml from './getLineTextHtml';
import connectJobSocket, { closeWebSocket } from './connectJobSocket';
@ -220,6 +221,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
...Object.values(siblingRequests.current || {}),
...Object.values(numEventsRequests.current || {}),
];
setHasContentLoading(true); // prevents "no content found" screen from flashing
Promise.all(pendingRequests).then(() => {
setRemoteRowCount(0);
clearLoadedEvents();
@ -509,6 +511,7 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
onToggleCollapsed={() => {
toggleNodeIsCollapsed(event.uuid, !node.isCollapsed);
}}
jobStatus={jobStatus}
/>
) : (
<JobEventSkeleton
@ -715,36 +718,54 @@ function JobOutput({ job, eventRelatedSearchableKeys, eventSearchableKeys }) {
rowCount={totalNonCollapsedRows + wsEvents.length}
minimumBatchSize={50}
>
{({ onRowsRendered, registerChild }) => (
<AutoSizer nonce={window.NONCE_ID} onResize={handleResize}>
{({ width, height }) => (
<>
{hasContentLoading ? (
<div style={{ width }}>
<ContentLoading />
</div>
) : (
<List
ref={(ref) => {
registerChild(ref);
listRef.current = ref;
}}
deferredMeasurementCache={cache}
height={height || 1}
onRowsRendered={onRowsRendered}
rowCount={totalNonCollapsedRows + wsEvents.length}
rowHeight={cache.rowHeight}
rowRenderer={rowRenderer}
scrollToAlignment="start"
width={width || 1}
overscanRowCount={20}
onScroll={handleScroll}
/>
)}
</>
)}
</AutoSizer>
)}
{({ onRowsRendered, registerChild }) => {
if (
!hasContentLoading &&
remoteRowCount + wsEvents.length === 0
) {
return (
<EmptyOutput
hasQueryParams={location.search.length > 1}
isJobRunning={isJobRunning(jobStatus)}
onUnmount={() => {
if (listRef.current?.recomputeRowHeights) {
listRef.current.recomputeRowHeights();
}
}}
/>
);
}
return (
<AutoSizer nonce={window.NONCE_ID} onResize={handleResize}>
{({ width, height }) => (
<>
{hasContentLoading ? (
<div style={{ width }}>
<ContentLoading />
</div>
) : (
<List
ref={(ref) => {
registerChild(ref);
listRef.current = ref;
}}
deferredMeasurementCache={cache}
height={height || 1}
onRowsRendered={onRowsRendered}
rowCount={totalNonCollapsedRows + wsEvents.length}
rowHeight={cache.rowHeight}
rowRenderer={rowRenderer}
scrollToAlignment="start"
width={width || 1}
overscanRowCount={20}
onScroll={handleScroll}
/>
)}
</>
)}
</AutoSizer>
);
}}
</InfiniteLoader>
<OutputFooter />
</OutputWrapper>