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:
parent
62c3501011
commit
e7f37b359e
@ -30,9 +30,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.TableCell {
|
.TableCell {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
&.menu {
|
&.menu {
|
||||||
@include table-cell-action;
|
@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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,7 @@ export interface ItemListLayoutProps<T extends ItemObject = ItemObject> {
|
|||||||
preloadStores?: boolean;
|
preloadStores?: boolean;
|
||||||
isClusterScoped?: boolean;
|
isClusterScoped?: boolean;
|
||||||
hideFilters?: boolean;
|
hideFilters?: boolean;
|
||||||
|
resizable?: boolean;
|
||||||
searchFilters?: SearchFilter<T>[];
|
searchFilters?: SearchFilter<T>[];
|
||||||
/** @deprecated */
|
/** @deprecated */
|
||||||
filterItems?: ItemsFilter<T>[];
|
filterItems?: ItemsFilter<T>[];
|
||||||
@ -97,6 +98,7 @@ const defaultProps: Partial<ItemListLayoutProps> = {
|
|||||||
@observer
|
@observer
|
||||||
export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
||||||
static defaultProps = defaultProps as object;
|
static defaultProps = defaultProps as object;
|
||||||
|
private cellSizes: Array<number>;
|
||||||
|
|
||||||
private storage = createStorage("item_list_layout", {
|
private storage = createStorage("item_list_layout", {
|
||||||
showFilters: false, // setup defaults
|
showFilters: false, // setup defaults
|
||||||
@ -110,6 +112,11 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
this.storage.merge({ showFilters });
|
this.storage.merge({ showFilters });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(props: ItemListLayoutProps) {
|
||||||
|
super(props);
|
||||||
|
this.cellSizes = new Array<number>(props.renderTableHeader.length);
|
||||||
|
}
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const { isClusterScoped, isConfigurable, tableId, preloadStores } = this.props;
|
const { isClusterScoped, isConfigurable, tableId, preloadStores } = this.props;
|
||||||
|
|
||||||
@ -212,7 +219,7 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
getRow(uid: string) {
|
getRow(uid: string) {
|
||||||
const {
|
const {
|
||||||
isSelectable, renderTableHeader, renderTableContents, renderItemMenu,
|
isSelectable, renderTableHeader, renderTableContents, renderItemMenu,
|
||||||
store, hasDetailsView, onDetails,
|
store, hasDetailsView, onDetails, resizable,
|
||||||
copyClassNameFromHeadCells, customizeTableRowProps, detailsItem,
|
copyClassNameFromHeadCells, customizeTableRowProps, detailsItem,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { isSelected } = store;
|
const { isSelected } = store;
|
||||||
@ -242,13 +249,18 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
renderTableContents(item).map((content, index) => {
|
renderTableContents(item).map((content, index) => {
|
||||||
const cellProps: TableCellProps = isReactNode(content) ? { children: content } : content;
|
const cellProps: TableCellProps = isReactNode(content) ? { children: content } : content;
|
||||||
const headCell = renderTableHeader?.[index];
|
const headCell = renderTableHeader?.[index];
|
||||||
|
const cellSize = this.cellSizes[index];
|
||||||
|
|
||||||
if (copyClassNameFromHeadCells && headCell) {
|
if (copyClassNameFromHeadCells && headCell) {
|
||||||
cellProps.className = cssNames(cellProps.className, headCell.className);
|
cellProps.className = cssNames(cellProps.className, headCell.className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cellSize !== undefined) {
|
||||||
|
cellProps.size = cellSize;
|
||||||
|
}
|
||||||
|
|
||||||
if (!headCell || !this.isHiddenColumn(headCell)) {
|
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() {
|
renderTableHeader() {
|
||||||
const { customizeTableRowProps, renderTableHeader, isSelectable, isConfigurable, store } = this.props;
|
const { customizeTableRowProps, renderTableHeader, isSelectable, isConfigurable, store, resizable } = this.props;
|
||||||
|
|
||||||
if (!renderTableHeader) {
|
if (!renderTableHeader) {
|
||||||
return;
|
return;
|
||||||
@ -399,8 +411,17 @@ export class ItemListLayout extends React.Component<ItemListLayoutProps> {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{renderTableHeader.map((cellProps, index) => {
|
{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)) {
|
if (!this.isHiddenColumn(cellProps)) {
|
||||||
return <TableCell key={cellProps.id ?? index} {...cellProps} />;
|
return <TableCell resizable key={cellProps.id ?? index} {..._cellProps} />;
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
<TableCell className="menu">
|
<TableCell className="menu">
|
||||||
|
|||||||
@ -12,6 +12,8 @@ export interface TableCellProps extends React.DOMAttributes<HTMLDivElement> {
|
|||||||
id?: string; // used for configuration visibility of columns
|
id?: string; // used for configuration visibility of columns
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: ReactNode;
|
title?: ReactNode;
|
||||||
|
resizable?: boolean; // allow resizing
|
||||||
|
size?: number; // set horizontal size
|
||||||
checkbox?: boolean; // render cell with a checkbox
|
checkbox?: boolean; // render cell with a checkbox
|
||||||
isChecked?: boolean; // mark checkbox as checked or not
|
isChecked?: boolean; // mark checkbox as checked or not
|
||||||
renderBoolean?: boolean; // show "true" or "false" for all of the children elements are "typeof boolean"
|
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 (!)
|
_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 (!)
|
_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 (!)
|
_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> {
|
export class TableCell extends React.Component<TableCellProps> {
|
||||||
@ -65,19 +68,23 @@ export class TableCell extends React.Component<TableCellProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
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, {
|
const classNames = cssNames("TableCell", className, {
|
||||||
checkbox,
|
checkbox,
|
||||||
nowrap: _nowrap,
|
nowrap: _nowrap,
|
||||||
sorting: this.isSortable,
|
sorting: this.isSortable,
|
||||||
});
|
});
|
||||||
const content = displayBooleans(displayBoolean, title || children);
|
const content = displayBooleans(displayBoolean, title || children);
|
||||||
|
const cellStyle: React.CSSProperties = size !== undefined ?
|
||||||
|
{ flexBasis: `${size}px` } :
|
||||||
|
{};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...cellProps} className={classNames} onClick={this.onClick}>
|
<div style={cellStyle} {...cellProps} className={classNames} onClick={this.onClick}>
|
||||||
{this.renderCheckbox()}
|
{this.renderCheckbox()}
|
||||||
{_nowrap ? <div className="content">{content}</div> : content}
|
{_nowrap ? <div className="content">{content}</div> : content}
|
||||||
{this.renderSortIcon()}
|
{this.renderSortIcon()}
|
||||||
|
{resizable && <span className="resize-anchor"></span>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user