Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
Flowsheet Data Grid - Row Selection
Browse files Browse the repository at this point in the history
  • Loading branch information
smason0 committed Nov 20, 2023
1 parent 457d4b4 commit 76cacb6
Show file tree
Hide file tree
Showing 33 changed files with 596 additions and 96 deletions.
22 changes: 16 additions & 6 deletions packages/terra-data-grid/src/FlowsheetDataGrid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ const propTypes = {
*/
onCellRangeSelect: PropTypes.func,

/**
* Callback function that is called when a row header cell is selected. Parameters:
* @param {string} rowId rowId
*/
onRowSelect: PropTypes.func,

/**
* @private
* The intl object containing translations. This is retrieved from the context automatically by injectIntl.
Expand Down Expand Up @@ -121,6 +127,7 @@ function FlowsheetDataGrid(props) {
onSectionSelect,
onClearSelectedCells,
onCellRangeSelect,
onRowSelect,
intl,
hasVisibleColumnHeaders,
} = props;
Expand Down Expand Up @@ -223,6 +230,10 @@ function FlowsheetDataGrid(props) {
}, [intl, rows, columns, setCellSelectionAriaLiveMessage]);

const selectCellRange = useCallback((rowIndex, columnIndex) => {
if (anchorCell.current === null) {
return;
}

const anchorRowIndex = rows.findIndex(row => row.id === anchorCell.current.rowId);
const anchorColumnIndex = columns.findIndex(col => col.id === anchorCell.current.columnId);

Expand All @@ -247,18 +258,17 @@ function FlowsheetDataGrid(props) {
}, [rows, columns, onCellRangeSelect]);

const handleCellSelection = useCallback((selectionDetails) => {
// Exclude the row header column.
if (selectionDetails.columnIndex === 0) {
return;
}

if (selectionDetails.isShiftPressed && anchorCell.current !== null) {
if (onRowSelect) {
onRowSelect(selectionDetails.rowId);
}
} else if (selectionDetails.isShiftPressed && anchorCell.current !== null) {
selectCellRange(selectionDetails.rowIndex, selectionDetails.columnIndex);
} else if (onCellSelect) {
anchorCell.current = { rowId: selectionDetails.rowId, columnId: selectionDetails.columnId };
onCellSelect(selectionDetails.rowId, selectionDetails.columnId);
}
}, [onCellSelect, selectCellRange]);
}, [onCellSelect, onRowSelect, selectCellRange]);

const handleCellRangeSelection = useCallback((rowIndex, columnIndex, direction) => {
// Exclude the row header column as an eligible anchor/start cell.
Expand Down
25 changes: 25 additions & 0 deletions packages/terra-data-grid/tests/jest/FlowsheetDataGrid.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -584,3 +584,28 @@ describe('Multi-cell selection', () => {
]);
});
});

describe('Row selection', () => {
let mockOnRowSelect = null;

beforeEach(() => {
mockOnRowSelect = jest.fn();
});

it('verifies single row selection when a row header cell is clicked', () => {
const wrapper = mountWithIntl(
<FlowsheetDataGrid
id="test-terra-flowsheet-data-grid"
columns={dataFile.cols}
rows={dataFile.rows}
ariaLabel="Test Flowsheet Data Grid"
onRowSelect={mockOnRowSelect}
/>,
);

const selectableCell = wrapper.find('Row').at(2).find('th.selectable').at(0);
selectableCell.simulate('mouseDown');

expect(mockOnRowSelect).toHaveBeenCalledWith('3');
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 62 additions & 23 deletions packages/terra-data-grid/tests/wdio/flowsheet-data-grid-spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const defaultSelector = '#default-terra-flowsheet-data-grid-table';

const holdDownShiftKey = () => {
browser.performActions([{
type: 'key',
Expand Down Expand Up @@ -40,7 +38,7 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
it('renders a default flowsheet data grid', () => {
browser.keys(['Tab']); // Cell 0,0 gets focus
expect(browser.$('tr.column-header-row th:nth-child(1)').isFocused()).toBe(true);
Terra.validates.element('default-flowsheet-data-grid', { selector: defaultSelector });
Terra.validates.element('default-flowsheet-data-grid', { selector: '#default-terra-flowsheet-data-grid-table' });
});
});

Expand Down Expand Up @@ -70,16 +68,17 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
});

describe('Cell selection', () => {
const cellSelectionSelector = '#terra-flowsheet-data-grid-cell-selection-table';
beforeEach(() => {
browser.url('/raw/tests/cerner-terra-framework-docs/data-grid/flowsheet-data-grid/default-flowsheet-data-grid');
browser.url('/raw/tests/cerner-terra-framework-docs/data-grid/flowsheet-data-grid/cell-selection');
});

it('selects the current cell with spacebar', () => {
navigateToCell(1, 1);
browser.keys(['Space']);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(1) td:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-and-focus-on-1-1', { selector: defaultSelector });
Terra.validates.element('selection-and-focus-on-1-1', { selector: cellSelectionSelector });
});

it('validates that navigating the grid does not change the selected cell', () => {
Expand All @@ -88,7 +87,7 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
moveCurrentPositionBy(2, 0);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(3) td:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-1-1-focus-3-1', { selector: defaultSelector });
Terra.validates.element('selection-1-1-focus-3-1', { selector: cellSelectionSelector });
});

it('validates that selecting another cell moves the selection and focus to current cell', () => {
Expand All @@ -98,7 +97,7 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
browser.keys(['Space']);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(3) td:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-3-1-focus-3-1', { selector: defaultSelector });
Terra.validates.element('selection-3-1-focus-3-1', { selector: cellSelectionSelector });
});

it('validates that Shift+Space selects a range of cells starting at the first selected cell', () => {
Expand All @@ -109,7 +108,7 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
browser.keys(['Space']);
releaseShiftKey();

Terra.validates.element('selection-space-range-1-1-to-3-2', { selector: defaultSelector });
Terra.validates.element('selection-space-range-1-1-to-3-2', { selector: cellSelectionSelector });
});

it('validates that Shift+Arrow keys selects a range of cells starting at the first selected cell', () => {
Expand All @@ -119,7 +118,7 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
moveCurrentPositionBy(2, 1);
releaseShiftKey();

Terra.validates.element('selection-arrows-range-1-1-to-3-2', { selector: defaultSelector });
Terra.validates.element('selection-arrows-range-1-1-to-3-2', { selector: cellSelectionSelector });
});

it('validates that Shift+Arrow keys does not select row header cells when navigated to', () => {
Expand All @@ -130,7 +129,7 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
releaseShiftKey();

expect(browser.$('[role="grid"] tbody tr:nth-of-type(3) th:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-arrows-range-1-1-to-3-1-focus-3-0', { selector: defaultSelector });
Terra.validates.element('selection-arrows-range-1-1-to-3-1-focus-3-0', { selector: cellSelectionSelector });
});

it('validates that Shift+Arrow keys does not select column header cells when navigated to', () => {
Expand All @@ -141,47 +140,87 @@ Terra.describeViewports('FlowsheetDataGrid', ['medium', 'large'], () => {
releaseShiftKey();

expect(browser.$('tr.column-header-row th:nth-child(2)').isFocused()).toBe(true);
Terra.validates.element('selection-arrows-range-3-1-to-1-1-focus-0-1', { selector: defaultSelector });
Terra.validates.element('selection-arrows-range-3-1-to-1-1-focus-0-1', { selector: cellSelectionSelector });
});

it('validates that clicking on a cell, moves selection and focus to that cell', () => {
clickCell(3, 1, defaultSelector);
clickCell(3, 1, cellSelectionSelector);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(3) td:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-3-1-focus-3-1-with-hover', { selector: defaultSelector });
Terra.validates.element('selection-3-1-focus-3-1-with-hover', { selector: cellSelectionSelector });
});

it('validates that navigation does not change cell selected via mouse click', () => {
clickCell(3, 1, defaultSelector);
clickCell(3, 1, cellSelectionSelector);
moveCurrentPositionBy(-2, -1);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(1) th:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-3-1-focus-1-0', { selector: defaultSelector });
Terra.validates.element('selection-3-1-focus-1-0', { selector: cellSelectionSelector });
});

it('validates that mouse click moves selection and focus to clicked cell', () => {
clickCell(3, 1, defaultSelector);
clickCell(4, 2, defaultSelector);
clickCell(3, 1, cellSelectionSelector);
clickCell(4, 2, cellSelectionSelector);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(4) td:nth-of-type(2)').isFocused()).toBe(true);
Terra.validates.element('selection-4-2-focus-4-2', { selector: defaultSelector });
Terra.validates.element('selection-4-2-focus-4-2', { selector: cellSelectionSelector });
});

it('validates that Shift+Click selects a range of cells starting at the first selected cell', () => {
clickCell(3, 1, defaultSelector);
clickCell(3, 1, cellSelectionSelector);
holdDownShiftKey();
clickCell(4, 2, defaultSelector);
clickCell(4, 2, cellSelectionSelector);
releaseShiftKey();

Terra.validates.element('selection-click-range-3-1-to-4-2', { selector: defaultSelector });
Terra.validates.element('selection-click-range-3-1-to-4-2', { selector: cellSelectionSelector });
});

it('clears selection with Esc key', () => {
clickCell(3, 1, defaultSelector);
clickCell(3, 1, cellSelectionSelector);
browser.keys(['Escape']);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(3) td:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('cell-3-1-focused', { selector: defaultSelector });
Terra.validates.element('cell-3-1-focused', { selector: cellSelectionSelector });
});
});

describe('Row selection', () => {
const rowSelectionSelector = '#terra-flowsheet-data-grid-row-selection-table';
beforeEach(() => {
browser.url('/raw/tests/cerner-terra-framework-docs/data-grid/flowsheet-data-grid/row-selection');
});

it('validates that selecting the row header cell with spacebar selects the current row', () => {
navigateToCell(1, 0);
browser.keys(['Space']);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(1) th:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-row-1-with-space', { selector: rowSelectionSelector });
});

it('validates that selecting another row header cell moves the selection and focus to current cell and selects the current row', () => {
navigateToCell(1, 0);
browser.keys(['Space']);
moveCurrentPositionBy(2, 0);
browser.keys(['Space']);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(3) th:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-row-3-changed-with-space', { selector: rowSelectionSelector });
});

it('validates that mouse click on a row header cell selects the current row', () => {
clickCell(2, 0, rowSelectionSelector);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(2) th:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-row-2-with-click', { selector: rowSelectionSelector });
});

it('validates that mouse click moves selection and focus to clicked row header cell and selects the current row', () => {
clickCell(2, 0, rowSelectionSelector);
clickCell(4, 0, rowSelectionSelector);

expect(browser.$('[role="grid"] tbody tr:nth-of-type(4) th:nth-of-type(1)').isFocused()).toBe(true);
Terra.validates.element('selection-row-4-changed-with-click', { selector: rowSelectionSelector });
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import RowSelection from './RowSelection?dev-site-example';

# Row Selection

### Description
This example demonstrates a Flowsheet Data Grid with row selection support by utilizing the following [properties](/components/cerner-terra-framework-docs/data-grid/flowsheet-data-grid/about#properties):

* The **onRowSelect** callback prop: When the user selects a row header cell (a cell in the pinned first column), this callback will be called with the `rowId` of the selected row.
In this example, the `isSelected` row property is toggled to true, adding highlighting to the selected row.

<RowSelection title='Flowsheet Data Grid with Row Selection' />
Loading

0 comments on commit 76cacb6

Please sign in to comment.