Skip to content

Commit 9a9a948

Browse files
committed
Merge branch 'feat/app-list-table' of github.com:devtron-labs/devtron-fe-common-lib into feat/app-list-table
2 parents ae57aab + 4743e56 commit 9a9a948

File tree

7 files changed

+117
-23
lines changed

7 files changed

+117
-23
lines changed

src/Shared/Components/CICDHistory/ConflictedResourcesTable.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import './ConflictedResourcesTable.scss'
1010
const Wrapper = ({ children }: TableViewWrapperProps<unknown, FiltersTypeEnum.STATE>) => (
1111
<div className="dc__overflow-hidden flexbox-col flex-grow-1">{children}</div>
1212
)
13-
const filter = () => true
1413

1514
const ConflictedResourcesTable = ({ resourceConflictDetails }: ConflictedResourcesTableProps) => {
1615
const rows: RowsType<ResourceConflictItemType> = useMemo(
@@ -42,7 +41,7 @@ const ConflictedResourcesTable = ({ resourceConflictDetails }: ConflictedResourc
4241
}}
4342
filtersVariant={FiltersTypeEnum.STATE}
4443
ViewWrapper={Wrapper}
45-
filter={filter}
44+
filter={null}
4645
/>
4746
)
4847
}

src/Shared/Components/Table/InternalTable.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const InternalTable = <
5858
clearFilters: userGivenUrlClearFilters,
5959
rowStartIconConfig,
6060
onRowClick,
61+
areFiltersApplied: userProvidedAreFiltersApplied,
6162
}: InternalTableProps<RowData, FilterVariant, AdditionalProps>) => {
6263
const {
6364
sortBy,
@@ -126,6 +127,7 @@ const InternalTable = <
126127
rows,
127128
filter,
128129
filterData,
130+
additionalProps,
129131
visibleColumns.find(({ field }) => field === sortBy)?.comparator,
130132
)
131133

@@ -140,10 +142,14 @@ const InternalTable = <
140142
// useAsync hook for 'rows' scenario
141143
const [_areRowsLoading, rowsResult, rowsError, reloadRows] = useAsync(
142144
handleFiltering,
143-
[searchKey, sortBy, sortOrder, rows, JSON.stringify(otherFilters), visibleColumns],
145+
[searchKey, filter, sortBy, sortOrder, rows, JSON.stringify(otherFilters), visibleColumns],
144146
!!rows,
145147
)
146148

149+
// NOTE: passing getRows to queryKey won't trigger a refetch
150+
// since it is a function
151+
const lastUpdatedGetRowsInstance = useMemo(() => new Date().toISOString(), [getRows])
152+
147153
// useAsync hook for 'getRows' scenario
148154
const {
149155
isFetching: _areGetRowsLoading,
@@ -160,8 +166,7 @@ const InternalTable = <
160166
searchKey,
161167
sortBy,
162168
sortOrder,
163-
// !TODO: functions in queryKey cannot trigger refetch
164-
// getRows,
169+
lastUpdatedGetRowsInstance,
165170
offset,
166171
pageSize,
167172
JSON.stringify(otherFilters),
@@ -191,7 +196,8 @@ const InternalTable = <
191196
}
192197

193198
if (!areFilteredRowsLoading && !filteredRows?.length && !loading) {
194-
return filtersVariant !== FiltersTypeEnum.NONE && areFiltersApplied ? (
199+
return filtersVariant !== FiltersTypeEnum.NONE &&
200+
(userProvidedAreFiltersApplied !== undefined ? userProvidedAreFiltersApplied : areFiltersApplied) ? (
195201
<GenericFilterEmptyState
196202
{...emptyStateConfig.noRowsForFilterConfig}
197203
handleClearFilters={userGivenUrlClearFilters ?? clearFilters}

src/Shared/Components/Table/TableContent.tsx

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
FiltersTypeEnum,
3636
PaginationEnum,
3737
RowType,
38+
SignalEnum,
3839
SignalsType,
3940
TableContentProps,
4041
} from './types'
@@ -152,9 +153,10 @@ const TableContent = <
152153
? `${initialGridTemplateColumns} ${typeof rowOnHoverComponentWidth === 'number' ? `minmax(${rowOnHoverComponentWidth}px, 1fr)` : rowOnHoverComponentWidth}`
153154
: initialGridTemplateColumns
154155

155-
const gridTemplateColumns = isAnyRowExpandable
156-
? `${ACTION_GUTTER_SIZE}px ${gridTemplateColumnsWithoutExpandButton}`
157-
: gridTemplateColumnsWithoutExpandButton
156+
const gridTemplateColumns =
157+
isAnyRowExpandable || rowStartIconConfig
158+
? `${ACTION_GUTTER_SIZE}px ${gridTemplateColumnsWithoutExpandButton}`
159+
: gridTemplateColumnsWithoutExpandButton
158160

159161
useEffect(() => {
160162
const scrollEventHandler = () => {
@@ -188,7 +190,7 @@ const TableContent = <
188190

189191
useEffectAfterMount(() => {
190192
setActiveRowIndex(0)
191-
}, [offset, visibleRows])
193+
}, [offset])
192194

193195
useEffect(() => {
194196
setIdentifiers?.(
@@ -203,6 +205,54 @@ const TableContent = <
203205
handleSorting(newSortBy)
204206
}
205207

208+
useEffect(() => {
209+
if (!isAnyRowExpandable) {
210+
return () => {}
211+
}
212+
213+
const getExpandCollapseRowHandler =
214+
(state: boolean) =>
215+
({ detail: { activeRowData } }) => {
216+
if ((activeRowData as RowType<RowData>).expandableRows) {
217+
setExpandState((prev) => ({
218+
...prev,
219+
[activeRowData.id]: state,
220+
}))
221+
}
222+
}
223+
224+
const handleExpandRow = getExpandCollapseRowHandler(true)
225+
const handleCollapseRow = getExpandCollapseRowHandler(false)
226+
227+
const signals = EVENT_TARGET as SignalsType
228+
229+
signals.addEventListener(SignalEnum.EXPAND_ROW, handleExpandRow)
230+
signals.addEventListener(SignalEnum.COLLAPSE_ROW, handleCollapseRow)
231+
232+
return () => {
233+
signals.removeEventListener(SignalEnum.EXPAND_ROW, handleExpandRow)
234+
signals.removeEventListener(SignalEnum.COLLAPSE_ROW, handleCollapseRow)
235+
}
236+
}, [isAnyRowExpandable])
237+
238+
useEffect(() => {
239+
if (!onRowClick) {
240+
return () => {}
241+
}
242+
243+
const handleEnterPress = ({ detail: { activeRowData } }) => {
244+
onRowClick(activeRowData, activeRowData.id.startsWith('expanded-row-' satisfies ExpandedRowPrefixType))
245+
}
246+
247+
const signals = EVENT_TARGET as SignalsType
248+
249+
signals.addEventListener(SignalEnum.ENTER_PRESSED, handleEnterPress)
250+
251+
return () => {
252+
signals.removeEventListener(SignalEnum.ENTER_PRESSED, handleEnterPress)
253+
}
254+
}, [onRowClick])
255+
206256
const toggleExpandAll = (e: MouseEvent<HTMLButtonElement>) => {
207257
e.stopPropagation()
208258

@@ -247,22 +297,24 @@ const TableContent = <
247297
return Object.values(bulkSelectionState)
248298
}
249299

300+
const showIconOrExpandActionGutter = isBulkSelectionConfigured || !!rowStartIconConfig || isAnyRowExpandable
301+
250302
const renderRows = () => {
251-
if (loading) {
303+
if (loading && !visibleColumns.length) {
252304
return SHIMMER_DUMMY_ARRAY.map((shimmerRowLabel) => (
253305
<div
254306
key={shimmerRowLabel}
255-
className={`px-20 flexbox py-12 dc__gap-16 ${showSeparatorBetweenRows ? 'border__secondary--bottom' : ''}`}
307+
className={`px-20 flex left py-12 dc__gap-16 ${showSeparatorBetweenRows ? 'border__secondary--bottom' : ''}`}
256308
>
257-
{isBulkSelectionConfigured ? <div className="shimmer w-20" /> : null}
309+
{showIconOrExpandActionGutter ? <div className="shimmer w-20" /> : null}
258310
{SHIMMER_DUMMY_ARRAY.map((shimmerCellLabel) => (
259311
<div key={shimmerCellLabel} className="shimmer w-200" />
260312
))}
261313
</div>
262314
))
263315
}
264316

265-
if (areFilteredRowsLoading) {
317+
if (areFilteredRowsLoading || (loading && visibleColumns.length)) {
266318
return SHIMMER_DUMMY_ARRAY.map((shimmerRowLabel) => (
267319
<div
268320
key={shimmerRowLabel}
@@ -271,6 +323,11 @@ const TableContent = <
271323
gridTemplateColumns,
272324
}}
273325
>
326+
{showIconOrExpandActionGutter ? (
327+
<div className="py-12 flex" aria-label="Loading...">
328+
<div className="shimmer h-16 w-20" />
329+
</div>
330+
) : null}
274331
{visibleColumns.map(({ label }) => (
275332
<div key={label} className="py-12 flex" aria-label="Loading...">
276333
<div className="shimmer h-16 w-100" />
@@ -364,7 +421,7 @@ const TableContent = <
364421
ariaLabel="Expand/Collapse row"
365422
showAriaLabelInTippy={false}
366423
variant={ButtonVariantType.borderLess}
367-
size={ComponentSizeType.xs}
424+
size={ComponentSizeType.xxs}
368425
style={ButtonStyleType.neutral}
369426
onClick={toggleExpandRow}
370427
/>
@@ -467,9 +524,9 @@ const TableContent = <
467524
ref={headerRef}
468525
className="bg__primary dc__min-width-fit-content px-20 border__secondary--bottom dc__position-sticky dc__zi-2 dc__top-0 generic-table__header"
469526
>
470-
{loading ? (
527+
{loading && !visibleColumns.length ? (
471528
<div className="flexbox py-12 dc__gap-16">
472-
{isBulkSelectionConfigured ? <div className="shimmer w-20" /> : null}
529+
{showIconOrExpandActionGutter ? <div className="shimmer w-20" /> : null}
473530
{SHIMMER_DUMMY_ARRAY.map((label) => (
474531
<div key={label} className="shimmer w-200" />
475532
))}
@@ -498,13 +555,15 @@ const TableContent = <
498555
ariaLabel="Expand/Collapse all rows"
499556
showAriaLabelInTippy={false}
500557
variant={ButtonVariantType.borderLess}
501-
size={ComponentSizeType.xs}
558+
size={ComponentSizeType.xxs}
502559
style={ButtonStyleType.neutral}
503560
onClick={toggleExpandAll}
504561
/>
505562
</div>
506563
) : null}
507564

565+
{!isAnyRowExpandable && rowStartIconConfig && <div />}
566+
508567
{visibleColumns.map(
509568
(
510569
{

src/Shared/Components/Table/styles.scss

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
&.expand-row-btn::before,
4545
&.row-start-icon::before,
46-
&.expanded-tree-libe::before {
46+
&.expanded-tree-line::before {
4747
left: -24px;
4848
width: 24px;
4949
}
@@ -76,6 +76,10 @@
7676
outline: none;
7777
}
7878

79+
&--expanded-row:has(+ .generic-table__row--expanded-row) {
80+
border-bottom: 0px;
81+
}
82+
7983
&:hover,
8084
&:hover > *,
8185
&--active,

src/Shared/Components/Table/types.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import { useBulkSelection, UseBulkSelectionProps } from '../BulkSelection'
3333
export interface UseFiltersReturnType extends UseStateFiltersReturnType<string> {}
3434

3535
export enum SignalEnum {
36+
COLLAPSE_ROW = 'collapse-row',
37+
EXPAND_ROW = 'expand-row',
3638
ENTER_PRESSED = 'enter-pressed',
3739
DELETE_PRESSED = 'delete-pressed',
3840
ESCAPE_PRESSED = 'escape-pressed',
@@ -237,7 +239,11 @@ export type ViewWrapperProps<
237239
: {})
238240
>
239241

240-
type FilterConfig<FilterVariant extends FiltersTypeEnum, RowData extends unknown> = {
242+
type FilterConfig<
243+
FilterVariant extends FiltersTypeEnum,
244+
RowData extends unknown,
245+
AdditionalProps extends Record<string, any>,
246+
> = {
241247
filtersVariant: FilterVariant
242248
/**
243249
* Props for useUrlFilters/useStateFilters hooks
@@ -251,12 +257,14 @@ type FilterConfig<FilterVariant extends FiltersTypeEnum, RowData extends unknown
251257
*/
252258
filter: FilterVariant extends FiltersTypeEnum.NONE
253259
? null
254-
: (row: RowType<RowData>, filterData: UseFiltersReturnType) => boolean
260+
: (row: RowType<RowData>, filterData: UseFiltersReturnType, additionalProps: AdditionalProps) => boolean
255261
clearFilters?: FilterVariant extends FiltersTypeEnum.URL
256262
? () => void
257263
: FilterVariant extends FiltersTypeEnum.STATE
258264
? never
259265
: never
266+
267+
areFiltersApplied?: FilterVariant extends FiltersTypeEnum.NONE ? never : boolean
260268
}
261269

262270
export type InternalTableProps<
@@ -360,7 +368,7 @@ export type InternalTableProps<
360368
pageSizeOptions?: never
361369
}
362370
) &
363-
FilterConfig<FilterVariant, RowData>
371+
FilterConfig<FilterVariant, RowData, AdditionalProps>
364372

365373
export type UseResizableTableConfigWrapperProps<
366374
RowData extends unknown,
@@ -415,6 +423,7 @@ export type TableProps<
415423
| 'clearFilters'
416424
| 'rowStartIconConfig'
417425
| 'onRowClick'
426+
| 'areFiltersApplied'
418427
>
419428

420429
export type BulkActionStateType = string | null

src/Shared/Components/Table/useTableWithKeyboardShortcuts.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@ const useTableWithKeyboardShortcuts = <
101101
)
102102

103103
useEffect(() => {
104+
registerShortcut({
105+
keys: ['ArrowLeft'],
106+
callback: () => {
107+
dispatchEvent(SignalEnum.COLLAPSE_ROW)
108+
},
109+
})
110+
111+
registerShortcut({
112+
keys: ['ArrowRight'],
113+
callback: () => {
114+
dispatchEvent(SignalEnum.EXPAND_ROW)
115+
},
116+
})
117+
104118
registerShortcut({
105119
keys: ['ArrowDown'],
106120
callback: () => {
@@ -142,6 +156,8 @@ const useTableWithKeyboardShortcuts = <
142156
unregisterShortcut(['Enter'])
143157
unregisterShortcut(['Backspace'])
144158
unregisterShortcut(['.'])
159+
unregisterShortcut(['ArrowLeft'])
160+
unregisterShortcut(['ArrowRight'])
145161
}
146162
}, [getMoveFocusToNextRowHandler, getMoveFocusToPreviousRowHandler, dispatchEvent])
147163

src/Shared/Components/Table/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ export const searchAndSortRows = <
4242
rows: TableProps<RowData, FilterVariant, AdditionalProps>['rows'],
4343
filter: TableProps<RowData, FilterVariant, AdditionalProps>['filter'],
4444
filterData: UseFiltersReturnType,
45+
additionalProps: AdditionalProps,
4546
comparator?: Column<RowData, FilterVariant, AdditionalProps>['comparator'],
4647
): Awaited<ReturnType<TableProps<RowData>['getRows']>> => {
4748
const { sortBy, sortOrder } = filterData ?? {}
4849

49-
const filteredRows = filter ? rows.filter((row) => filter(row, filterData)) : rows
50+
const filteredRows = filter ? rows.filter((row) => filter(row, filterData, additionalProps)) : rows
5051

5152
return {
5253
rows:

0 commit comments

Comments
 (0)