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

Setup resize functionality for table cells

Signed-off-by: Alex Culliere <alozhkin@mirantis.com>
This commit is contained in:
Alex Culliere 2021-02-12 15:21:53 +02:00
parent 62c3501011
commit e7f37b359e
3 changed files with 46 additions and 6 deletions

View File

@ -30,9 +30,21 @@
}
.TableCell {
position: relative;
&.menu {
@include table-cell-action;
}
.resize-anchor {
position: absolute;
top: 0;
right: 0;
min-width: 5px;
user-select: none;
cursor: col-resize;
background-color: gray;
height: -webkit-fill-available;
}
}
}

View File

@ -44,6 +44,7 @@ export interface ItemListLayoutProps<T extends ItemObject = ItemObject> {
preloadStores?: boolean;
isClusterScoped?: boolean;
hideFilters?: boolean;
resizable?: boolean;
searchFilters?: SearchFilter<T>[];
/** @deprecated */
filterItems?: ItemsFilter<T>[];
@ -97,6 +98,7 @@ const defaultProps: Partial<ItemListLayoutProps> = {
@observer
export class ItemListLayout extends React.Component<ItemListLayoutProps> {
static defaultProps = defaultProps as object;
private cellSizes: Array<number>;
private storage = createStorage("item_list_layout", {
showFilters: false, // setup defaults
@ -110,6 +112,11 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
this.storage.merge({ showFilters });
}
constructor(props: ItemListLayoutProps) {
super(props);
this.cellSizes = new Array<number>(props.renderTableHeader.length);
}
async componentDidMount() {
const { isClusterScoped, isConfigurable, tableId, preloadStores } = this.props;
@ -212,7 +219,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
getRow(uid: string) {
const {
isSelectable, renderTableHeader, renderTableContents, renderItemMenu,
store, hasDetailsView, onDetails,
store, hasDetailsView, onDetails, resizable,
copyClassNameFromHeadCells, customizeTableRowProps, detailsItem,
} = this.props;
const { isSelected } = store;
@ -242,13 +249,18 @@ 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];
if (copyClassNameFromHeadCells && headCell) {
cellProps.className = cssNames(cellProps.className, headCell.className);
}
if (cellSize !== undefined) {
cellProps.size = cellSize;
}
if (!headCell || !this.isHiddenColumn(headCell)) {
return <TableCell key={index} {...cellProps} />;
return <TableCell resizable key={index} {...cellProps} />;
}
})
}
@ -381,7 +393,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
}
renderTableHeader() {
const { customizeTableRowProps, renderTableHeader, isSelectable, isConfigurable, store } = this.props;
const { customizeTableRowProps, renderTableHeader, isSelectable, isConfigurable, store, resizable } = this.props;
if (!renderTableHeader) {
return;
@ -399,8 +411,17 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
/>
)}
{renderTableHeader.map((cellProps, index) => {
const cellSize = this.cellSizes[index];
const _cellProps = resizable ?
{ ...cellProps, _onResize: (width: number) => this.cellSizes[index] = width } :
cellProps;
if (cellSize !== undefined) {
_cellProps.size = cellSize;
}
if (!this.isHiddenColumn(cellProps)) {
return <TableCell key={cellProps.id ?? index} {...cellProps} />;
return <TableCell resizable key={cellProps.id ?? index} {..._cellProps} />;
}
})}
<TableCell className="menu">

View File

@ -12,6 +12,8 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
id?: string; // used for configuration visibility of columns
className?: string;
title?: ReactNode;
resizable?: boolean; // allow resizing
size?: number; // set horizontal size
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"
@ -20,6 +22,7 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
_sorting?: Partial<TableSortParams>; // <Table> sorting state, don't use this prop outside (!)
_sort?(sortBy: TableSortBy): void; // <Table> sort function, don't use this prop outside (!)
_nowrap?: boolean; // indicator, might come from parent <TableHead>, don't use this prop outside (!)
_onResize?(width: number): void; // <Table> resize callbalck, don't use this prop outside (!)
}
export class TableCell extends React.Component<TableCellProps> {
@ -65,19 +68,23 @@ export class TableCell extends React.Component<TableCellProps> {
}
render() {
const { className, checkbox, isChecked, 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, ...cellProps } = this.props;
const classNames = cssNames("TableCell", className, {
checkbox,
nowrap: _nowrap,
sorting: this.isSortable,
});
const content = displayBooleans(displayBoolean, title || children);
const cellStyle: React.CSSProperties = size !== undefined ?
{ flexBasis: `${size}px` } :
{};
return (
<div {...cellProps} className={classNames} onClick={this.onClick}>
<div 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>}
</div>
);
}