From bb16ec23844c84b5579361cae043186b750a8320 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Tue, 17 Dec 2019 14:56:59 +0100 Subject: [PATCH 1/3] feat(AnalyticalTable): Update to react-table rc.10 Support Multi Selection of rows BREAKING CHANGE: replaced prop `selectedRowKey` with `selectedRowIds` (Object of rowIds) BREAKING CHANGE: Update to react-table `7.0.0-rc.10` --- packages/main/package.json | 2 +- .../AnalyticalTable/AnayticalTable.jss.ts | 44 ++++---- .../AnalyticalTable.test.tsx.snap | 100 +++++++++--------- .../defaults/Column/Expandable.tsx | 16 +-- .../AnalyticalTable/demo/demo.stories.tsx | 6 +- .../AnalyticalTable/hooks/useCellStyling.ts | 48 --------- .../AnalyticalTable/hooks/useRowSelection.ts | 40 ------- .../hooks/useTableCellStyling.ts | 10 +- .../hooks/useTableHeaderGroupStyling.ts | 4 +- .../hooks/useTableHeaderStyling.ts | 9 +- .../hooks/useTableRowStyling.ts | 91 ++++++---------- .../AnalyticalTable/hooks/useTableStyling.ts | 3 +- .../hooks/useToggleRowExpand.ts | 4 +- .../components/AnalyticalTable/hooks/utils.ts | 14 --- .../src/components/AnalyticalTable/index.tsx | 27 +++-- .../tableReducer/stateReducer.ts | 2 + .../virtualization/VirtualTableBody.tsx | 19 +++- .../virtualization/VirtualTableRow.tsx | 9 +- yarn.lock | 8 +- 19 files changed, 180 insertions(+), 276 deletions(-) delete mode 100644 packages/main/src/components/AnalyticalTable/hooks/useCellStyling.ts delete mode 100644 packages/main/src/components/AnalyticalTable/hooks/useRowSelection.ts delete mode 100644 packages/main/src/components/AnalyticalTable/hooks/utils.ts diff --git a/packages/main/package.json b/packages/main/package.json index 44c09c47651..c3ff95a6095 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -29,7 +29,7 @@ "lodash.debounce": "^4.0.8", "react-content-loader": "^4.3.2", "react-jss": "10.0.0", - "react-table": "7.0.0-rc.5", + "react-table": "7.0.0-rc.10", "react-toastify": "^5.4.1", "react-window": "^1.8.5" }, diff --git a/packages/main/src/components/AnalyticalTable/AnayticalTable.jss.ts b/packages/main/src/components/AnalyticalTable/AnayticalTable.jss.ts index 8261a9fa12c..4d5e335c9d1 100644 --- a/packages/main/src/components/AnalyticalTable/AnayticalTable.jss.ts +++ b/packages/main/src/components/AnalyticalTable/AnayticalTable.jss.ts @@ -38,31 +38,23 @@ const styles = ({ parameters }: JSSTheme) => ({ position: 'relative', zIndex: 0, overflowX: 'auto', + backgroundColor: parameters.sapUiListBackground + }, + tr: { + zIndex: 0, backgroundColor: parameters.sapUiListBackground, - '&$selectable $tr:hover': { - backgroundColor: parameters.sapUiListHoverBackground - }, - '& $selectedRow': { + color: parameters.sapUiListTextColor, + '&[data-is-selected]': { backgroundColor: parameters.sapUiListSelectionBackgroundColor }, - '& $selectedRow:hover': { + '&[data-is-selected]:hover': { backgroundColor: `${parameters.sapUiListSelectionHoverBackground} !important` - }, - '&$selectable $tr:active:not($selectedRow):not($tableGroupHeader)': { - backgroundColor: parameters.sapUiListActiveBackground, - color: parameters.sapUiListActiveTextColor - }, - '&$selectable $tr:active:not($selectedRow):not($tableGroupHeader) $tableCell': { - borderRight: `1px solid ${parameters.sapUiListActiveBackground}` } }, - tr: { - zIndex: 0, - backgroundColor: parameters.sapUiListBackground, - color: parameters.sapUiListTextColor - }, alternateRowColor: { - backgroundColor: parameters.sapUiListHeaderBackground + '& $tr:nth-child(even)': { + backgroundColor: parameters.sapUiListHeaderBackground + } }, tableGroupHeader: { '&$tr': { @@ -74,8 +66,20 @@ const styles = ({ parameters }: JSSTheme) => ({ } } }, - selectable: {}, - selectedRow: {}, + selectable: { + '& $tr:hover': { + backgroundColor: parameters.sapUiListHoverBackground, + cursor: 'pointer' + }, + '& $tr:active:not([data-is-selected]):not($tableGroupHeader)': { + backgroundColor: parameters.sapUiListActiveBackground, + '& $tableCell': { + borderRight: `1px solid ${parameters.sapUiListActiveBackground}`, + color: `${parameters.sapUiListActiveTextColor}`, + '--sapUiBaseText': parameters.sapUiListActiveTextColor + } + } + }, tableCell: { height: '2.75rem', fontFamily: parameters.sapUiFontFamily, diff --git a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap index 5170eca8ade..54084e70b77 100644 --- a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap +++ b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap @@ -299,7 +299,7 @@ exports[`AnalyticalTable Alternate Row Color 1`] = ` style="position: relative; height: 220px; width: 600px; overflow: auto; will-change: transform; direction: ltr;" >
{ const getPadding = (level) => { switch (level) { - case 1: + case 0: return 0; - case 2: + case 1: return isCompact ? '1.5rem' : '1rem'; - case 3: + case 2: return isCompact ? '2.25rem' : '1.5rem'; - case 4: + case 3: return isCompact ? '2.75rem' : '2rem'; default: - return `${(isCompact ? 2.75 : 2) + (level - 4) * 0.5}rem`; + return `${(isCompact ? 2.75 : 2) + (level - 3) * 0.5}rem`; } }; - let paddingLeft = null; + let paddingLeft = undefined; if (row.canExpand) { - paddingLeft = columnIndex === 0 ? getPadding(row.path.length) : 0; + paddingLeft = columnIndex === 0 ? getPadding(row.depth) : 0; } else { - paddingLeft = columnIndex === 0 ? `calc(${getPadding(row.path.length)} + 2rem)` : 0; + paddingLeft = columnIndex === 0 ? `calc(${getPadding(row.depth)} + 2rem)` : 0; } const style: CSSProperties = { paddingLeft diff --git a/packages/main/src/components/AnalyticalTable/demo/demo.stories.tsx b/packages/main/src/components/AnalyticalTable/demo/demo.stories.tsx index f6721ae0b45..bd9d7e67454 100644 --- a/packages/main/src/components/AnalyticalTable/demo/demo.stories.tsx +++ b/packages/main/src/components/AnalyticalTable/demo/demo.stories.tsx @@ -1,5 +1,5 @@ import { action } from '@storybook/addon-actions'; -import { array, boolean, number, text } from '@storybook/addon-knobs'; +import { array, boolean, number, text, object } from '@storybook/addon-knobs'; import { AnalyticalTable } from '@ui5/webcomponents-react/lib/AnalyticalTable'; import { Button } from '@ui5/webcomponents-react/lib/Button'; import { TextAlign } from '@ui5/webcomponents-react/lib/TextAlign'; @@ -78,7 +78,7 @@ export const defaultTable = () => { onRowExpandChange={action('onRowExpandChange')} groupBy={array('groupBy', [])} rowHeight={number('rowHeight', 60)} - selectedRowKey={text('selectedRowKey', `row_5`)} + selectedRowIds={object('selectedRowIds', { 3: true })} onColumnsReordered={action('onColumnsReordered')} />
@@ -106,7 +106,7 @@ export const treeTable = () => { onSort={action('onSort')} onRowExpandChange={action('onRowExpandChange')} subRowsKey={text('subRowsKey', 'subRows')} - selectedRowKey={text('selectedRowKey', `row_5`)} + selectedRowIds={object('selectedRowIds', { 3: true })} isTreeTable={boolean('isTreeTable', true)} /> ); diff --git a/packages/main/src/components/AnalyticalTable/hooks/useCellStyling.ts b/packages/main/src/components/AnalyticalTable/hooks/useCellStyling.ts deleted file mode 100644 index 0260fb830ab..00000000000 --- a/packages/main/src/components/AnalyticalTable/hooks/useCellStyling.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { TextAlign } from '@ui5/webcomponents-react/lib/TextAlign'; -import { VerticalAlign } from '@ui5/webcomponents-react/lib/VerticalAlign'; -import { CSSProperties } from 'react'; - -export const useCellStyling = ({ rowHeight }, classes) => ({ column }) => { - const style: CSSProperties = {}; - - if (rowHeight) { - style.height = `${rowHeight}px`; - } - switch (column.hAlign) { - case TextAlign.Begin: - style.textAlign = 'start'; - break; - case TextAlign.Center: - style.textAlign = 'center'; - break; - case TextAlign.End: - style.textAlign = 'end'; - break; - case TextAlign.Left: - style.textAlign = 'left'; - break; - case TextAlign.Right: - style.textAlign = 'right'; - break; - } - switch (column.vAlign) { - case VerticalAlign.Bottom: - style.verticalAlign = 'bottom'; - break; - case VerticalAlign.Middle: - style.verticalAlign = 'middle'; - break; - case VerticalAlign.Top: - style.verticalAlign = 'top'; - break; - } - - let className = classes.tableCell; - if (column.className) { - className += ` ${column.className}`; - } - return { - className, - style - }; -}; diff --git a/packages/main/src/components/AnalyticalTable/hooks/useRowSelection.ts b/packages/main/src/components/AnalyticalTable/hooks/useRowSelection.ts deleted file mode 100644 index 004f118ef0e..00000000000 --- a/packages/main/src/components/AnalyticalTable/hooks/useRowSelection.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Event } from '@ui5/webcomponents-react-base/lib/Event'; -import { useCallback, useRef, useState } from 'react'; - -const comparePaths = (path1, path2) => { - return path1.length === path2.length && path1.every((item, i) => item === path2[i]); -}; - -export const useRowSelection = (onRowSelected, selectedRowKeyProp) => { - const [selectedRowPath, setSelectedRowPath] = useState([]); - const prevSelectedRowKeyProp = useRef(selectedRowKeyProp); - const onRowClicked = useCallback( - (row) => (e) => { - if (row.isAggregated) return; - const newKey = row.path; - const pathsEqual = comparePaths(row.path, selectedRowPath); - - let newSelectedRow; - - let selectedIndexProp = null; - if (typeof selectedRowKeyProp === 'string') { - const [_, ...path] = selectedRowKeyProp.split('_'); - selectedIndexProp = path; - } - - if (prevSelectedRowKeyProp.current !== selectedRowKeyProp && comparePaths(selectedIndexProp, newKey)) { - newSelectedRow = []; - prevSelectedRowKeyProp.current = selectedRowKeyProp; - } else { - newSelectedRow = pathsEqual ? [] : newKey; - } - - setSelectedRowPath(newSelectedRow); - if (typeof onRowSelected === 'function') { - onRowSelected(Event.of(null, e, { row, isSelected: newSelectedRow.length > 0 })); - } - }, - [selectedRowPath, setSelectedRowPath, selectedRowKeyProp, prevSelectedRowKeyProp.current] - ); - return [selectedRowPath, onRowClicked]; -}; diff --git a/packages/main/src/components/AnalyticalTable/hooks/useTableCellStyling.ts b/packages/main/src/components/AnalyticalTable/hooks/useTableCellStyling.ts index 047761254a7..3378a46bbfd 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useTableCellStyling.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useTableCellStyling.ts @@ -5,12 +5,13 @@ import { PluginHook } from 'react-table'; export const useTableCellStyling = (classes, rowHeight) => { const hook: PluginHook<{}> = (instance) => { - instance.getCellProps.push(({ column }) => { + instance.getCellProps.push((cellProps, instance, { column }) => { const style: CSSProperties = {}; if (rowHeight) { style.height = `${rowHeight}px`; } + switch (column.hAlign) { case TextAlign.Begin: style.textAlign = 'start'; @@ -44,9 +45,14 @@ export const useTableCellStyling = (classes, rowHeight) => { if (column.className) { className += ` ${column.className}`; } + return { + ...cellProps, className, - style + style: { + ...cellProps.style, + style + } }; }); }; diff --git a/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderGroupStyling.ts b/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderGroupStyling.ts index 7916c4069f0..6632245fcd3 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderGroupStyling.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderGroupStyling.ts @@ -1,10 +1,10 @@ import { PluginHook } from 'react-table'; -import { makeTemplateColumns } from './utils'; export const useTableHeaderGroupStyling = (classes) => { const hook: PluginHook<{}> = (instance) => { - instance.getHeaderGroupProps.push(() => { + instance.getHeaderGroupProps.push((headerGroupProps) => { return { + ...headerGroupProps, className: classes.tableHeaderRow }; }); diff --git a/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderStyling.ts b/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderStyling.ts index ed3620f20c1..ffada872ca8 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderStyling.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useTableHeaderStyling.ts @@ -2,10 +2,15 @@ import { PluginHook } from 'react-table'; export const useTableHeaderStyling = (classes) => { const hook: PluginHook<{}> = (instance) => { - instance.getHeaderProps.push((column) => { + instance.getHeaderProps.push((columnProps, instance, column) => { return { + ...columnProps, className: classes.th, - column + column, + style: { + ...columnProps.style, + position: 'absolute' // TODO should be removed at some point in time + } }; }); return instance; diff --git a/packages/main/src/components/AnalyticalTable/hooks/useTableRowStyling.ts b/packages/main/src/components/AnalyticalTable/hooks/useTableRowStyling.ts index a979e5adf25..6c73c97c35c 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useTableRowStyling.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useTableRowStyling.ts @@ -1,74 +1,45 @@ -import { useEffect, useMemo, useRef } from 'react'; -import { PluginHook } from 'react-table'; +import { Event } from '@ui5/webcomponents-react-base/lib/Event'; -export const useTableRowStyling = ( - classes, - selectable, - selectedRow, - selectedRowKey, - onRowClicked, - alternateRowColor -) => { - const prevSelectedRow = useRef(null); - const prevSelectedRowKey = useRef(null); - - const applySelectedRow = useMemo(() => { - if (selectedRowKey !== prevSelectedRowKey.current) { - return false; - } - if (selectedRow !== prevSelectedRow.current) { - return true; - } - return false; - }, [selectedRow, selectedRowKey]); - - useEffect(() => { - prevSelectedRow.current = selectedRow; - }, [selectedRow]); - - useEffect(() => { - prevSelectedRowKey.current = selectedRowKey; - }, [selectedRowKey]); - - const hook: PluginHook<{}> = (instance) => { - instance.getRowProps.push((row) => { - const rowKey = row.path.reduce((acc, val) => `${acc}_${val}`, 'row'); - let selected = false; - - if (!row.isAggregated && selectable) { - if (applySelectedRow) { - if (selectedRow.length && selectedRow.length > 0) { - selected = row.path.length === selectedRow.length && row.path.every((item, i) => item === selectedRow[i]); - } - } else if (selectedRowKey && rowKey === selectedRowKey) { - selected = true; - } - } +const ROW_SELECTION_ATTRIBUTE = 'data-is-selected'; +export const useTableRowStyling = (classes, selectable, onRowSelected) => { + const hook = (instance) => { + instance.getRowProps.push((passedRowProps, instance, row) => { let className = classes.tr; - if (row.isAggregated) { + if (row.isGrouped) { className += ` ${classes.tableGroupHeader}`; } - if (selected) { - className += ` ${classes.selectedRow}`; - } - if (alternateRowColor) { - if (row.index % 2 === 1) { - className += ` ${classes.alternateRowColor}`; - } - } + const rowProps: any = { + ...passedRowProps, + className, + role: 'row' + }; if (selectable) { - return { - className, - onClick: onRowClicked(row) + rowProps.onClick = (e) => { + if (row.isGrouped) { + return; + } + + row.toggleRowSelected(); + if (typeof onRowSelected === 'function') { + onRowSelected(Event.of(null, e, { row, isSelected: !row.isSelected })); + } + const clickedRow = e.currentTarget as HTMLDivElement; + if (clickedRow.hasAttribute(ROW_SELECTION_ATTRIBUTE)) { + clickedRow.removeAttribute(ROW_SELECTION_ATTRIBUTE); + } else { + clickedRow.setAttribute(ROW_SELECTION_ATTRIBUTE, ''); + } }; + if (row.isSelected) { + rowProps['data-is-selected'] = ''; + } } - return { - className - }; + return rowProps; }); + return instance; }; diff --git a/packages/main/src/components/AnalyticalTable/hooks/useTableStyling.ts b/packages/main/src/components/AnalyticalTable/hooks/useTableStyling.ts index a1fe3ab94e8..c32572ad2b6 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useTableStyling.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useTableStyling.ts @@ -2,8 +2,9 @@ import { PluginHook } from 'react-table'; export const useTableStyling = (classes) => { const hook: PluginHook<{}> = (tableHooks) => { - tableHooks.getTableProps.push(() => { + tableHooks.getTableProps.push((tableProps) => { return { + ...tableProps, className: classes.table }; }); diff --git a/packages/main/src/components/AnalyticalTable/hooks/useToggleRowExpand.ts b/packages/main/src/components/AnalyticalTable/hooks/useToggleRowExpand.ts index e57de276ddc..f9f8264154d 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useToggleRowExpand.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useToggleRowExpand.ts @@ -3,9 +3,9 @@ import { PluginHook } from 'react-table'; export const useToggleRowExpand = (onRowExpandChange, isTreeTable) => { const hook: PluginHook = (instance) => { - // @ts-ignore - instance.getExpandedToggleProps.push((row) => { + instance.getExpandedToggleProps.push((rowProps, instance, row) => { return { + ...rowProps, onClick: (e) => { e.stopPropagation(); e.persist(); diff --git a/packages/main/src/components/AnalyticalTable/hooks/utils.ts b/packages/main/src/components/AnalyticalTable/hooks/utils.ts deleted file mode 100644 index ca9eaa44075..00000000000 --- a/packages/main/src/components/AnalyticalTable/hooks/utils.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const makeTemplateColumns = (columns) => { - return columns - .map((column) => { - let columnWidth = column.width; - if (typeof columnWidth === 'number') { - columnWidth = `${columnWidth}px`; - } - if (!columnWidth) { - columnWidth = '1fr'; - } - return `minmax(${column.minWidth}px, ${columnWidth})`; - }) - .join(' '); -}; diff --git a/packages/main/src/components/AnalyticalTable/index.tsx b/packages/main/src/components/AnalyticalTable/index.tsx index 706a4d8c28e..41ba8f8e846 100644 --- a/packages/main/src/components/AnalyticalTable/index.tsx +++ b/packages/main/src/components/AnalyticalTable/index.tsx @@ -20,6 +20,7 @@ import React, { } from 'react'; import { createUseStyles, useTheme } from 'react-jss'; import { + Column, PluginHook, useAbsoluteLayout, useColumnOrder, @@ -27,9 +28,9 @@ import { useFilters, useGroupBy, useResizeColumns, + useRowSelect, useSortBy, - useTable, - Column + useTable } from 'react-table'; import { CommonProps } from '../../interfaces/CommonProps'; import { JSSTheme } from '../../interfaces/JSSTheme'; @@ -40,7 +41,6 @@ import { DefaultLoadingComponent } from './defaults/LoadingComponent'; import { TablePlaceholder } from './defaults/LoadingComponent/TablePlaceholder'; import { DefaultNoDataComponent } from './defaults/NoDataComponent'; import { useDragAndDrop } from './hooks/useDragAndDrop'; -import { useRowSelection } from './hooks/useRowSelection'; import { useTableCellStyling } from './hooks/useTableCellStyling'; import { useTableHeaderGroupStyling } from './hooks/useTableHeaderGroupStyling'; import { useTableHeaderStyling } from './hooks/useTableHeaderStyling'; @@ -114,7 +114,7 @@ export interface TableProps extends CommonProps { reactTableOptions?: object; tableHooks?: Array>; subRowsKey?: string; - selectedRowKey?: string; + selectedRowIds?: { [key: string]: boolean }; isTreeTable?: boolean; overscanCount?: number; @@ -147,7 +147,7 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< subRowsKey, onGroup, rowHeight, - selectedRowKey, + selectedRowIds, LoadingComponent, onRowExpandChange, noDataText, @@ -161,7 +161,6 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< const theme = useTheme() as JSSTheme; const classes = useStyles({ rowHeight: props.rowHeight }); - const [selectedRowPath, onRowClicked] = useRowSelection(onRowSelected, selectedRowKey); const [analyticalTableRef, reactWindowRef] = useTableScrollHandles(ref); const tableRef: RefObject = useRef(); @@ -187,7 +186,8 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< state: tableState, setColumnOrder, dispatch, - totalColumnsWidth + totalColumnsWidth, + selectedFlatRows } = useTable( { columns, @@ -197,17 +197,18 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< stateReducer, ...reactTableOptions }, + useAbsoluteLayout, useFilters, useGroupBy, useColumnOrder, useSortBy, useExpanded, - useAbsoluteLayout, + useRowSelect, useResizeColumns, useTableStyling(classes), useTableHeaderGroupStyling(classes), useTableHeaderStyling(classes), - useTableRowStyling(classes, selectable, selectedRowPath, selectedRowKey, onRowClicked, alternateRowColor), + useTableRowStyling(classes, selectable, onRowSelected), useTableCellStyling(classes, rowHeight), useToggleRowExpand(onRowExpandChange, isTreeTable), ...tableHooks @@ -236,6 +237,10 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< dispatch({ type: 'SET_GROUP_BY', payload: groupBy }); }, [groupBy, dispatch]); + useEffect(() => { + dispatch({ type: 'SET_SELECTED_ROWS', selectedIds: selectedRowIds }); + }, [selectedRowIds, dispatch]); + const tableContainerClasses = StyleClassHelper.of(classes.tableContainer); if (theme.contentDensity === ContentDensity.Compact) { @@ -349,8 +354,6 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< rows={rows} minRows={minRows} columns={columns} - selectedRow={selectedRowKey} - selectedRowPath={selectedRowPath} selectable={selectable} reactWindowRef={reactWindowRef} isTreeTable={isTreeTable} @@ -360,6 +363,7 @@ const AnalyticalTable: FC = forwardRef((props: TableProps, ref: Ref< alternateRowColor={alternateRowColor} overscanCount={overscanCount} totalColumnsWidth={totalColumnsWidth} + selectedFlatRows={selectedFlatRows} /> )}
@@ -389,6 +393,7 @@ AnalyticalTable.defaultProps = { tableHooks: [], visibleRows: 15, subRowsKey: 'subRows', + selectedRowIds: {}, onGroup: () => {}, onRowExpandChange: () => {}, onColumnsReordered: () => {}, diff --git a/packages/main/src/components/AnalyticalTable/tableReducer/stateReducer.ts b/packages/main/src/components/AnalyticalTable/tableReducer/stateReducer.ts index 35f0bf1109e..2b99cd2b2e5 100644 --- a/packages/main/src/components/AnalyticalTable/tableReducer/stateReducer.ts +++ b/packages/main/src/components/AnalyticalTable/tableReducer/stateReducer.ts @@ -3,6 +3,8 @@ export const stateReducer = (newState, action, prevState) => { switch (action.type) { case 'SET_GROUP_BY': return { ...prevState, groupBy: payload }; + case 'SET_SELECTED_ROWS': + return { ...prevState, selectedRowIds: action.selectedIds }; default: return newState; } diff --git a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx index 353e4e479dd..b4a75d97d8e 100644 --- a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx +++ b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableBody.tsx @@ -11,8 +11,6 @@ export const VirtualTableBody = (props) => { rows, minRows, columns, - selectedRow, - selectedRowPath, selectable, reactWindowRef, isTreeTable, @@ -21,7 +19,8 @@ export const VirtualTableBody = (props) => { visibleRows, alternateRowColor, overscanCount, - totalColumnsWidth + totalColumnsWidth, + selectedFlatRows } = props; const innerDivRef = useRef(null); @@ -33,8 +32,18 @@ export const VirtualTableBody = (props) => { if (selectable) { innerDivRef.current.classList.add(classes.selectable); } + if (alternateRowColor) { + innerDivRef.current.classList.add(classes.alternateRowColor); + } } - }, [innerDivRef.current, selectable, classes.tbody, classes.selectable]); + }, [ + innerDivRef.current, + selectable, + classes.tbody, + classes.selectable, + alternateRowColor, + classes.alternateRowColor + ]); const itemCount = Math.max(minRows, rows.length); const overscan = overscanCount ? overscanCount : Math.floor(visibleRows / 2); @@ -48,7 +57,7 @@ export const VirtualTableBody = (props) => { columns } }; - }, [rows, prepareRow, isTreeTable, classes, columns, alternateRowColor, selectedRow, selectedRowPath]); + }, [rows, prepareRow, isTreeTable, classes, columns, selectedFlatRows]); const getItemKey = useCallback( (index, data) => { diff --git a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx index ded94b3f591..4bd8d97a01c 100644 --- a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx +++ b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx @@ -21,16 +21,19 @@ export const VirtualTableRow = (props) => { } return ( -
+
{row.cells.map((cell, i) => { + if (index <= 3) { + console.log(cell); + } let contentToRender = 'Cell'; if (isTreeTable) { contentToRender = 'Expandable'; } else if (cell.isGrouped) { contentToRender = 'Grouped'; - } else if (cell.isAggregated) { + } else if (row.isGrouped) { contentToRender = 'Aggregated'; - } else if (cell.isRepeatedValue) { + } else if (cell.isRepeatedValue || cell.column.isGrouped) { contentToRender = 'RepeatedValue'; } return
{cell.render(contentToRender)}
; diff --git a/yarn.lock b/yarn.lock index 63ea17ea17d..aa77354a728 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14536,10 +14536,10 @@ react-syntax-highlighter@^8.0.1: prismjs "^1.8.4" refractor "^2.4.1" -react-table@7.0.0-rc.5: - version "7.0.0-rc.5" - resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-rc.5.tgz#6d0caf6b6003c19c3e36dfd7c926f5b40dee0c30" - integrity sha512-hMrnKMvKOfqbHv3WUxmActkTj06Y8r3v/HIZ2H6CRqhgjGV3gtONn2N1w9lLCY7NE3x7BtD+YhtmacYhWkGtJA== +react-table@7.0.0-rc.10: + version "7.0.0-rc.10" + resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.0.0-rc.10.tgz#b7469752f5cd6a44f4eb7309645a7fc4a42f3808" + integrity sha512-9EekDruo8+yvkfN3idyBIXRLeLMW9E/HlEu41LItNRufGF0g6r1Kn7/3HKSMOBxUP0DeAGDyD82KHHCU+g2Feg== react-test-renderer@^16.0.0-0: version "16.8.6" From aa55ab04d797c41078002d76e629df0e2dc4aad6 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Tue, 17 Dec 2019 15:03:27 +0100 Subject: [PATCH 2/3] WIP: Add additional test --- .../AnalyticalTable/AnalyticalTable.test.tsx | 9 + .../AnalyticalTable.test.tsx.snap | 306 ++++++++++++++++++ .../defaults/Column/Aggregated.tsx | 3 + .../AnalyticalTable/defaults/Column/index.tsx | 3 +- 4 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 packages/main/src/components/AnalyticalTable/defaults/Column/Aggregated.tsx diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx index 661f13522f7..3e543972e3e 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.test.tsx @@ -250,4 +250,13 @@ describe('AnalyticalTable', () => { expect(wrapper.render()).toMatchSnapshot(); }); + + test('render without data', () => { + const data = []; + const wrapper = mountThemedComponent( + + ); + + expect(wrapper.render()).toMatchSnapshot(); + }); }); diff --git a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap index 54084e70b77..2d0c1949177 100644 --- a/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap +++ b/packages/main/src/components/AnalyticalTable/__snapshots__/AnalyticalTable.test.tsx.snap @@ -2533,6 +2533,312 @@ exports[`AnalyticalTable custom row height 1`] = `
`; +exports[`AnalyticalTable render without data 1`] = ` +
+
+ + Table Title + +
+
+
+
+
+
+
+ + Name + +
+
+
+ + + + Sort Ascending + + + Sort Descending + + + +
+
+
+
+
+ + Age + +
+
+
+ + + + Sort Ascending + + + Sort Descending + + + +
+
+
+
+
+ + Friend Name + +
+
+
+ + + + Sort Ascending + + + Sort Descending + + + +
+
+
+
+
+ + + Friend Age + + +
+
+
+ + + + Sort Ascending + + + Sort Descending + + + +
+
+
+
+ No Data +
+
+
+
+`; + exports[`AnalyticalTable test Asc desc 1`] = `
= () => null; diff --git a/packages/main/src/components/AnalyticalTable/defaults/Column/index.tsx b/packages/main/src/components/AnalyticalTable/defaults/Column/index.tsx index 4cbc1160fe7..093716844d1 100644 --- a/packages/main/src/components/AnalyticalTable/defaults/Column/index.tsx +++ b/packages/main/src/components/AnalyticalTable/defaults/Column/index.tsx @@ -1,5 +1,6 @@ import { VerticalAlign } from '@ui5/webcomponents-react/lib/VerticalAlign'; import { DefaultFilterComponent } from '../FilterComponent'; +import { Aggregated } from './Aggregated'; import { Cell } from './Cell'; import { Expandable } from './Expandable'; import { Grouped } from './Grouped'; @@ -16,7 +17,7 @@ export const DefaultColumn = { canResize: true, minWidth: DEFAULT_COLUMN_WIDTH, vAlign: VerticalAlign.Middle, - Aggregated: () => null, + Aggregated: Aggregated, defaultFilter: defaultFilterMethod, Grouped: Grouped, Cell: Cell, From e30a36b854ddc90486393cdd60de601945c5e67d Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Tue, 17 Dec 2019 19:42:17 +0100 Subject: [PATCH 3/3] WIP: PR Comments --- .../AnalyticalTable/virtualization/VirtualTableRow.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx index 4bd8d97a01c..5f7e42a6d7f 100644 --- a/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx +++ b/packages/main/src/components/AnalyticalTable/virtualization/VirtualTableRow.tsx @@ -22,10 +22,7 @@ export const VirtualTableRow = (props) => { return (
- {row.cells.map((cell, i) => { - if (index <= 3) { - console.log(cell); - } + {row.cells.map((cell) => { let contentToRender = 'Cell'; if (isTreeTable) { contentToRender = 'Expandable';