mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make column resize sorta-functioning
Signed-off-by: Alex Culliere <alozhkin@mirantis.com>
This commit is contained in:
parent
e7f37b359e
commit
42f68b5db3
@ -80,6 +80,10 @@ export interface ItemListLayoutProps<T extends ItemObject = ItemObject> {
|
||||
renderFooter?: (parent: ItemListLayout) => React.ReactNode;
|
||||
}
|
||||
|
||||
interface ItemListLayoutState {
|
||||
cellSizes: number[];
|
||||
}
|
||||
|
||||
const defaultProps: Partial<ItemListLayoutProps> = {
|
||||
showHeader: true,
|
||||
isSearchable: true,
|
||||
@ -96,9 +100,8 @@ const defaultProps: Partial<ItemListLayoutProps> = {
|
||||
};
|
||||
|
||||
@observer
|
||||
export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
export class ItemListLayout extends React.Component<ItemListLayoutProps, ItemListLayoutState> {
|
||||
static defaultProps = defaultProps as object;
|
||||
private cellSizes: Array<number>;
|
||||
|
||||
private storage = createStorage("item_list_layout", {
|
||||
showFilters: false, // setup defaults
|
||||
@ -114,7 +117,10 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
|
||||
constructor(props: ItemListLayoutProps) {
|
||||
super(props);
|
||||
this.cellSizes = new Array<number>(props.renderTableHeader.length);
|
||||
|
||||
this.state = {
|
||||
cellSizes: new Array<number>(props.renderTableHeader.length)
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
@ -215,6 +221,13 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
return this.applyFilters(filterItems.concat(this.props.filterItems), items);
|
||||
}
|
||||
|
||||
handleCellResize(index: number, width: number) {
|
||||
const cellSizes = [...this.state.cellSizes];
|
||||
|
||||
cellSizes[index] = width;
|
||||
this.setState({ cellSizes });
|
||||
}
|
||||
|
||||
@autobind()
|
||||
getRow(uid: string) {
|
||||
const {
|
||||
@ -249,7 +262,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
renderTableContents(item).map((content, index) => {
|
||||
const cellProps: TableCellProps = isReactNode(content) ? { children: content } : content;
|
||||
const headCell = renderTableHeader?.[index];
|
||||
const cellSize = this.cellSizes[index];
|
||||
const cellSize = this.state.cellSizes[index];
|
||||
|
||||
if (copyClassNameFromHeadCells && headCell) {
|
||||
cellProps.className = cssNames(cellProps.className, headCell.className);
|
||||
@ -259,8 +272,12 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
cellProps.size = cellSize;
|
||||
}
|
||||
|
||||
if (resizable) {
|
||||
cellProps._onResize = width => this.handleCellResize(index, width);
|
||||
}
|
||||
|
||||
if (!headCell || !this.isHiddenColumn(headCell)) {
|
||||
return <TableCell resizable key={index} {...cellProps} />;
|
||||
return <TableCell resizable={resizable} key={index} {...cellProps} />;
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -411,9 +428,9 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
/>
|
||||
)}
|
||||
{renderTableHeader.map((cellProps, index) => {
|
||||
const cellSize = this.cellSizes[index];
|
||||
const cellSize = this.state.cellSizes[index];
|
||||
const _cellProps = resizable ?
|
||||
{ ...cellProps, _onResize: (width: number) => this.cellSizes[index] = width } :
|
||||
{ ...cellProps, _onResize: (width: number) => this.handleCellResize(index, width), resizable } :
|
||||
cellProps;
|
||||
|
||||
if (cellSize !== undefined) {
|
||||
@ -421,7 +438,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||
}
|
||||
|
||||
if (!this.isHiddenColumn(cellProps)) {
|
||||
return <TableCell resizable key={cellProps.id ?? index} {..._cellProps} />;
|
||||
return <TableCell key={cellProps.id ?? index} {..._cellProps} />;
|
||||
}
|
||||
})}
|
||||
<TableCell className="menu">
|
||||
|
||||
@ -46,6 +46,7 @@ export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutPr
|
||||
|
||||
return (
|
||||
<ItemListLayout
|
||||
resizable
|
||||
{...layoutProps}
|
||||
className={cssNames("KubeObjectListLayout", className)}
|
||||
store={store}
|
||||
|
||||
@ -2,6 +2,7 @@ import "./table-cell.scss";
|
||||
import type { TableSortBy, TableSortParams } from "./table";
|
||||
|
||||
import React, { ReactNode } from "react";
|
||||
import { throttle } from "lodash";
|
||||
import { autobind, cssNames, displayBooleans } from "../../utils";
|
||||
import { Icon } from "../icon";
|
||||
import { Checkbox } from "../checkbox";
|
||||
@ -25,7 +26,16 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
|
||||
_onResize?(width: number): void; // <Table> resize callbalck, don't use this prop outside (!)
|
||||
}
|
||||
|
||||
type ResizeHandlerState = {
|
||||
mousePosX: number,
|
||||
currentColumn?: HTMLDivElement;
|
||||
nextColumn?: HTMLDivElement;
|
||||
};
|
||||
|
||||
export class TableCell extends React.Component<TableCellProps> {
|
||||
private resizeHandlerState?: ResizeHandlerState;
|
||||
private cellContainer: React.RefObject<HTMLDivElement> = React.createRef();
|
||||
|
||||
@autobind()
|
||||
onClick(evt: React.MouseEvent<HTMLDivElement>) {
|
||||
if (this.props.onClick) {
|
||||
@ -37,6 +47,10 @@ export class TableCell extends React.Component<TableCellProps> {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.removeMouseEventListeners();
|
||||
}
|
||||
|
||||
get isSortable() {
|
||||
const { _sorting, sortBy } = this.props;
|
||||
|
||||
@ -67,8 +81,34 @@ export class TableCell extends React.Component<TableCellProps> {
|
||||
}
|
||||
}
|
||||
|
||||
addMouseEventListeners() {
|
||||
document.addEventListener("mousemove", this.mouseMoveHandler.bind(this));
|
||||
document.addEventListener("mouseup", this.mouseUpHandler.bind(this));
|
||||
}
|
||||
|
||||
removeMouseEventListeners() {
|
||||
document.removeEventListener("mousemove", this.mouseMoveHandler.bind(this));
|
||||
document.removeEventListener("mouseup", this.mouseUpHandler.bind(this));
|
||||
}
|
||||
|
||||
mouseMoveHandler(event: MouseEvent) {
|
||||
if (!this.resizeHandlerState) {
|
||||
return;
|
||||
}
|
||||
|
||||
const diffPosX = event.pageX - this.resizeHandlerState.mousePosX;
|
||||
const currentWidth = this.cellContainer.current.offsetWidth;
|
||||
|
||||
this.props?._onResize(currentWidth + diffPosX);
|
||||
}
|
||||
|
||||
mouseUpHandler() {
|
||||
this.removeMouseEventListeners();
|
||||
this.resizeHandlerState = undefined;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { className, checkbox, isChecked, resizable, size, sortBy, _sort, _sorting, _nowrap, children, title, renderBoolean: displayBoolean, showWithColumn, ...cellProps } = this.props;
|
||||
const { className, checkbox, isChecked, resizable, size, sortBy, _sort, _sorting, _nowrap, children, title, renderBoolean: displayBoolean, showWithColumn, _onResize, ...cellProps } = this.props;
|
||||
const classNames = cssNames("TableCell", className, {
|
||||
checkbox,
|
||||
nowrap: _nowrap,
|
||||
@ -78,13 +118,21 @@ export class TableCell extends React.Component<TableCellProps> {
|
||||
const cellStyle: React.CSSProperties = size !== undefined ?
|
||||
{ flexBasis: `${size}px` } :
|
||||
{};
|
||||
const resizeHandlers: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> = {
|
||||
onMouseDown: event => {
|
||||
this.addMouseEventListeners();
|
||||
this.resizeHandlerState = {
|
||||
mousePosX: event.pageX
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={cellStyle} {...cellProps} className={classNames} onClick={this.onClick}>
|
||||
<div ref={this.cellContainer} style={cellStyle} {...cellProps} className={classNames} onClick={this.onClick}>
|
||||
{this.renderCheckbox()}
|
||||
{_nowrap ? <div className="content">{content}</div> : content}
|
||||
{this.renderSortIcon()}
|
||||
{resizable && <span className="resize-anchor"></span>}
|
||||
{resizable && <span {...resizeHandlers} className="resize-anchor"></span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user