1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

refactoring & fixes

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-03-29 20:21:03 +03:00
parent 85ddcb47b4
commit 3b40f044b4
8 changed files with 135 additions and 66 deletions

View File

@ -14,9 +14,6 @@
.VirtualList {
height: 100%;
.list {
overflow-x: scroll!important;
.LogRow {
padding: 2px 16px;
height: 18px; // Must be equal to lineHeight variable in pod-log-list.tsx
@ -51,7 +48,6 @@
}
}
}
}
&.isLoading {
cursor: wait;

View File

@ -407,10 +407,12 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
)}
{renderTableHeader.map((cellProps, index) => {
if (!this.isHiddenColumn(cellProps)) {
const storageId = cellProps.id ?? cellProps.storageId;
return (
<TableCell
key={cellProps.id ?? cellProps.storageId ?? index}
storageId={cellProps.storageId}
key={storageId ?? index}
storageId={storageId}
tableId={tableId} {...cellProps}
/>
);

View File

@ -19,8 +19,37 @@
}
}
&.warning {
flex: 0 0 40px !important;
}
&.resizable {
position: relative; // required for resizing-anchor with `position:absolute`
min-width: 50px;
> .ResizingAnchor {
width: 18px;
}
.TableHead:hover & {
> .ResizingAnchor {
opacity: .25;
&:hover {
opacity: .75;
}
&:after {
font: 20px "Material Icons";
content: "compress";
position: absolute;
left: -8px;
top: 10px;
transform: rotate(90deg);
transform-origin: center;
}
}
}
&.resizing {
filter: invert(50%);

View File

@ -27,9 +27,9 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
title?: ReactNode;
/**
* Allow to resize width and save to local storage, default: true
* (applicable only with props.id)
*/
isResizable?: boolean;
onResizeEnd?: () => void;
checkbox?: boolean; // render cell with a checkbox
isChecked?: boolean; // mark checkbox as checked or not
renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean"
@ -43,7 +43,7 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
@observer
export class TableCell extends React.Component<TableCellProps> {
private elem: HTMLElement;
@observable.ref elem?: HTMLElement;
static defaultProps: TableCellProps = {
isResizable: true,
@ -97,7 +97,9 @@ export class TableCell extends React.Component<TableCellProps> {
}
@computed get columnSize(): number {
return getColumnSize(this.props.tableId, this.columnId) ?? 0;
const savedSize = getColumnSize(this.props.tableId, this.columnId);
return savedSize ?? this.elem?.offsetWidth;
}
@computed get isResizable(): boolean {
@ -113,6 +115,7 @@ export class TableCell extends React.Component<TableCellProps> {
if (this.isResizable && this.columnSize) {
styles.flexGrow = 0;
styles.flexShrink = 0;
styles.flexBasis = this.columnSize;
}
@ -123,10 +126,20 @@ export class TableCell extends React.Component<TableCellProps> {
onResize(extent: number) {
const { tableId } = this.props;
const { columnId } = this;
const size = extent || this.elem?.offsetWidth;
// persist state in storage
setColumnSize({ tableId, columnId, size });
setColumnSize({ tableId, columnId, size: extent });
}
@autobind()
onResizeStart() {
this.isResizing = true;
}
@autobind()
onResizeEnd() {
this.isResizing = false;
this.props.onResizeEnd?.();
}
@autobind()
@ -136,7 +149,7 @@ export class TableCell extends React.Component<TableCellProps> {
render() {
const {
className, checkbox, isChecked, isResizable, sortBy,
className, checkbox, isChecked, isResizable, sortBy, onResizeEnd,
_sort, _sorting, _nowrap, children, title, tableId, storageId,
renderBoolean: displayBoolean, showWithColumn,
...cellProps
@ -147,7 +160,7 @@ export class TableCell extends React.Component<TableCellProps> {
nowrap: _nowrap,
sorting: this.isSortable,
resizing: this.isResizing,
resizable: isResizable,
resizable: this.isResizable,
});
const content = displayBooleans(displayBoolean, title || children);
@ -158,12 +171,13 @@ export class TableCell extends React.Component<TableCellProps> {
{this.renderSortIcon()}
{this.isResizable && (
<ResizingAnchor
minExtent={50}
direction={ResizeDirection.HORIZONTAL}
placement={ResizeSide.TRAILING}
growthDirection={ResizeGrowthDirection.LEFT_TO_RIGHT}
getCurrentExtent={() => this.columnSize}
onStart={() => this.isResizing = true}
onEnd={() => this.isResizing = false}
onStart={this.onResizeStart}
onEnd={this.onResizeEnd}
onDrag={this.onResize}
/>
)}

View File

@ -10,6 +10,7 @@ export interface TableHeadProps extends React.DOMAttributes<HTMLDivElement> {
showTopLine?: boolean; // show border line at the top
sticky?: boolean; // keep header on top when scrolling
nowrap?: boolean; // white-space: nowrap, align inner <TableCell> in one line
style?: React.CSSProperties;
}
export class TableHead extends React.Component<TableHeadProps> {

View File

@ -1,7 +1,7 @@
import "./table.scss";
import React from "react";
import { orderBy } from "lodash";
import { orderBy, throttle } from "lodash";
import { observer } from "mobx-react";
import { observable } from "mobx";
import { autobind, cssNames, noop } from "../../utils";
@ -57,6 +57,8 @@ export const orderByUrlParam = createPageParam({
@observer
export class Table extends React.Component<TableProps> {
@observable.ref elemRef = React.createRef<HTMLDivElement>();
static defaultProps: TableProps = {
scrollable: true,
autoSize: true,
@ -73,6 +75,14 @@ export class Table extends React.Component<TableProps> {
this.props.sortByDefault,
);
componentDidMount() {
window.addEventListener("resize", this.refreshDimensions);
}
componentWillUnmount() {
window.removeEventListener("resize", this.refreshDimensions);
}
renderHead() {
const { sortable, children } = this.props;
const content = React.Children.toArray(children) as (TableRowElem | TableHeadElem)[];
@ -83,6 +93,10 @@ export class Table extends React.Component<TableProps> {
const columns = React.Children.toArray(headElem.props.children) as TableCellElem[];
return React.cloneElement(headElem, {
style: {
...(headElem.props.style ?? {}),
width: this.contentWidth,
},
children: columns.map(elem => {
if (elem.props.checkbox) {
return elem;
@ -98,6 +112,10 @@ export class Table extends React.Component<TableProps> {
_sort: this.sort,
_sorting: this.sortParams,
_nowrap: headElem.props.nowrap,
onResizeEnd: () => {
elem.props.onResizeEnd?.();
this.refreshDimensions();
}
});
})
});
@ -180,6 +198,10 @@ export class Table extends React.Component<TableProps> {
getRow={getTableRow}
selectedItemId={selectedItemId}
className={className}
// must match to table's content width for proper scrolling header and virtual-list items.
// required if some column(s) are resized and overall content-area more than 100%.
// why: table & virtual-list has own scrolling areas and table-head is sticky..
width={this.contentWidth}
/>
);
}
@ -187,16 +209,25 @@ export class Table extends React.Component<TableProps> {
return rows;
}
render() {
const { selectable, scrollable, sortable, autoSize, virtual } = this.props;
let { className } = this.props;
@observable refreshKey: number;
className = cssNames("Table flex column", className, {
get contentWidth() {
return this.elemRef.current?.scrollWidth;
}
refreshDimensions = throttle(() => {
// using "full refresh" with changing "key" as this.forceUpdate() don't update some internals
this.refreshKey = Math.random();
}, 250);
render() {
const { selectable, scrollable, sortable, autoSize, virtual, className } = this.props;
const classNames = cssNames("Table flex column", className, {
selectable, scrollable, sortable, autoSize, virtual,
});
return (
<div className={className}>
<div key={this.refreshKey} className={classNames} ref={this.elemRef}>
{this.renderHead()}
{this.renderRows()}
</div>

View File

@ -1,7 +1,4 @@
.VirtualList {
overflow: hidden;
> .list {
overflow-x: hidden !important;
overflow-y: overlay !important;
}
}

View File

@ -32,7 +32,7 @@ interface State {
}
const defaultProps: Partial<Props> = {
width: "100%",
width: "auto",
initialOffset: 1,
readyOffset: 10,
onScroll: noop
@ -52,7 +52,7 @@ export class VirtualList extends Component<Props, State> {
componentDidMount() {
this.setListHeight();
this.scrollToSelectedItem();
new ResizeSensor(this.parentRef.current as any as Element, this.setListHeight);
new ResizeSensor(this.parentRef.current, this.setListHeight);
this.setState({ overscanCount: this.props.readyOffset });
}
@ -100,9 +100,8 @@ export class VirtualList extends Component<Props, State> {
};
return (
<div className={cssNames("VirtualList", className)} ref={this.parentRef}>
<VariableSizeList
className="list"
className={cssNames("VirtualList", className)}
width={width}
height={height}
itemSize={this.getItemSize}
@ -110,12 +109,12 @@ export class VirtualList extends Component<Props, State> {
itemData={rowData}
overscanCount={overscanCount}
ref={this.listRef}
innerRef={this.parentRef}
outerRef={outerRef}
onScroll={onScroll}
>
{Row}
</VariableSizeList>
</div>
);
}
}