From e7f37b359ea99cba2ce01c913e2508c182a730b4 Mon Sep 17 00:00:00 2001 From: Alex Culliere Date: Fri, 12 Feb 2021 15:21:53 +0200 Subject: [PATCH] Setup resize functionality for table cells Signed-off-by: Alex Culliere --- .../item-object-list/item-list-layout.scss | 12 ++++++++ .../item-object-list/item-list-layout.tsx | 29 ++++++++++++++++--- src/renderer/components/table/table-cell.tsx | 11 +++++-- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/renderer/components/item-object-list/item-list-layout.scss b/src/renderer/components/item-object-list/item-list-layout.scss index 0008ffd527..026791ebb1 100644 --- a/src/renderer/components/item-object-list/item-list-layout.scss +++ b/src/renderer/components/item-object-list/item-list-layout.scss @@ -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; + } } } 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 ab352361fe..667e7e2524 100644 --- a/src/renderer/components/item-object-list/item-list-layout.tsx +++ b/src/renderer/components/item-object-list/item-list-layout.tsx @@ -44,6 +44,7 @@ export interface ItemListLayoutProps { preloadStores?: boolean; isClusterScoped?: boolean; hideFilters?: boolean; + resizable?: boolean; searchFilters?: SearchFilter[]; /** @deprecated */ filterItems?: ItemsFilter[]; @@ -97,6 +98,7 @@ const defaultProps: Partial = { @observer export class ItemListLayout extends React.Component { static defaultProps = defaultProps as object; + private cellSizes: Array; private storage = createStorage("item_list_layout", { showFilters: false, // setup defaults @@ -110,6 +112,11 @@ export class ItemListLayout extends React.Component { this.storage.merge({ showFilters }); } + constructor(props: ItemListLayoutProps) { + super(props); + this.cellSizes = new Array(props.renderTableHeader.length); + } + async componentDidMount() { const { isClusterScoped, isConfigurable, tableId, preloadStores } = this.props; @@ -212,7 +219,7 @@ export class ItemListLayout extends React.Component { 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 { 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 ; + return ; } }) } @@ -381,7 +393,7 @@ export class ItemListLayout extends React.Component { } 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 { /> )} {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 ; + return ; } })} diff --git a/src/renderer/components/table/table-cell.tsx b/src/renderer/components/table/table-cell.tsx index 81e2f9f85f..093534cb26 100644 --- a/src/renderer/components/table/table-cell.tsx +++ b/src/renderer/components/table/table-cell.tsx @@ -12,6 +12,8 @@ export interface TableCellProps extends React.DOMAttributes { 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 { _sorting?: Partial; // sorting state, don't use this prop outside (!) _sort?(sortBy: TableSortBy): void; //
sort function, don't use this prop outside (!) _nowrap?: boolean; // indicator, might come from parent , don't use this prop outside (!) + _onResize?(width: number): void; //
resize callbalck, don't use this prop outside (!) } export class TableCell extends React.Component { @@ -65,19 +68,23 @@ export class TableCell extends React.Component { } 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 ( -
+
{this.renderCheckbox()} {_nowrap ?
{content}
: content} {this.renderSortIcon()} + {resizable && }
); }