mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix PodDetailsList being empty over 100 pods (#4096)
This commit is contained in:
parent
3fc9436a2e
commit
d5719f29b8
@ -51,26 +51,14 @@ interface Props extends OptionalProps {
|
||||
interface OptionalProps {
|
||||
maxCpu?: number;
|
||||
maxMemory?: number;
|
||||
showTitle?: boolean;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class PodDetailsList extends React.Component<Props> {
|
||||
static defaultProps: OptionalProps = {
|
||||
showTitle: true
|
||||
};
|
||||
|
||||
private metricsWatcher = interval(120, () => {
|
||||
podsStore.loadKubeMetrics(this.props.owner.getNs());
|
||||
});
|
||||
|
||||
private sortingCallbacks = {
|
||||
[sortBy.name]: (pod: Pod) => pod.getName(),
|
||||
[sortBy.namespace]: (pod: Pod) => pod.getNs(),
|
||||
[sortBy.cpu]: (pod: Pod) => podsStore.getPodKubeMetrics(pod).cpu,
|
||||
[sortBy.memory]: (pod: Pod) => podsStore.getPodKubeMetrics(pod).memory,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.metricsWatcher.start(true);
|
||||
disposeOnUnmount(this, [
|
||||
@ -144,27 +132,43 @@ export class PodDetailsList extends React.Component<Props> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { pods, showTitle } = this.props;
|
||||
const virtual = pods.length > 100;
|
||||
const { pods } = this.props;
|
||||
|
||||
if (!pods.length && !podsStore.isLoaded) return (
|
||||
<div className="PodDetailsList flex justify-center"><Spinner/></div>
|
||||
);
|
||||
if (!pods.length) return null;
|
||||
if (!podsStore.isLoaded) {
|
||||
return (
|
||||
<div className="PodDetailsList flex justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!pods.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const virtual = pods.length > 20;
|
||||
|
||||
return (
|
||||
<div className="PodDetailsList flex column">
|
||||
{showTitle && <DrawerTitle title="Pods"/>}
|
||||
<DrawerTitle title="Pods" />
|
||||
<Table
|
||||
tableId="workloads_pod_details_list"
|
||||
items={pods}
|
||||
selectable
|
||||
virtual={virtual}
|
||||
scrollable={false}
|
||||
sortable={this.sortingCallbacks}
|
||||
virtual={virtual}
|
||||
// 660 is the exact hight required for 20 items with the default paddings
|
||||
virtualHeight={660}
|
||||
sortable={{
|
||||
[sortBy.name]: pod => pod.getName(),
|
||||
[sortBy.namespace]: pod => pod.getNs(),
|
||||
[sortBy.cpu]: pod => podsStore.getPodKubeMetrics(pod).cpu,
|
||||
[sortBy.memory]: pod => podsStore.getPodKubeMetrics(pod).memory,
|
||||
}}
|
||||
sortByDefault={{ sortBy: sortBy.cpu, orderBy: "desc" }}
|
||||
sortSyncWithUrl={false}
|
||||
getTableRow={this.getTableRow}
|
||||
renderRow={!virtual && (pod => this.getTableRow(pod.getId()))}
|
||||
className="box grow"
|
||||
>
|
||||
<TableHead>
|
||||
@ -176,9 +180,6 @@ export class PodDetailsList extends React.Component<Props> {
|
||||
<TableCell className="memory" sortBy={sortBy.memory}>Memory</TableCell>
|
||||
<TableCell className="status">Status</TableCell>
|
||||
</TableHead>
|
||||
{
|
||||
!virtual && pods.map(pod => this.getTableRow(pod.getId()))
|
||||
}
|
||||
</Table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -57,9 +57,26 @@ export interface TableProps<Item> extends React.DOMAttributes<HTMLDivElement> {
|
||||
onSort?: (params: TableSortParams) => void; // callback on sort change, default: global sync with url
|
||||
noItems?: React.ReactNode; // Show no items state table list is empty
|
||||
selectedItemId?: string; // Allows to scroll list to selected item
|
||||
virtual?: boolean; // Use virtual list component to render only visible rows
|
||||
rowPadding?: string;
|
||||
rowLineHeight?: string;
|
||||
|
||||
/**
|
||||
* Use virtual list component to render only visible rows. By default uses a
|
||||
* auto sizer to fill available height
|
||||
*/
|
||||
virtual?: boolean;
|
||||
/**
|
||||
* Only used when virtual is true. Sets the virtual list to be a fixed height.
|
||||
* Needed when used in contexts that already have a parent component that
|
||||
* is `overflow-y: scroll`,
|
||||
*/
|
||||
virtualHeight?: number;
|
||||
/**
|
||||
* Row padding in pixels
|
||||
*/
|
||||
rowPadding?: number;
|
||||
/**
|
||||
* Row line height in pixels
|
||||
*/
|
||||
rowLineHeight?: number;
|
||||
customRowHeights?: (item: Item, lineHeight: number, paddings: number) => number;
|
||||
getTableRow?: (uid: string) => React.ReactElement<TableRowProps>;
|
||||
renderRow?: (item: Item) => React.ReactElement<TableRowProps>;
|
||||
@ -78,9 +95,10 @@ export class Table<Item> extends React.Component<TableProps<Item>> {
|
||||
static defaultProps: TableProps<any> = {
|
||||
scrollable: true,
|
||||
autoSize: true,
|
||||
rowPadding: "8px",
|
||||
rowLineHeight: "17px",
|
||||
rowPadding: 8,
|
||||
rowLineHeight: 17,
|
||||
sortSyncWithUrl: true,
|
||||
customRowHeights: (item, lineHeight, paddings) => lineHeight + paddings,
|
||||
};
|
||||
|
||||
constructor(props: TableProps<Item>) {
|
||||
@ -185,7 +203,10 @@ export class Table<Item> extends React.Component<TableProps<Item>> {
|
||||
}
|
||||
|
||||
renderRows() {
|
||||
const { noItems, virtual, customRowHeights, rowLineHeight, rowPadding, items, getTableRow, selectedItemId, className } = this.props;
|
||||
const {
|
||||
noItems, virtual, customRowHeights, rowLineHeight, rowPadding, items,
|
||||
getTableRow, selectedItemId, className, virtualHeight
|
||||
} = this.props;
|
||||
const content = this.getContent();
|
||||
let rows: React.ReactElement<TableRowProps>[] = content.filter(elem => elem.type === TableRow);
|
||||
let sortedItems = rows.length ? rows.map(row => row.props.sortItem) : [...items];
|
||||
@ -194,9 +215,7 @@ export class Table<Item> extends React.Component<TableProps<Item>> {
|
||||
sortedItems = this.getSorted(sortedItems);
|
||||
|
||||
if (rows.length) {
|
||||
rows = sortedItems.map(item => rows.find(row => {
|
||||
return item == row.props.sortItem;
|
||||
}));
|
||||
rows = sortedItems.map(item => rows.find(row => item == row.props.sortItem));
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,15 +224,7 @@ export class Table<Item> extends React.Component<TableProps<Item>> {
|
||||
}
|
||||
|
||||
if (virtual) {
|
||||
const lineHeight = parseFloat(rowLineHeight);
|
||||
const padding = parseFloat(rowPadding);
|
||||
let rowHeights: number[] = Array(items.length).fill(lineHeight + padding * 2);
|
||||
|
||||
if (customRowHeights) {
|
||||
rowHeights = sortedItems.map(item => {
|
||||
return customRowHeights(item, lineHeight, padding * 2);
|
||||
});
|
||||
}
|
||||
const rowHeights = sortedItems.map(item => customRowHeights(item, rowLineHeight, rowPadding * 2));
|
||||
|
||||
return (
|
||||
<VirtualList
|
||||
@ -222,6 +233,7 @@ export class Table<Item> extends React.Component<TableProps<Item>> {
|
||||
getRow={getTableRow}
|
||||
selectedItemId={selectedItemId}
|
||||
className={className}
|
||||
fixedHeight={virtualHeight}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@ interface Props<T extends ItemObject = any> {
|
||||
getRow?: (uid: string | number) => React.ReactElement<any>;
|
||||
onScroll?: (props: ListOnScrollProps) => void;
|
||||
outerRef?: React.Ref<any>
|
||||
|
||||
/**
|
||||
* If specified then AutoSizer will not be used and instead a fixed height
|
||||
* virtual list will be rendered
|
||||
*/
|
||||
fixedHeight?: number;
|
||||
}
|
||||
|
||||
interface State {
|
||||
@ -98,34 +104,45 @@ export class VirtualList extends Component<Props, State> {
|
||||
this.listRef.current?.scrollToItem(index, align);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { width, className, items, getRow, onScroll, outerRef } = this.props;
|
||||
renderList(height: number | undefined) {
|
||||
const { width, items, getRow, onScroll, outerRef } = this.props;
|
||||
const { overscanCount } = this.state;
|
||||
const rowData: RowData = {
|
||||
items,
|
||||
getRow
|
||||
};
|
||||
|
||||
return (
|
||||
<VariableSizeList
|
||||
className="list"
|
||||
width={width}
|
||||
height={height}
|
||||
itemSize={this.getItemSize}
|
||||
itemCount={items.length}
|
||||
itemData={{
|
||||
items,
|
||||
getRow
|
||||
}}
|
||||
overscanCount={overscanCount}
|
||||
ref={this.listRef}
|
||||
outerRef={outerRef}
|
||||
onScroll={onScroll}
|
||||
>
|
||||
{Row}
|
||||
</VariableSizeList>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, fixedHeight } = this.props;
|
||||
|
||||
return (
|
||||
<div className={cssNames("VirtualList", className)}>
|
||||
<AutoSizer disableWidth>
|
||||
{({ height }) => (
|
||||
<VariableSizeList
|
||||
className="list"
|
||||
width={width}
|
||||
height={height}
|
||||
itemSize={this.getItemSize}
|
||||
itemCount={items.length}
|
||||
itemData={rowData}
|
||||
overscanCount={overscanCount}
|
||||
ref={this.listRef}
|
||||
outerRef={outerRef}
|
||||
onScroll={onScroll}
|
||||
>
|
||||
{Row}
|
||||
</VariableSizeList>
|
||||
)}
|
||||
</AutoSizer>
|
||||
{
|
||||
typeof fixedHeight === "number"
|
||||
? this.renderList(fixedHeight)
|
||||
: (
|
||||
<AutoSizer disableWidth>
|
||||
{({ height }) => this.renderList(height)}
|
||||
</AutoSizer>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user