Skip to content

Commit 992c152

Browse files
feat: Add grouped table with raw JSON of events (#1093)
* Add fetching and grouping logic for Workflow History V2 page & components, based on the existing fetching logic for V1 * Add grouped events table, with JSON placeholder for each event group row Signed-off-by: Adhitya Mamallan <[email protected]>
1 parent 0f3132c commit 992c152

File tree

8 files changed

+703
-94
lines changed

8 files changed

+703
-94
lines changed

src/views/workflow-history-v2/__tests__/workflow-history-v2.test.tsx

Lines changed: 301 additions & 80 deletions
Large diffs are not rendered by default.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const WORKFLOW_HISTORY_FETCH_EVENTS_THROTTLE_MS_CONFIG = 2000;
2+
3+
export default WORKFLOW_HISTORY_FETCH_EVENTS_THROTTLE_MS_CONFIG;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const WORKFLOW_HISTORY_SET_RANGE_THROTTLE_MS_CONFIG = 700;
2+
3+
export default WORKFLOW_HISTORY_SET_RANGE_THROTTLE_MS_CONFIG;
Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
import React from 'react';
22

3-
import { render, screen } from '@/test-utils/rtl';
3+
import { VirtuosoMockContext } from 'react-virtuoso';
4+
5+
import { render, screen, userEvent } from '@/test-utils/rtl';
6+
7+
import { RequestError } from '@/utils/request/request-error';
8+
import { mockActivityEventGroup } from '@/views/workflow-history/__fixtures__/workflow-history-event-groups';
9+
import { type HistoryEventsGroup } from '@/views/workflow-history/workflow-history.types';
410

511
import WorkflowHistoryGroupedTable from '../workflow-history-grouped-table';
612

13+
jest.mock(
14+
'@/views/workflow-history/workflow-history-timeline-load-more/workflow-history-timeline-load-more',
15+
() =>
16+
jest.fn(({ error, hasNextPage, isFetchingNextPage, fetchNextPage }) => (
17+
<div data-testid="timeline-load-more">
18+
{error && <div data-testid="load-more-error">Error loading more</div>}
19+
{hasNextPage && <div data-testid="has-next-page">Has more</div>}
20+
{isFetchingNextPage && <div data-testid="is-fetching">Fetching...</div>}
21+
<button onClick={fetchNextPage} data-testid="fetch-more-button">
22+
Fetch More
23+
</button>
24+
</div>
25+
))
26+
);
27+
728
describe(WorkflowHistoryGroupedTable.name, () => {
829
it('should render all column headers in correct order', () => {
930
setup();
1031

11-
expect(screen.getByText('ID')).toBeInTheDocument();
1232
expect(screen.getByText('Event group')).toBeInTheDocument();
1333
expect(screen.getByText('Status')).toBeInTheDocument();
1434
expect(screen.getByText('Time')).toBeInTheDocument();
@@ -19,14 +39,98 @@ describe(WorkflowHistoryGroupedTable.name, () => {
1939
it('should apply grid layout to table header', () => {
2040
setup();
2141

22-
const header = screen.getByText('ID').parentElement;
42+
const header = screen.getByText('Event group').parentElement;
2343
expect(header).toHaveStyle({
2444
display: 'grid',
2545
gridTemplateColumns: '0.3fr 2fr 1fr 1.2fr 1fr 3fr minmax(0, 70px)',
2646
});
2747
});
48+
49+
it('should render event groups data', () => {
50+
const mockEventGroups: Array<[string, HistoryEventsGroup]> = [
51+
['group-1', mockActivityEventGroup],
52+
];
53+
setup({ eventGroupsById: mockEventGroups });
54+
55+
expect(
56+
screen.getByText(JSON.stringify(mockActivityEventGroup))
57+
).toBeInTheDocument();
58+
});
59+
60+
it('should render timeline load more component with correct props', () => {
61+
const mockFetchMoreEvents = jest.fn();
62+
63+
setup({
64+
error: new RequestError('Test error', '/mock-history-url', 500),
65+
hasMoreEvents: true,
66+
isFetchingMoreEvents: false,
67+
fetchMoreEvents: mockFetchMoreEvents,
68+
});
69+
70+
expect(screen.getByTestId('timeline-load-more')).toBeInTheDocument();
71+
expect(screen.getByTestId('has-next-page')).toBeInTheDocument();
72+
});
73+
74+
it('should show error state in load more component', () => {
75+
setup({ error: new RequestError('Test error', '/mock-history-url', 500) });
76+
77+
expect(screen.getByTestId('load-more-error')).toBeInTheDocument();
78+
});
79+
80+
it('should show fetching state in load more component', () => {
81+
setup({ isFetchingMoreEvents: true });
82+
83+
expect(screen.getByTestId('is-fetching')).toBeInTheDocument();
84+
});
2885
});
2986

30-
function setup() {
31-
return render(<WorkflowHistoryGroupedTable />);
87+
function setup({
88+
eventGroupsById = [],
89+
error = null,
90+
hasMoreEvents = false,
91+
isFetchingMoreEvents = false,
92+
fetchMoreEvents = jest.fn(),
93+
setVisibleRange = jest.fn(),
94+
initialStartIndex,
95+
}: {
96+
eventGroupsById?: Array<[string, HistoryEventsGroup]>;
97+
error?: RequestError | null;
98+
hasMoreEvents?: boolean;
99+
isFetchingMoreEvents?: boolean;
100+
fetchMoreEvents?: () => void;
101+
setVisibleRange?: ({
102+
startIndex,
103+
endIndex,
104+
}: {
105+
startIndex: number;
106+
endIndex: number;
107+
}) => void;
108+
initialStartIndex?: number;
109+
} = {}) {
110+
const virtuosoRef = { current: null };
111+
const user = userEvent.setup();
112+
113+
render(
114+
<VirtuosoMockContext.Provider
115+
value={{ viewportHeight: 1000, itemHeight: 160 }}
116+
>
117+
<WorkflowHistoryGroupedTable
118+
eventGroupsById={eventGroupsById}
119+
virtuosoRef={virtuosoRef}
120+
initialStartIndex={initialStartIndex}
121+
setVisibleRange={setVisibleRange}
122+
error={error}
123+
hasMoreEvents={hasMoreEvents}
124+
fetchMoreEvents={fetchMoreEvents}
125+
isFetchingMoreEvents={isFetchingMoreEvents}
126+
/>
127+
</VirtuosoMockContext.Provider>
128+
);
129+
130+
return {
131+
user,
132+
virtuosoRef,
133+
mockFetchMoreEvents: fetchMoreEvents,
134+
mockSetVisibleRange: setVisibleRange,
135+
};
32136
}
Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,58 @@
1+
import { Virtuoso } from 'react-virtuoso';
2+
3+
import WorkflowHistoryTimelineLoadMore from '@/views/workflow-history/workflow-history-timeline-load-more/workflow-history-timeline-load-more';
4+
15
import { styled } from './workflow-history-grouped-table.styles';
6+
import { type Props } from './workflow-history-grouped-table.types';
27

3-
/**
4-
* To be used in History v2
5-
*/
6-
export default function WorkflowHistoryGroupedTable() {
8+
export default function WorkflowHistoryGroupedTable({
9+
eventGroupsById,
10+
virtuosoRef,
11+
initialStartIndex,
12+
setVisibleRange,
13+
error,
14+
hasMoreEvents,
15+
fetchMoreEvents,
16+
isFetchingMoreEvents,
17+
}: Props) {
718
return (
819
<>
920
<styled.TableHeader>
10-
<div>ID</div>
21+
<div />
1122
<div>Event group</div>
1223
<div>Status</div>
1324
<div>Time</div>
1425
<div>Duration</div>
1526
<div>Details</div>
1627
</styled.TableHeader>
17-
{/* TODO @adhityamamallan: Add table body with Virtuoso with new design*/}
28+
<Virtuoso
29+
useWindowScroll
30+
data={eventGroupsById}
31+
ref={virtuosoRef}
32+
defaultItemHeight={160}
33+
rangeChanged={setVisibleRange}
34+
{...(initialStartIndex === undefined
35+
? {}
36+
: {
37+
initialTopMostItemIndex: {
38+
index: initialStartIndex,
39+
align: 'start',
40+
behavior: 'auto',
41+
},
42+
})}
43+
// TODO: update this with the actual implementation for groupedEntry
44+
itemContent={(_, [__, group]) => <div>{JSON.stringify(group)}</div>}
45+
components={{
46+
Footer: () => (
47+
<WorkflowHistoryTimelineLoadMore
48+
error={error}
49+
fetchNextPage={fetchMoreEvents}
50+
hasNextPage={hasMoreEvents}
51+
isFetchingNextPage={isFetchingMoreEvents}
52+
/>
53+
),
54+
}}
55+
/>
1856
</>
1957
);
2058
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { type RefObject } from 'react';
2+
3+
import { type VirtuosoHandle } from 'react-virtuoso';
4+
5+
import { type RequestError } from '@/utils/request/request-error';
6+
import { type HistoryEventsGroup } from '@/views/workflow-history/workflow-history.types';
7+
8+
export type Props = {
9+
eventGroupsById: Array<[string, HistoryEventsGroup]>;
10+
virtuosoRef: RefObject<VirtuosoHandle>;
11+
initialStartIndex?: number;
12+
setVisibleRange: ({
13+
startIndex,
14+
endIndex,
15+
}: {
16+
startIndex: number;
17+
endIndex: number;
18+
}) => void;
19+
// Props to fetch more history
20+
error: RequestError | null;
21+
hasMoreEvents: boolean;
22+
fetchMoreEvents: () => void;
23+
isFetchingMoreEvents: boolean;
24+
};

0 commit comments

Comments
 (0)