Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(AnalyticalTable): Fix tree-table selection, add selectionBehavior prop + enum #401

Merged
merged 22 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2ebe214
WIP: fix select in tree table
Lukas742 Apr 2, 2020
661955a
replace noSelectionColumn with selectionBehavior enum
Lukas742 Apr 2, 2020
2793ee0
add selectionBehavior functionality
Lukas742 Apr 2, 2020
adda9f3
change styling
Lukas742 Apr 2, 2020
d1e4596
update snapshots
Lukas742 Apr 2, 2020
96697cb
fix: in some cases instance was not defined in cb
Lukas742 Apr 2, 2020
b7a6eda
use updated instance of Cell
Lukas742 Apr 2, 2020
3799d9a
Merge branch 'master' into fix/analytical-table-tree
Lukas742 Apr 2, 2020
282fb57
selection column adapts its width to contentDensity
Lukas742 Apr 2, 2020
f974aec
Merge branch 'master' into fix/analytical-table-tree
Lukas742 Apr 2, 2020
5dc746f
Update packages/main/src/components/AnalyticalTable/index.tsx
Lukas742 Apr 2, 2020
f0f5793
Update packages/main/src/components/AnalyticalTable/demo/demo.stories…
Lukas742 Apr 2, 2020
44888f4
Update packages/main/src/components/AnalyticalTable/demo/demo.stories…
Lukas742 Apr 2, 2020
476dfc2
update snapshots
Lukas742 Apr 2, 2020
efb031f
updated snapshots (again), requested changes
Lukas742 Apr 2, 2020
f4fee1f
WIP: add hook
Lukas742 Apr 2, 2020
600ae15
add useSingleRowStateSelection hook, remove checkbox css variables to…
Lukas742 Apr 2, 2020
5990e6d
update snapshots
Lukas742 Apr 2, 2020
47789aa
Merge branch 'master' into fix/analytical-table-tree
Lukas742 Apr 2, 2020
d5b498b
Merge remote-tracking branch 'origin/master' into fix/analytical-tabl…
MarcusNotheis Apr 3, 2020
a00433d
Update AnalyticalTable.test.tsx.snap
MarcusNotheis Apr 3, 2020
55db818
Update useRowSelectionColumn.tsx
MarcusNotheis Apr 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/base/src/styling/CssSizeVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export enum CssSizeVariablesNames {
sapWcrAnalyticalTableRowHeight = 'sapWcrAnalyticalTableRowHeight',
sapWcrAnalyticalTableTreePaddingLevel1 = 'sapWcrAnalyticalTableTreePaddingLevel1',
sapWcrAnalyticalTableTreePaddingLevel2 = 'sapWcrAnalyticalTableTreePaddingLevel2',
sapWcrAnalyticalTableTreePaddingLevel3 = 'sapWcrAnalyticalTableTreePaddingLevel3'
sapWcrAnalyticalTableTreePaddingLevel3 = 'sapWcrAnalyticalTableTreePaddingLevel3',
sapWcrAnalyticalTableSelectionColumnWidth = 'sapWcrAnalyticalTableSelectionColumnWidth'
}

export const CssSizeVariables: Record<CssSizeVariablesNames, string> = Object.values(CssSizeVariablesNames).reduce(
Expand Down Expand Up @@ -41,6 +42,7 @@ export const cssVariablesStyles = `
--${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel1}:1.5rem;
--${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel2}:2.25rem;
--${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel3}:2.75rem;
--${CssSizeVariablesNames.sapWcrAnalyticalTableSelectionColumnWidth}:55px;

}

Expand All @@ -61,5 +63,6 @@ export const cssVariablesStyles = `
--${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel1}:1rem;
--${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel2}:1.5rem;
--${CssSizeVariablesNames.sapWcrAnalyticalTableTreePaddingLevel3}:2rem;
--${CssSizeVariablesNames.sapWcrAnalyticalTableSelectionColumnWidth}:40px;
}
`;
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { createPassThroughPropsTest } from '@shared/tests/utils';
import { mount } from 'enzyme';
import { AnalyticalTable } from '@ui5/webcomponents-react/lib/AnalyticalTable';
import { ValueState } from '@ui5/webcomponents-react/lib/ValueState';
import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode';
import { AnalyticalTableScrollMode } from '@ui5/webcomponents-react/lib/AnalyticalTableScrollMode';
import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode';
import { ValueState } from '@ui5/webcomponents-react/lib/ValueState';
import { TableSelectionBehavior } from '@ui5/webcomponents-react/lib/TableSelectionBehavior';
import { mount } from 'enzyme';
import React, { useRef } from 'react';

const columns = [
Expand Down Expand Up @@ -268,7 +269,7 @@ describe('AnalyticalTable', () => {
data={data}
columns={columns}
selectionMode={TableSelectionMode.SINGLE_SELECT}
noSelectionColumn
selectionBehavior={TableSelectionBehavior.ROW_ONLY}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ const styles = {
selectable: {
'& $tr:hover:not($emptyRow)': {
backgroundColor: ThemingParameters.sapList_Hover_Background,
cursor: 'pointer'
'&:not($selectionModeRowSelector)': {
cursor: 'pointer'
}
},
'& $tr:active:not([data-is-selected]):not($tableGroupHeader):not($emptyRow)': {
'& $tr:active:not([data-is-selected]):not($tableGroupHeader):not($emptyRow):not($selectionModeRowSelector)': {
backgroundColor: ThemingParameters.sapList_Active_Background,
'& $tableCell': {
borderRight: `1px solid ${ThemingParameters.sapList_Active_Background}`,
Expand All @@ -79,6 +81,7 @@ const styles = {
}
}
},
selectionModeRowSelector: {},
tableCell: {
height: CssSizeVariables.sapWcrAnalyticalTableRowHeight,
fontFamily: ThemingParameters.sapFontFamily,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export interface ColumnHeaderProps {

const styles = {
header: {
padding: `0 0.5rem`,
height: '100%',
display: 'flex',
justifyContent: 'begin',
Expand Down Expand Up @@ -161,14 +160,18 @@ export const ColumnHeader: FC<ColumnHeaderProps> = (props: ColumnHeaderProps) =>
fontWeight: 'normal',
cursor: 'pointer',
height: '100%',
overflowX: 'hidden'
overflowX: 'hidden',
padding: `0 0.5rem`
};
if (isResizable) {
modifiedStyles.maxWidth = `calc(100% - 16px)`;
}
if (dragOver) {
modifiedStyles.borderLeft = `3px solid ${ThemingParameters.sapSelectedColor}`;
}
if (column.id === '__ui5wcr__internal_highlight_column' || column.id === '__ui5wcr__internal_selection_column') {
modifiedStyles.padding = 0;
}
return modifiedStyles;
}, [isResizable, dragOver]);

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CssSizeVariables } from '@ui5/webcomponents-react-base/lib/CssSizeVariables';
import { Icon } from '@ui5/webcomponents-react/lib/Icon';
import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode';
import { TableSelectionBehavior } from '@ui5/webcomponents-react/lib/TableSelectionBehavior';
import React, { CSSProperties } from 'react';

const tableGroupExpandCollapseIcon = {
Expand Down Expand Up @@ -32,13 +33,15 @@ export const Expandable = (props) => {
row,
column,
columns,
webComponentsReactProperties: { selectionMode, noSelectionColumn }
webComponentsReactProperties: { selectionMode, selectionBehavior }
} = props;

const tableColumns =
selectionMode === TableSelectionMode.NONE || noSelectionColumn
selectionMode === TableSelectionMode.NONE || selectionBehavior === TableSelectionBehavior.ROW_ONLY
? columns
: columns.filter(({ id }) => id !== '__ui5wcr__internal_selection_column' && id !== '__ui5wcr__internal_highlight_column');
: columns.filter(
({ id }) => id !== '__ui5wcr__internal_selection_column' && id !== '__ui5wcr__internal_highlight_column'
);

const columnIndex = tableColumns.findIndex((col) => col.id === column.id);

Expand Down
14 changes: 12 additions & 2 deletions packages/main/src/components/AnalyticalTable/demo/demo.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { AnalyticalTable } from '@ui5/webcomponents-react/lib/AnalyticalTable';
import { Button } from '@ui5/webcomponents-react/lib/Button';
import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode';
import { TextAlign } from '@ui5/webcomponents-react/lib/TextAlign';
import { TableScaleWidthMode } from '@ui5/webcomponents-react/lib/TableScaleWidthMode';
import { TableSelectionBehavior } from '@ui5/webcomponents-react/lib/TableSelectionBehavior';
import { Title } from '@ui5/webcomponents-react/lib/Title';
import React from 'react';
import { TableScaleWidthMode } from '../../../enums/TableScaleWidthMode';
import generateData from './generateData';

const columns = [
Expand Down Expand Up @@ -88,12 +89,16 @@ export const defaultTable = () => {
rowHeight={number('rowHeight', 44)}
selectedRowIds={object('selectedRowIds', { 3: true })}
onColumnsReordered={action('onColumnsReordered')}
noSelectionColumn={boolean('noSelectionColumn', false)}
withRowHighlight={boolean('withRowHighlight', true)}
highlightField={text('highlightField', 'status')}
infiniteScroll={boolean('infiniteScroll', true)}
infiniteScrollThreshold={number('infiniteScrollThreshold', 20)}
onLoadMore={action('onLoadMore')}
selectionBehavior={select<TableSelectionBehavior>(
'selectionBehavior',
TableSelectionBehavior,
TableSelectionBehavior.ROW
)}
/>
</div>
);
Expand Down Expand Up @@ -121,6 +126,11 @@ export const treeTable = () => {
onRowExpandChange={action('onRowExpandChange')}
subRowsKey={text('subRowsKey', 'subRows')}
selectedRowIds={object('selectedRowIds', { 3: true })}
selectionBehavior={select<TableSelectionBehavior>(
'selectionBehavior',
TableSelectionBehavior,
TableSelectionBehavior.ROW
)}
isTreeTable={boolean('isTreeTable', true)}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,45 @@
import { CssSizeVariablesNames } from '@ui5/webcomponents-react-base/lib/CssSizeVariables';
import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils';
import { CheckBox } from '@ui5/webcomponents-react/lib/CheckBox';
import { TableSelectionBehavior } from '@ui5/webcomponents-react/lib/TableSelectionBehavior';
import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode';
import React from 'react';
import { PluginHook } from 'react-table';

const divStyle = { width: '100%', height: '100%' };
const divStyle = { width: '100%', height: '100%', cursor: 'pointer' };
const customCheckBoxStyling = {
'--_ui5_checkbox_compact_width_height': 'var(--_ui5_checkbox_compact_inner_size)',
'--_ui5_checkbox_width_height': 'var(--_ui5_checkbox_inner_width_height)',
cursor: 'pointer',
verticalAlign: 'middle'
};
const noop = () => {
// do nothing
};

export const useRowSelectionColumn: PluginHook<{}> = (hooks) => {
hooks.columns.push((columns, { instance }) => {
const { selectionMode, noSelectionColumn, onRowSelected } = instance.webComponentsReactProperties;
const { webComponentsReactProperties } = instance;
const { selectionMode, onRowSelected, selectionBehavior, tableRef } = webComponentsReactProperties;

if (selectionMode === TableSelectionMode.NONE || noSelectionColumn) {
if (selectionMode === TableSelectionMode.NONE || selectionBehavior === TableSelectionBehavior.ROW_ONLY) {
return columns;
}

const toggleAllRowsSelected = (e) => {
const allRowsSelected = e.detail.checked;
const allRowsSelected = e.target.checked;
instance.toggleAllRowsSelected(allRowsSelected);
if (typeof onRowSelected === 'function') {
onRowSelected(enrichEventWithDetails(e, { allRowsSelected }));
onRowSelected(
//cannot use instance.selectedFlatRows here as it only returns all rows on the first level
enrichEventWithDetails(e, { allRowsSelected, selectedFlatRows: allRowsSelected ? instance.flatRows : [] })
);
}
};

const selectionColumnWidth = tableRef.current
? parseInt(
getComputedStyle(tableRef.current).getPropertyValue(
`--${CssSizeVariablesNames.sapWcrAnalyticalTableSelectionColumnWidth}`
),
10
)
: 47;
return [
// Let's make a column for selection
{
Expand All @@ -40,8 +50,9 @@ export const useRowSelectionColumn: PluginHook<{}> = (hooks) => {
disableGroupBy: true,
disableResizing: true,
canReorder: false,
width: 36,
minWidth: 36,
width: selectionColumnWidth,
minWidth: selectionColumnWidth,
maxWidth: selectionColumnWidth,
// The header can use the table's getToggleAllRowsSelectedProps method
// to render a checkbox
// eslint-disable-next-line react/prop-types,react/display-name
Expand All @@ -61,35 +72,40 @@ export const useRowSelectionColumn: PluginHook<{}> = (hooks) => {
// to the render a checkbox
// eslint-disable-next-line react/prop-types,react/display-name
Cell: ({ row }) => {
const handleCellClick = (e) => {
if (TableSelectionBehavior.ROW_SELECTOR === selectionBehavior) {
row.getRowProps().onClick(e, true);
}
};
if (row.isGrouped && selectionMode === TableSelectionMode.SINGLE_SELECT) {
return null;
}
if (selectionMode === TableSelectionMode.SINGLE_SELECT) {
// eslint-disable-next-line react/prop-types
return <div style={divStyle} onClick={row.toggleRowSelected} />;
return <div style={divStyle} onClick={handleCellClick} />;
}
// eslint-disable-next-line react/prop-types
return <CheckBox {...row.getToggleRowSelectedProps()} onChange={noop} style={customCheckBoxStyling} />;
return (
<CheckBox {...row.getToggleRowSelectedProps()} onChange={handleCellClick} style={customCheckBoxStyling} />
);
}
},
...columns
];
});

hooks.columnsDeps.push((deps, { instance: { state, webComponentsReactProperties } }) => {
return [...deps, webComponentsReactProperties.selectionMode, webComponentsReactProperties.noSelectionColumn];
return [...deps, webComponentsReactProperties.selectionMode, webComponentsReactProperties.selectionBehavior];
});

hooks.visibleColumnsDeps.push((deps, { instance }) => [
...deps,
instance.webComponentsReactProperties.noSelectionColumn,
instance.webComponentsReactProperties.selectionMode
instance.webComponentsReactProperties.selectionMode,
instance.webComponentsReactProperties.selectionBehavior
]);

hooks.visibleColumns.push((columns, { instance: { webComponentsReactProperties } }) => {
if (
webComponentsReactProperties.noSelectionColumn ||
webComponentsReactProperties.selectionMode === TableSelectionMode.NONE
webComponentsReactProperties.selectionMode === TableSelectionMode.NONE ||
webComponentsReactProperties.selectionBehavior === TableSelectionBehavior.ROW_ONLY
) {
return columns;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { enrichEventWithDetails } from '@ui5/webcomponents-react-base/lib/Utils';
import { TableSelectionBehavior } from '@ui5/webcomponents-react/lib/TableSelectionBehavior';
import { TableSelectionMode } from '@ui5/webcomponents-react/lib/TableSelectionMode';
import { PluginHook } from 'react-table';

export const useSingleRowStateSelection: PluginHook<{}> = (hooks) => {
hooks.getRowProps.push((passedRowProps, { instance, row }) => {
const { webComponentsReactProperties, dispatch, toggleRowSelected, selectedFlatRows } = instance;
const { isTreeTable, selectionMode, onRowSelected, selectionBehavior } = webComponentsReactProperties;
const rowProps = { ...passedRowProps };
const isEmptyRow = row.original?.emptyRow;

if ([TableSelectionMode.SINGLE_SELECT, TableSelectionMode.MULTI_SELECT].includes(selectionMode) && !isEmptyRow) {
rowProps.onClick = (e, selectionCellClick = false) => {
if (row.isGrouped || (TableSelectionBehavior.ROW_SELECTOR === selectionBehavior && !selectionCellClick)) {
return;
}
if (isTreeTable) {
if (selectionMode === TableSelectionMode.MULTI_SELECT) {
dispatch({
type: 'SET_SELECTED_ROWS',
selectedIds: Object.assign({}, ...selectedFlatRows.map((item) => ({ [item.id]: true })), {
[row.id]: !row.isSelected
})
});
} else {
dispatch({ type: 'SET_SELECTED_ROWS', selectedIds: { [row.id]: !row.isSelected } });
}
} else {
row.toggleRowSelected();
}
if (typeof onRowSelected === 'function') {
const payload = {
row,
isSelected: !row.isSelected
};
const payloadWithFlatRows = {
...payload,
selectedFlatRows: !row.isSelected
? [...selectedFlatRows, row]
: selectedFlatRows.filter((prevRow) => prevRow.id !== row.id)
};
onRowSelected(
enrichEventWithDetails(e, TableSelectionMode.MULTI_SELECT === selectionMode ? payloadWithFlatRows : payload)
);
}
if (selectionMode === TableSelectionMode.SINGLE_SELECT && !isTreeTable) {
selectedFlatRows.forEach(({ id }) => {
toggleRowSelected(id, false);
});
}
};
}

return rowProps;
});
};

useSingleRowStateSelection.pluginName = 'useSingleRowStateSelection';
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const useTableCellStyling: PluginHook<{}> = (hooks) => {
className += ` ${column.className}`;
}

if (column.id === '__ui5wcr__internal_highlight_column') {
if (column.id === '__ui5wcr__internal_highlight_column' || column.id === '__ui5wcr__internal_selection_column') {
style.padding = 0;
}

Expand All @@ -59,7 +59,6 @@ export const useTableCellStyling: PluginHook<{}> = (hooks) => {
style.boxSizing = 'border-box';
style.width = `calc(${cellProps.style.width} - ${ThemingParameters.sapScrollBar_Dimension})`;
}

return {
...cellProps,
className,
Expand Down
Loading