From 5f3d4503637c850c63d7dd96f9705c77645ed287 Mon Sep 17 00:00:00 2001 From: Matt Gallo Date: Thu, 17 Aug 2023 16:03:03 -0400 Subject: [PATCH 1/3] feat(DataTable): render select all button is onSelectAll is provided --- .../__snapshots__/PublicAPI-test.js.snap | 14 ++++ .../src/components/DataTable/DataTable.tsx | 4 + .../components/DataTable/TableBatchActions.js | 29 +++++++ .../DataTable/__tests__/DataTable-test.js | 55 ++++++++----- .../__snapshots__/DataTable-test.js.snap | 80 ++++++++++++------- .../DataTable-batch-actions.stories.js | 10 ++- .../data-table/action/_data-table-action.scss | 4 + 7 files changed, 147 insertions(+), 49 deletions(-) diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index 6eed0b2fc2e6..8aa8038a1631 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -1874,9 +1874,15 @@ Map { "isRequired": true, "type": "func", }, + "onSelectAll": Object { + "type": "func", + }, "shouldShowBatchActions": Object { "type": "bool", }, + "totalCount": Object { + "type": "number", + }, "totalSelected": Object { "isRequired": true, "type": "number", @@ -1889,6 +1895,7 @@ Map { "carbon.table.batch.cancel", "carbon.table.batch.items.selected", "carbon.table.batch.item.selected", + "carbon.table.batch.selectAll", ], }, "TableBody": Object { @@ -7805,9 +7812,15 @@ Map { "isRequired": true, "type": "func", }, + "onSelectAll": Object { + "type": "func", + }, "shouldShowBatchActions": Object { "type": "bool", }, + "totalCount": Object { + "type": "number", + }, "totalSelected": Object { "isRequired": true, "type": "number", @@ -7820,6 +7833,7 @@ Map { "carbon.table.batch.cancel", "carbon.table.batch.items.selected", "carbon.table.batch.item.selected", + "carbon.table.batch.selectAll", ], }, "TableBody" => Object { diff --git a/packages/react/src/components/DataTable/DataTable.tsx b/packages/react/src/components/DataTable/DataTable.tsx index e1d578e0a171..28efb0e0a3af 100644 --- a/packages/react/src/components/DataTable/DataTable.tsx +++ b/packages/react/src/components/DataTable/DataTable.tsx @@ -170,7 +170,9 @@ export interface DataTableRenderProps { [key: string]: unknown; }) => { onCancel: () => void; + onSelectAll: () => void; shouldShowBatchActions: boolean; + totalCount: number; totalSelected: number; [key: string]: unknown; }; @@ -644,6 +646,8 @@ class DataTable extends React.Component< const { shouldShowBatchActions } = this.state; const totalSelected = this.getSelectedRows().length; return { + onSelectAll: () => {}, + totalCount: this.state.rowIds.length || 0, ...props, shouldShowBatchActions: shouldShowBatchActions && totalSelected > 0, totalSelected, diff --git a/packages/react/src/components/DataTable/TableBatchActions.js b/packages/react/src/components/DataTable/TableBatchActions.js index 9f24cf3152eb..cd9fac394d69 100644 --- a/packages/react/src/components/DataTable/TableBatchActions.js +++ b/packages/react/src/components/DataTable/TableBatchActions.js @@ -17,12 +17,16 @@ const translationKeys = { 'carbon.table.batch.cancel': 'Cancel', 'carbon.table.batch.items.selected': 'items selected', 'carbon.table.batch.item.selected': 'item selected', + 'carbon.table.batch.selectAll': 'Select all', }; const translateWithId = (id, state) => { if (id === 'carbon.table.batch.cancel') { return translationKeys[id]; } + if (id === 'carbon.table.batch.selectAll') { + return `${translationKeys[id]} (${state.totalCount})`; + } return `${state.totalSelected} ${translationKeys[id]}`; }; @@ -31,7 +35,9 @@ const TableBatchActions = ({ children, shouldShowBatchActions, totalSelected, + totalCount, onCancel, + onSelectAll, translateWithId: t, ...rest }) => { @@ -65,6 +71,16 @@ const TableBatchActions = ({ : t('carbon.table.batch.item.selected', { totalSelected })}

+ {onSelectAll && ( + <> + | + + + )} {children} @@ -91,12 +107,25 @@ TableBatchActions.propTypes = { */ onCancel: PropTypes.func.isRequired, + /** + * Hook required to listen for when the user initiates a select all + * request through this component. This _only_ controls the rendering + * of the `Select All` button and does not include built in functionality + */ + onSelectAll: PropTypes.func, + /** * Boolean specifier for whether or not the batch action bar should be * displayed */ shouldShowBatchActions: PropTypes.bool, + /** + * Numeric representation of the total number of items in a table. + * This number is used in the select all button text + */ + totalCount: PropTypes.number, + /** * Numeric representation of the total number of items selected in a table. * This number is used to derive the selection message diff --git a/packages/react/src/components/DataTable/__tests__/DataTable-test.js b/packages/react/src/components/DataTable/__tests__/DataTable-test.js index 003b4a791cd7..98a8b4165dca 100644 --- a/packages/react/src/components/DataTable/__tests__/DataTable-test.js +++ b/packages/react/src/components/DataTable/__tests__/DataTable-test.js @@ -35,28 +35,32 @@ import { render, screen, within } from '@testing-library/react'; const getLastCallFor = (mocker) => mocker.mock.calls[mocker.mock.calls.length - 1]; +const onSelectAllFn = jest.fn(); + +const rows = [ + { + id: 'b', + fieldA: 'Field 2:A', + fieldB: 'Field 2:B', + }, + { + id: 'a', + fieldA: 'Field 1:A', + fieldB: 'Field 1:B', + }, + { + id: 'c', + fieldA: 'Field 3:A', + fieldB: 'Field 3:B', + }, +]; + describe('DataTable', () => { let mockProps; beforeEach(() => { mockProps = { - rows: [ - { - id: 'b', - fieldA: 'Field 2:A', - fieldB: 'Field 2:B', - }, - { - id: 'a', - fieldA: 'Field 1:A', - fieldB: 'Field 1:B', - }, - { - id: 'c', - fieldA: 'Field 3:A', - fieldB: 'Field 3:B', - }, - ], + rows, headers: [ { key: 'fieldA', @@ -334,7 +338,10 @@ describe('DataTable', () => { }) => ( - + Ghost @@ -452,6 +459,18 @@ describe('DataTable', () => { const { selectedRows } = getLastCallFor(mockProps.render)[0]; expect(selectedRows.length).toBe(0); }); + + it('should call the onSelectAll prop if supplied to TableBatchAction component', async () => { + render(); + const selectAllCheckbox = screen.getAllByRole('checkbox')[0]; + + await userEvent.click(selectAllCheckbox); + expect(selectAllCheckbox).toBeChecked(); + + const selectAllButton = screen.getByText(`Select all (${rows.length})`); + await userEvent.click(selectAllButton); + expect(onSelectAllFn).toHaveBeenCalledTimes(1); + }); }); describe('selection with filtering', () => { diff --git a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap index 9b94f0ef8686..34d188921d37 100644 --- a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap +++ b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap @@ -10,20 +10,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should not hav >

DataTable with selection

@@ -60,14 +60,14 @@ exports[`DataTable behaves as expected selection -- radio buttons should not hav >
@@ -229,14 +229,14 @@ exports[`DataTable behaves as expected selection -- radio buttons should render >
@@ -775,13 +787,13 @@ exports[`DataTable renders as expected - Component API should render and match s >

DataTable with toolbar

+ + | + +
diff --git a/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js b/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js index 068ad7666b7a..a9b0f9a57b49 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js @@ -73,7 +73,11 @@ export const Default = () => ( getTableProps, getTableContainerProps, }) => { - const batchActionProps = getBatchActionProps(); + const batchActionProps = { + ...getBatchActionProps({ + onSelectAll: action('Select all rows across all pages'), + }), + }; return ( ( @@ -236,7 +240,7 @@ export const Playground = (args) => ( diff --git a/packages/styles/scss/components/data-table/action/_data-table-action.scss b/packages/styles/scss/components/data-table/action/_data-table-action.scss index 37cca71b0717..3be4eb510ce8 100644 --- a/packages/styles/scss/components/data-table/action/_data-table-action.scss +++ b/packages/styles/scss/components/data-table/action/_data-table-action.scss @@ -510,6 +510,10 @@ @include type-style('body-compact-01'); } + .#{$prefix}--batch-summary__divider { + padding-left: $spacing-03; + } + //------------------------------------------------- //SMALL TOOLBAR //------------------------------------------------- From 3bef839480492133f71d798ca8953fbfa04d4a87 Mon Sep 17 00:00:00 2001 From: Matt Gallo Date: Mon, 21 Aug 2023 09:23:18 -0400 Subject: [PATCH 2/3] fix(DataTable): update onSelectAll type --- packages/react/src/components/DataTable/DataTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react/src/components/DataTable/DataTable.tsx b/packages/react/src/components/DataTable/DataTable.tsx index 28efb0e0a3af..6d4cadde6b74 100644 --- a/packages/react/src/components/DataTable/DataTable.tsx +++ b/packages/react/src/components/DataTable/DataTable.tsx @@ -170,7 +170,7 @@ export interface DataTableRenderProps { [key: string]: unknown; }) => { onCancel: () => void; - onSelectAll: () => void; + onSelectAll?: () => void | undefined; shouldShowBatchActions: boolean; totalCount: number; totalSelected: number; @@ -646,7 +646,7 @@ class DataTable extends React.Component< const { shouldShowBatchActions } = this.state; const totalSelected = this.getSelectedRows().length; return { - onSelectAll: () => {}, + onSelectAll: undefined, totalCount: this.state.rowIds.length || 0, ...props, shouldShowBatchActions: shouldShowBatchActions && totalSelected > 0, From 8a6caad1c97108e911cac95a052bb42dd6266ac0 Mon Sep 17 00:00:00 2001 From: Matt Gallo Date: Mon, 21 Aug 2023 09:54:29 -0400 Subject: [PATCH 3/3] chore: update test snapshot --- .../__snapshots__/DataTable-test.js.snap | 44 +++++++------------ 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap index 34d188921d37..099615dfc45c 100644 --- a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap +++ b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap @@ -10,20 +10,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should not hav >

DataTable with selection

@@ -179,20 +179,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should render >

DataTable with selection

@@ -348,13 +348,13 @@ exports[`DataTable behaves as expected selection should render and match snapsho >

DataTable with selection

@@ -787,13 +787,13 @@ exports[`DataTable renders as expected - Component API should render and match s >

DataTable with toolbar

- - | - -