From ae4dc3023c6bcc660e0f3e1d8ae0daab91641c37 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Fri, 27 Nov 2020 14:38:14 +0300 Subject: [PATCH] Refactoring VirtualList types Signed-off-by: Alex Andreev --- src/extensions/renderer-api/components.ts | 1 + .../components/+cluster/cluster-issues.tsx | 4 +-- .../endpoint-subset-list.tsx | 15 ++++------- .../+workloads-pods/pod-details-list.tsx | 6 ++--- .../item-object-list/item-list-layout.tsx | 6 ++--- src/renderer/components/table/table.tsx | 23 ++++++++++++++--- .../components/virtual-list/virtual-list.tsx | 25 ++++++------------- 7 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/extensions/renderer-api/components.ts b/src/extensions/renderer-api/components.ts index 242799c749..f1118074f2 100644 --- a/src/extensions/renderer-api/components.ts +++ b/src/extensions/renderer-api/components.ts @@ -36,3 +36,4 @@ export * from "../../renderer/components/+events/kube-event-details"; export * from "../../renderer/components/status-brick"; export { terminalStore, createTerminalTab } from "../../renderer/components/dock/terminal.store"; export { createPodLogsTab } from "../../renderer/components/dock/pod-logs.store"; +export { ItemObject } from "../../renderer/item.store"; diff --git a/src/renderer/components/+cluster/cluster-issues.tsx b/src/renderer/components/+cluster/cluster-issues.tsx index a2959cda20..80d8362ed1 100644 --- a/src/renderer/components/+cluster/cluster-issues.tsx +++ b/src/renderer/components/+cluster/cluster-issues.tsx @@ -73,9 +73,7 @@ export class ClusterIssues extends React.Component { } @autobind() - getTableRow(uid: string) { - const { warnings } = this; - const warning = warnings.find(warn => warn.getId() == uid); + getTableRow(warning: IWarning) { const { getId, getName, message, kind, selfLink } = warning; return ( { - getAddressTableRow(ip: string) { - const { subset } = this.props; - const address = subset.getAddresses().find(address => address.getId() == ip); + getAddressTableRow(address: EndpointAddress) { return this.renderAddressTableRow(address); } @autobind() - getNotReadyAddressTableRow(ip: string) { - const { subset} = this.props; - const address = subset.getNotReadyAddresses().find(address => address.getId() == ip); + getNotReadyAddressTableRow(address: EndpointAddress) { return this.renderAddressTableRow(address); } @@ -52,7 +47,7 @@ export class EndpointSubsetList extends React.Component { Target { - !virtual && addresses.map(address => this.getAddressTableRow(address.getId())) + !virtual && addresses.map(address => this.getAddressTableRow(address)) } @@ -105,7 +100,7 @@ export class EndpointSubsetList extends React.Component { Hostname Target - { !addressesVirtual && addresses.map(address => this.getAddressTableRow(address.getId())) } + { !addressesVirtual && addresses.map(this.getAddressTableRow) } )} @@ -126,7 +121,7 @@ export class EndpointSubsetList extends React.Component { Hostname Target - { !notReadyAddressesVirtual && notReadyAddresses.map(address => this.getNotReadyAddressTableRow(address.getId())) } + { !notReadyAddressesVirtual && notReadyAddresses.map(this.getNotReadyAddressTableRow) } )} diff --git a/src/renderer/components/+workloads-pods/pod-details-list.tsx b/src/renderer/components/+workloads-pods/pod-details-list.tsx index 111562d06a..e092bb8fe5 100644 --- a/src/renderer/components/+workloads-pods/pod-details-list.tsx +++ b/src/renderer/components/+workloads-pods/pod-details-list.tsx @@ -95,9 +95,7 @@ export class PodDetailsList extends React.Component { } @autobind() - getTableRow(uid: string) { - const { pods } = this.props; - const pod = pods.find(pod => pod.getId() == uid); + getTableRow(pod: Pod) { const metrics = podsStore.getPodKubeMetrics(pod); return ( { Status { - !virtual && pods.map(pod => this.getTableRow(pod.getId())) + !virtual && pods.map(pod => this.getTableRow(pod)) } diff --git a/src/renderer/components/item-object-list/item-list-layout.tsx b/src/renderer/components/item-object-list/item-list-layout.tsx index 9fbcb54add..0a9b5f8202 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -198,15 +198,13 @@ export class ItemListLayout extends React.Component { } @autobind() - getRow(uid: string) { + getRow(item: ItemObject) { const { isSelectable, renderTableHeader, renderTableContents, renderItemMenu, store, hasDetailsView, onDetails, copyClassNameFromHeadCells, customizeTableRowProps, detailsItem, } = this.props; const { isSelected } = store; - const item = this.items.find(item => item.getId() == uid); - if (!item) return; const itemId = item.getId(); return ( { )} { - !virtual && items.map(item => this.getRow(item.getId())) + !virtual && items.map((item) => this.getRow(item)) } )} diff --git a/src/renderer/components/table/table.tsx b/src/renderer/components/table/table.tsx index 61b3be3cfc..fa7c5859cf 100644 --- a/src/renderer/components/table/table.tsx +++ b/src/renderer/components/table/table.tsx @@ -9,8 +9,9 @@ import { TableHead, TableHeadElem, TableHeadProps } from "./table-head"; import { TableCellElem } from "./table-cell"; import { VirtualList } from "../virtual-list"; import { navigation, setQueryParams } from "../../navigation"; -import orderBy from "lodash/orderBy"; import { ItemObject } from "../../item.store"; +import orderBy from "lodash/orderBy"; +import debounce from "lodash/debounce"; // todo: refactor + decouple search from location @@ -20,7 +21,7 @@ export type TableSortParams = { sortBy: TableSortBy; orderBy: TableOrderBy }; export type TableSortCallback = (data: D) => string | number | (string | number)[]; export interface TableProps extends React.DOMAttributes { - items?: any[]; // Raw items data + items?: ItemObject[]; // Raw items data className?: string; autoSize?: boolean; // Setup auto-sizing for all columns (flex: 1 0) selectable?: boolean; // Highlight rows on hover @@ -40,7 +41,7 @@ export interface TableProps extends React.DOMAttributes { rowPadding?: string; rowLineHeight?: string; customRowHeights?: (item: object, lineHeight: number, paddings: number) => number; - getTableRow?: (uid: string | number) => React.ReactElement; + getTableRow?: (item: ItemObject) => React.ReactElement; } @observer @@ -55,6 +56,8 @@ export class Table extends React.Component { @observable sortParamsLocal = this.props.sortByDefault; + private virtualListRef = React.createRef(); + @computed get sortParams(): Partial { if (this.props.sortSyncWithUrl) { const sortBy = navigation.searchParams.get("sortBy"); @@ -64,6 +67,19 @@ export class Table extends React.Component { return this.sortParamsLocal || {}; } + componentDidMount() { + this.scrollToSelectedItem(); + } + + scrollToSelectedItem = debounce(() => { + const { items, selectedItemId, sortable } = this.props; + if (!selectedItemId) return; + const sortedItems = sortable ? this.getSorted(items) : items; + const index = sortedItems.findIndex(item => item.getId() == selectedItemId); + if (index === -1) return; + this.virtualListRef.current.scrollToItem(index, "start"); + }); + renderHead() { const { sortable, children } = this.props; const content = React.Children.toArray(children) as (TableRowElem | TableHeadElem)[]; @@ -162,6 +178,7 @@ export class Table extends React.Component { getRow={getTableRow} selectedItemId={selectedItemId} className={className} + ref={this.virtualListRef} /> ); } diff --git a/src/renderer/components/virtual-list/virtual-list.tsx b/src/renderer/components/virtual-list/virtual-list.tsx index 4175c50474..849b753987 100644 --- a/src/renderer/components/virtual-list/virtual-list.tsx +++ b/src/renderer/components/virtual-list/virtual-list.tsx @@ -6,22 +6,19 @@ import React, { Component } from "react"; import { observer } from "mobx-react"; import { Align, ListChildComponentProps, ListOnScrollProps, VariableSizeList } from "react-window"; import { cssNames, noop } from "../../utils"; -import { TableRowProps } from "../table/table-row"; -import { ItemObject } from "../../item.store"; import throttle from "lodash/throttle"; -import debounce from "lodash/debounce"; import isEqual from "lodash/isEqual"; import ResizeSensor from "css-element-queries/src/ResizeSensor"; -interface Props { - items: T[]; +interface Props { + items: any[]; rowHeights: number[]; className?: string; width?: number | string; initialOffset?: number; readyOffset?: number; selectedItemId?: string; - getRow?: (uid: string | number) => React.ReactElement; + getRow: (item: any) => React.ReactElement; onScroll?: (props: ListOnScrollProps) => void; outerRef?: React.Ref } @@ -51,7 +48,6 @@ export class VirtualList extends Component { componentDidMount() { this.setListHeight(); - this.scrollToSelectedItem(); new ResizeSensor(this.parentRef.current as any as Element, this.setListHeight); this.setState({ overscanCount: this.props.readyOffset }); } @@ -75,13 +71,6 @@ export class VirtualList extends Component { getItemSize = (index: number) => this.props.rowHeights[index]; - scrollToSelectedItem = debounce(() => { - if (!this.props.selectedItemId) return; - const { items, selectedItemId } = this.props; - const index = items.findIndex(item => item.getId() == selectedItemId); - if (index === -1) return; - this.listRef.current.scrollToItem(index, "start"); - }); scrollToItem = (index: number, align: Align) => { this.listRef.current.scrollToItem(index, align); @@ -115,8 +104,8 @@ export class VirtualList extends Component { } interface RowData { - items: ItemObject[]; - getRow?: (uid: string | number) => React.ReactElement; + items: any[]; + getRow?: (item: any) => React.ReactElement; } interface RowProps extends ListChildComponentProps { @@ -126,8 +115,8 @@ interface RowProps extends ListChildComponentProps { const Row = observer((props: RowProps) => { const { index, style, data } = props; const { items, getRow } = data; - const uid = items[index]?.getId ? items[index].getId() : index; - const row = getRow(uid); + const item = items[index]; + const row = getRow(item); if (!row) return null; return React.cloneElement(row, { style: Object.assign({}, row.props.style, style)