Skip to content

Commit b5820c6

Browse files
author
Amrit Kashyap Borah
committed
fix: RB table bulk actions props
1 parent 0d590b3 commit b5820c6

10 files changed

Lines changed: 276 additions & 174 deletions

File tree

Lines changed: 8 additions & 0 deletions
Loading

src/Common/Hooks/UseRegisterShortcut/UseRegisterShortcutProvider.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,6 @@ const UseRegisterShortcutProvider = ({
117117
}, [])
118118

119119
const handleKeydownEvent = useCallback((event: KeyboardEvent) => {
120-
if (preventDefault) {
121-
event.preventDefault()
122-
}
123-
124120
if (
125121
// NOTE: in case of custom events generated by password managers autofill, the event.key is not set
126122
!event.key ||
@@ -132,6 +128,10 @@ const UseRegisterShortcutProvider = ({
132128
return
133129
}
134130

131+
if (preventDefault) {
132+
event.preventDefault()
133+
}
134+
135135
keysDownRef.current.add(event.key.toUpperCase() as Uppercase<string>)
136136

137137
if (event.ctrlKey) {

src/Shared/Components/BulkSelection/BulkSelection.tsx

Lines changed: 70 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { forwardRef } from 'react'
18+
1719
import { ReactComponent as ICCheckAll } from '../../../Assets/Icon/ic-check-all.svg'
1820
import { ReactComponent as ICCheckSquare } from '../../../Assets/Icon/ic-check-square.svg'
1921
import { ReactComponent as ICChevronDown } from '../../../Assets/Icon/ic-chevron-down.svg'
@@ -24,74 +26,77 @@ import { useBulkSelection } from './BulkSelectionProvider'
2426
import { BULK_DROPDOWN_TEST_ID, BulkSelectionOptionsLabels } from './constants'
2527
import { BulkSelectionDropdownItemsType, BulkSelectionEvents, BulkSelectionProps } from './types'
2628

27-
const BulkSelection = <T,>({ showPagination, disabled = false, showChevronDownIcon = true }: BulkSelectionProps) => {
28-
const { handleBulkSelection, isChecked, checkboxValue, getSelectedIdentifiersCount } = useBulkSelection<T>()
29-
const areOptionsSelected = getSelectedIdentifiersCount() > 0
30-
const BulkSelectionItems: BulkSelectionDropdownItemsType[] = [
31-
{
32-
locator: BulkSelectionEvents.SELECT_ALL_ON_PAGE,
33-
label: BulkSelectionOptionsLabels[BulkSelectionEvents.SELECT_ALL_ON_PAGE],
34-
isSelected: isChecked && checkboxValue === CHECKBOX_VALUE.CHECKED,
35-
icon: ICCheckSquare,
36-
},
37-
...(showPagination
38-
? [
39-
{
40-
locator: BulkSelectionEvents.SELECT_ALL_ACROSS_PAGES,
41-
label: BulkSelectionOptionsLabels[BulkSelectionEvents.SELECT_ALL_ACROSS_PAGES],
42-
isSelected: isChecked && checkboxValue === CHECKBOX_VALUE.BULK_CHECKED,
43-
icon: ICCheckAll,
44-
},
45-
]
46-
: []),
47-
...(areOptionsSelected
48-
? [
49-
{
50-
locator: BulkSelectionEvents.CLEAR_ALL_SELECTIONS,
51-
label: BulkSelectionOptionsLabels[BulkSelectionEvents.CLEAR_ALL_SELECTIONS],
52-
isSelected: false,
53-
icon: ICClose,
54-
iconClass: 'icon-use-fill-n6',
55-
},
56-
]
57-
: []),
58-
]
29+
const BulkSelection = forwardRef(
30+
({ showPagination, disabled = false, showChevronDownIcon = true }: BulkSelectionProps, forwardedRef) => {
31+
const { handleBulkSelection, isChecked, checkboxValue, getSelectedIdentifiersCount } = useBulkSelection()
32+
const areOptionsSelected = getSelectedIdentifiersCount() > 0
33+
const BulkSelectionItems: BulkSelectionDropdownItemsType[] = [
34+
{
35+
locator: BulkSelectionEvents.SELECT_ALL_ON_PAGE,
36+
label: BulkSelectionOptionsLabels[BulkSelectionEvents.SELECT_ALL_ON_PAGE],
37+
isSelected: isChecked && checkboxValue === CHECKBOX_VALUE.CHECKED,
38+
icon: ICCheckSquare,
39+
},
40+
...(showPagination
41+
? [
42+
{
43+
locator: BulkSelectionEvents.SELECT_ALL_ACROSS_PAGES,
44+
label: BulkSelectionOptionsLabels[BulkSelectionEvents.SELECT_ALL_ACROSS_PAGES],
45+
isSelected: isChecked && checkboxValue === CHECKBOX_VALUE.BULK_CHECKED,
46+
icon: ICCheckAll,
47+
},
48+
]
49+
: []),
50+
...(areOptionsSelected
51+
? [
52+
{
53+
locator: BulkSelectionEvents.CLEAR_ALL_SELECTIONS,
54+
label: BulkSelectionOptionsLabels[BulkSelectionEvents.CLEAR_ALL_SELECTIONS],
55+
isSelected: false,
56+
icon: ICClose,
57+
iconClass: 'icon-use-fill-n6',
58+
},
59+
]
60+
: []),
61+
]
5962

60-
return (
61-
<PopupMenu autoClose>
62-
<PopupMenu.Button
63-
isKebab
64-
rootClassName="h-20 flexbox p-0 dc__no-background dc__no-border dc__outline-none-imp"
65-
dataTestId={BULK_DROPDOWN_TEST_ID}
66-
disabled={disabled}
67-
>
68-
<Checkbox
69-
isChecked={isChecked}
70-
onChange={noop}
71-
rootClassName="icon-dim-20 m-0"
72-
value={checkboxValue}
63+
return (
64+
<PopupMenu autoClose>
65+
<PopupMenu.Button
66+
ref={forwardedRef}
67+
isKebab
68+
rootClassName="h-20 flexbox p-0 dc__no-background dc__no-border dc__outline-none-imp"
69+
dataTestId={BULK_DROPDOWN_TEST_ID}
7370
disabled={disabled}
74-
// Ideally should be disabled but was giving issue with cursor
75-
/>
71+
>
72+
<Checkbox
73+
isChecked={isChecked}
74+
onChange={noop}
75+
rootClassName="icon-dim-20 m-0"
76+
value={checkboxValue}
77+
disabled={disabled}
78+
// Ideally should be disabled but was giving issue with cursor
79+
/>
7680

77-
{showChevronDownIcon && <ICChevronDown className="icon-dim-20 fcn-6 dc__no-shrink" />}
78-
</PopupMenu.Button>
81+
{showChevronDownIcon && <ICChevronDown className="icon-dim-20 fcn-6 dc__no-shrink" />}
82+
</PopupMenu.Button>
7983

80-
<PopupMenu.Body rootClassName="dc__top-22 w-150 dc__right-0 pt-4 pb-4 pl-0 pr-0 bg__primary flex column dc__content-start dc__align-start dc__position-abs bg__primary dc__border dc__border-radius-4-imp">
81-
{BulkSelectionItems.map((item) => (
82-
<BulkSelectionDropdownItems<T>
83-
key={item.locator}
84-
locator={item.locator}
85-
label={item.label}
86-
isSelected={item.isSelected}
87-
icon={item.icon}
88-
handleBulkSelection={handleBulkSelection}
89-
iconClass={item.iconClass}
90-
/>
91-
))}
92-
</PopupMenu.Body>
93-
</PopupMenu>
94-
)
95-
}
84+
<PopupMenu.Body rootClassName="dc__top-22 w-150 dc__right-0 pt-4 pb-4 pl-0 pr-0 bg__primary flex column dc__content-start dc__align-start dc__position-abs bg__primary dc__border dc__border-radius-4-imp">
85+
{BulkSelectionItems.map((item) => (
86+
<BulkSelectionDropdownItems
87+
key={item.locator}
88+
locator={item.locator}
89+
label={item.label}
90+
isSelected={item.isSelected}
91+
icon={item.icon}
92+
handleBulkSelection={handleBulkSelection}
93+
iconClass={item.iconClass}
94+
/>
95+
))}
96+
</PopupMenu.Body>
97+
</PopupMenu>
98+
)
99+
},
100+
)
96101

97102
export default BulkSelection

src/Shared/Components/BulkSelection/BulkSelectionDropdownItems.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616

1717
import { BulkSelectionDropdownItemsProps } from './types'
1818

19-
const BulkSelectionDropdownItems = <T,>({
19+
const BulkSelectionDropdownItems = ({
2020
locator,
2121
label,
2222
isSelected,
2323
handleBulkSelection,
2424
icon: Icon,
2525
iconClass,
26-
}: BulkSelectionDropdownItemsProps<T>) => {
26+
}: BulkSelectionDropdownItemsProps<unknown>) => {
2727
const handleSelect = () => {
2828
handleBulkSelection({
2929
action: locator,

src/Shared/Components/Icon/Icon.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import { ReactComponent as ICHelpOutline } from '@IconsV2/ic-help-outline.svg'
8989
import { ReactComponent as ICHibernate } from '@IconsV2/ic-hibernate.svg'
9090
import { ReactComponent as ICInProgress } from '@IconsV2/ic-in-progress.svg'
9191
import { ReactComponent as ICInfoFilled } from '@IconsV2/ic-info-filled.svg'
92+
import { ReactComponent as ICInfoFilledColor } from '@IconsV2/ic-info-filled-color.svg'
9293
import { ReactComponent as ICInfoOutline } from '@IconsV2/ic-info-outline.svg'
9394
import { ReactComponent as ICInstall } from '@IconsV2/ic-install.svg'
9495
import { ReactComponent as ICJobColor } from '@IconsV2/ic-job-color.svg'
@@ -245,6 +246,7 @@ export const iconMap = {
245246
'ic-help-outline': ICHelpOutline,
246247
'ic-hibernate': ICHibernate,
247248
'ic-in-progress': ICInProgress,
249+
'ic-info-filled-color': ICInfoFilledColor,
248250
'ic-info-filled': ICInfoFilled,
249251
'ic-info-outline': ICInfoOutline,
250252
'ic-install': ICInstall,

src/Shared/Components/Table/BulkSelectionActionWidget.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) 2024. Devtron Inc.
33
*/
44

5-
import { useEffect } from 'react'
5+
import { MouseEvent, useEffect } from 'react'
66

77
import { ReactComponent as ICClose } from '@Icons/ic-close.svg'
88
import { DraggableButton, DraggablePositionVariant, DraggableWrapper } from '@Common/DraggableWrapper'
@@ -18,6 +18,8 @@ const BulkSelectionActionWidget = ({
1818
handleClearBulkSelection,
1919
parentRef,
2020
BulkActionsComponent,
21+
bulkActionsData,
22+
setBulkActionState,
2123
}: BulkSelectionActionWidgetProps) => {
2224
const { registerShortcut, unregisterShortcut } = useRegisterShortcut()
2325

@@ -29,6 +31,13 @@ const BulkSelectionActionWidget = ({
2931
}
3032
}, [])
3133

34+
const onActionClick = (event: MouseEvent<HTMLButtonElement>) => {
35+
const {
36+
dataset: { key },
37+
} = event.currentTarget
38+
setBulkActionState(key)
39+
}
40+
3241
return (
3342
<DraggableWrapper
3443
dragSelector={`.${DRAG_SELECTOR_IDENTIFIER}`}
@@ -46,7 +55,7 @@ const BulkSelectionActionWidget = ({
4655
</div>
4756
</div>
4857

49-
<BulkActionsComponent />
58+
<BulkActionsComponent onActionClick={onActionClick} bulkActionsData={bulkActionsData} />
5059

5160
<Button
5261
icon={<ICClose />}

src/Shared/Components/Table/InternalTable.tsx

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Fragment, useEffect, useMemo, useRef } from 'react'
1+
import { Fragment, useEffect, useMemo, useRef, useState } from 'react'
22

33
import { Checkbox } from '@Common/Checkbox'
44
import { DEFAULT_BASE_PAGE_SIZE } from '@Common/Constants'
@@ -16,7 +16,7 @@ import { SortableTableHeaderCell } from '@Common/SortableTableHeaderCell'
1616
import { BulkSelection } from '../BulkSelection'
1717
import BulkSelectionActionWidget from './BulkSelectionActionWidget'
1818
import { BULK_ACTION_GUTTER_LABEL, EVENT_TARGET, NO_ROWS_OR_GET_ROWS_ERROR, SHIMMER_DUMMY_ARRAY } from './constants'
19-
import { FiltersTypeEnum, InternalTableProps, PaginationEnum, SignalsType } from './types'
19+
import { BulkActionStateType, FiltersTypeEnum, InternalTableProps, PaginationEnum, SignalsType } from './types'
2020
import useTableWithKeyboardShortcuts from './useTableWithKeyboardShortcuts'
2121
import { getFilteringPromise, searchAndSortRows } from './utils'
2222

@@ -42,13 +42,20 @@ const InternalTable = ({
4242
handleToggleBulkSelectionOnRow,
4343
paginationVariant,
4444
RowActionsOnHoverComponent,
45-
children,
4645
}: InternalTableProps) => {
4746
const rowsContainerRef = useRef<HTMLDivElement>(null)
4847
const parentRef = useRef<HTMLDivElement>(null)
4948
const activeRowRef = useRef<HTMLDivElement>(null)
49+
const bulkSelectionButtonRef = useRef<HTMLButtonElement>(null)
5050

51-
const { BulkActionsComponent } = bulkSelectionConfig ?? {}
51+
const [bulkActionState, setBulkActionState] = useState<BulkActionStateType>(null)
52+
53+
const {
54+
BulkActionsComponent,
55+
bulkActionsData = null,
56+
BulkOperationModal,
57+
bulkOperationModalData = null,
58+
} = bulkSelectionConfig ?? {}
5259

5360
const { showSeparatorBetweenRows = true } = stylesConfig ?? {}
5461

@@ -115,7 +122,8 @@ const InternalTable = ({
115122

116123
const areFilteredRowsLoading = _areFilteredRowsLoading || filteredRowsError === NO_ROWS_OR_GET_ROWS_ERROR
117124

118-
const bulkSelectionCount = isBulkSelectionApplied && rows ? rows.length : (getSelectedIdentifiersCount?.() ?? 0)
125+
const bulkSelectionCount =
126+
isBulkSelectionApplied && rows ? filteredRows.length : (getSelectedIdentifiersCount?.() ?? 0)
119127

120128
const visibleRows = useMemo(() => {
121129
const normalizedFilteredRows = filteredRows ?? []
@@ -128,9 +136,14 @@ const InternalTable = ({
128136
return paginatedRows
129137
}, [paginationVariant, offset, pageSize, filteredRows])
130138

139+
const showPagination =
140+
paginationVariant === PaginationEnum.PAGINATED && filteredRows?.length > DEFAULT_BASE_PAGE_SIZE
141+
131142
const { activeRowIndex, setActiveRowIndex } = useTableWithKeyboardShortcuts(
132143
{ bulkSelectionConfig, bulkSelectionReturnValue, handleToggleBulkSelectionOnRow },
133144
visibleRows,
145+
showPagination,
146+
bulkSelectionButtonRef,
134147
)
135148

136149
useEffectAfterMount(() => {
@@ -161,8 +174,17 @@ const InternalTable = ({
161174
activeRowRef.current?.focus()
162175
}, [activeRowIndex])
163176

164-
const showPagination =
165-
paginationVariant === PaginationEnum.PAGINATED && filteredRows?.length > DEFAULT_BASE_PAGE_SIZE
177+
const onBulkOperationModalClose = () => {
178+
setBulkActionState(null)
179+
}
180+
181+
const getBulkSelections = () => {
182+
if (isBulkSelectionApplied && rows) {
183+
return filteredRows
184+
}
185+
186+
return Object.values(bulkSelectionState)
187+
}
166188

167189
const renderRows = () => {
168190
if (loading) {
@@ -308,7 +330,13 @@ const InternalTable = ({
308330
const isResizable = !!size?.range
309331

310332
if (field === BULK_ACTION_GUTTER_LABEL) {
311-
return <BulkSelection key={field} showPagination={showPagination} />
333+
return (
334+
<BulkSelection
335+
ref={bulkSelectionButtonRef}
336+
key={field}
337+
showPagination={showPagination}
338+
/>
339+
)
312340
}
313341

314342
return (
@@ -344,6 +372,8 @@ const InternalTable = ({
344372
handleClearBulkSelection={handleClearBulkSelection}
345373
parentRef={parentRef}
346374
BulkActionsComponent={BulkActionsComponent}
375+
setBulkActionState={setBulkActionState}
376+
bulkActionsData={bulkActionsData}
347377
/>
348378
)}
349379
</div>
@@ -359,7 +389,15 @@ const InternalTable = ({
359389
/>
360390
)}
361391

362-
{children}
392+
{bulkActionState && (
393+
<BulkOperationModal
394+
action={bulkActionState}
395+
onClose={onBulkOperationModalClose}
396+
bulkOperationModalData={bulkOperationModalData}
397+
isBulkSelectionApplied={isBulkSelectionApplied}
398+
selections={getBulkSelections()}
399+
/>
400+
)}
363401
</div>
364402
)
365403
}

src/Shared/Components/Table/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export { default as Table } from './Table.component'
22
export type {
3+
BulkActionsComponentProps as TableBulkActionsComponentProps,
4+
BulkOperationModalProps as TableBulkOperationModalProps,
35
CellComponentProps as TableCellComponentProps,
46
Column as TableColumnType,
57
TableProps,

0 commit comments

Comments
 (0)