Skip to content

Commit 57724d4

Browse files
authored
Show duration on compact history group (#912)
1 parent cb4439d commit 57724d4

File tree

7 files changed

+107
-49
lines changed

7 files changed

+107
-49
lines changed

src/views/workflow-history/workflow-history-compact-event-card/__tests__/workflow-history-compact-event-card.test.tsx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React from 'react';
22

33
import { render, screen, userEvent } from '@/test-utils/rtl';
44

5+
import { startWorkflowExecutionEvent } from '../../__fixtures__/workflow-history-single-events';
56
import type WorkflowHistoryEventStatusBadge from '../../workflow-history-event-status-badge/workflow-history-event-status-badge';
7+
import WorkflowHistoryEventsDurationBadge from '../../workflow-history-events-duration-badge/workflow-history-events-duration-badge';
68
import WorkflowHistoryCompactEventCard from '../workflow-history-compact-event-card';
79
import { type Props } from '../workflow-history-compact-event-card.types';
810

@@ -11,7 +13,16 @@ jest.mock<typeof WorkflowHistoryEventStatusBadge>(
1113
() => jest.fn((props) => <div>{props.status}</div>)
1214
);
1315

16+
jest.mock<typeof WorkflowHistoryEventsDurationBadge>(
17+
'../../workflow-history-events-duration-badge/workflow-history-events-duration-badge',
18+
() => jest.fn(() => <div>Duration Badge</div>)
19+
);
20+
1421
describe('WorkflowHistoryCompactEventCard', () => {
22+
beforeEach(() => {
23+
jest.clearAllMocks();
24+
});
25+
1526
it('renders label correctly', () => {
1627
setup({
1728
label: 'test label',
@@ -59,6 +70,26 @@ describe('WorkflowHistoryCompactEventCard', () => {
5970

6071
expect(mockOnClick).toHaveBeenCalled();
6172
});
73+
74+
it('should render duration badge passing showOngoingOnly as true when timeMs is provided', () => {
75+
setup({
76+
timeMs: 1726652232190.7927,
77+
});
78+
expect(WorkflowHistoryEventsDurationBadge).toHaveBeenCalledWith(
79+
expect.objectContaining({
80+
showOngoingOnly: true,
81+
}),
82+
{}
83+
);
84+
});
85+
86+
it('does not render duration badge when timeMs is not provided', () => {
87+
setup({
88+
timeMs: null,
89+
});
90+
91+
expect(screen.queryByText('Duration Badge')).not.toBeInTheDocument();
92+
});
6293
});
6394

6495
function setup(props: Partial<Props>) {
@@ -70,8 +101,14 @@ function setup(props: Partial<Props>) {
70101
statusReady
71102
status="COMPLETED"
72103
label="test label"
73-
secondaryLabel="test secondaryLabel"
74104
onClick={mockOnClick}
105+
timeMs={null}
106+
closeTimeMs={null}
107+
events={[startWorkflowExecutionEvent]}
108+
workflowCloseTimeMs={null}
109+
workflowCloseStatus={null}
110+
workflowIsArchived={false}
111+
hasMissingEvents={false}
75112
{...props}
76113
/>
77114
),

src/views/workflow-history/workflow-history-compact-event-card/workflow-history-compact-event-card.styles.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export const overrides = {
4242
color: $theme.colors.contentSecondary,
4343
...$theme.typography.LabelXSmall,
4444
whiteSpace: 'nowrap',
45+
marginLeft: $theme.sizing.scale100,
4546
}),
4647
},
4748
} satisfies BadgeOverrides,
@@ -60,9 +61,8 @@ const cssStylesObj = {
6061
...$theme.typography.LabelSmall,
6162
color: $theme.colors.contentPrimary,
6263
}),
63-
secondaryLabel: ($theme: Theme) => ({
64-
...$theme.typography.LabelXSmall,
65-
color: '#868686',
64+
durationContainer: ($theme: Theme) => ({
65+
marginLeft: $theme.sizing.scale100,
6666
}),
6767
} satisfies StyletronCSSObject;
6868

src/views/workflow-history/workflow-history-compact-event-card/workflow-history-compact-event-card.tsx

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ALIGNMENT, TILE_KIND, Tile } from 'baseui/tile';
88
import useStyletronClasses from '@/hooks/use-styletron-classes';
99

1010
import WorkflowHistoryEventStatusBadge from '../workflow-history-event-status-badge/workflow-history-event-status-badge';
11+
import WorkflowHistoryEventsDurationBadge from '../workflow-history-events-duration-badge/workflow-history-events-duration-badge';
1112

1213
import {
1314
cssStyles,
@@ -19,10 +20,17 @@ export default function WorkflowHistoryCompactEventCard({
1920
status,
2021
statusReady,
2122
label,
22-
badges,
2323
showLabelPlaceholder,
2424
selected,
2525
disabled,
26+
timeMs,
27+
badges,
28+
closeTimeMs,
29+
events,
30+
hasMissingEvents,
31+
workflowCloseTimeMs,
32+
workflowCloseStatus,
33+
workflowIsArchived,
2634
onClick,
2735
}: Props) {
2836
const { cls, theme } = useStyletronClasses(cssStyles);
@@ -49,17 +57,28 @@ export default function WorkflowHistoryCompactEventCard({
4957
{label}
5058
{hasBadges &&
5159
badges.map((badge) => (
52-
<>
53-
{' '}
54-
<Badge
55-
key={badge.content}
56-
overrides={overrides.badge}
57-
content={badge.content}
58-
shape="rectangle"
59-
color="primary"
60-
/>
61-
</>
60+
<Badge
61+
key={badge.content}
62+
overrides={overrides.badge}
63+
content={badge.content}
64+
shape="rectangle"
65+
color="primary"
66+
/>
6267
))}
68+
{timeMs && (
69+
<span className={cls.durationContainer}>
70+
<WorkflowHistoryEventsDurationBadge
71+
startTime={timeMs}
72+
closeTime={closeTimeMs}
73+
eventsCount={events.length}
74+
hasMissingEvents={hasMissingEvents}
75+
workflowCloseTime={workflowCloseTimeMs}
76+
workflowIsArchived={workflowIsArchived}
77+
workflowCloseStatus={workflowCloseStatus}
78+
showOngoingOnly={true}
79+
/>
80+
</span>
81+
)}
6382
</div>
6483
)}
6584
</div>
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
import { type TileProps } from 'baseui/tile';
22

3-
import { type WorkflowEventStatus } from '../workflow-history-event-status-badge/workflow-history-event-status-badge.types';
4-
import { type HistoryGroupBadge } from '../workflow-history.types';
3+
import { type WorkflowExecutionCloseStatus } from '@/__generated__/proto-ts/uber/cadence/api/v1/WorkflowExecutionCloseStatus';
54

6-
export type Props = {
7-
status: WorkflowEventStatus;
5+
import { type HistoryEventsGroup } from '../workflow-history.types';
6+
7+
export type Props = Pick<
8+
HistoryEventsGroup,
9+
| 'events'
10+
| 'label'
11+
| 'hasMissingEvents'
12+
| 'status'
13+
| 'badges'
14+
| 'resetToDecisionEventId'
15+
| 'timeMs'
16+
| 'closeTimeMs'
17+
> & {
818
statusReady: boolean;
9-
label: string;
10-
secondaryLabel: string;
1119
showLabelPlaceholder?: boolean;
12-
badges?: HistoryGroupBadge[];
1320
onClick: TileProps['onClick'];
1421
selected?: boolean;
1522
disabled?: boolean;
23+
workflowIsArchived: boolean;
24+
workflowCloseTimeMs?: number | null;
25+
workflowCloseStatus?: WorkflowExecutionCloseStatus | null;
1626
};

src/views/workflow-history/workflow-history-events-duration-badge/workflow-history-events-duration-badge.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,32 @@ export default function WorkflowHistoryEventsDurationBadge({
1313
eventsCount,
1414
hasMissingEvents,
1515
workflowCloseTime,
16+
showOngoingOnly,
1617
}: Props) {
1718
const endTime = closeTime || workflowCloseTime;
1819
const workflowEnded =
1920
workflowIsArchived ||
2021
workflowCloseStatus !== 'WORKFLOW_EXECUTION_CLOSE_STATUS_INVALID';
2122
const singleEvent = eventsCount === 1 && !hasMissingEvents;
2223
const noDuration = singleEvent || (workflowEnded && !endTime);
24+
const hideDuration = (showOngoingOnly && endTime) || noDuration;
2325

2426
const [duration, setDuration] = useState<string>(() =>
2527
getFormattedEventsDuration(startTime, endTime)
2628
);
2729

2830
useEffect(() => {
2931
setDuration(getFormattedEventsDuration(startTime, endTime));
30-
if (!endTime && !noDuration) {
32+
if (!endTime && !hideDuration) {
3133
const interval = setInterval(() => {
3234
setDuration(getFormattedEventsDuration(startTime, endTime));
3335
}, 1000);
3436

3537
return () => clearInterval(interval);
3638
}
37-
}, [startTime, endTime, noDuration]);
39+
}, [startTime, endTime, hideDuration]);
3840

39-
if (noDuration) {
41+
if (hideDuration) {
4042
return null;
4143
}
4244

src/views/workflow-history/workflow-history-events-duration-badge/workflow-history-events-duration-badge.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export type Props = {
88
eventsCount: number;
99
hasMissingEvents: boolean;
1010
workflowCloseTime: Date | string | number | null | undefined;
11+
showOngoingOnly?: boolean;
1112
};

src/views/workflow-history/workflow-history.tsx

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -342,39 +342,28 @@ export default function WorkflowHistory({ params }: Props) {
342342
: {
343343
initialTopMostItemIndex: initialEventGroupIndex,
344344
})}
345-
itemContent={(
346-
index,
347-
[
348-
groupId,
349-
{
350-
label,
351-
status,
352-
timeLabel,
353-
badges,
354-
events,
355-
hasMissingEvents,
356-
},
357-
]
358-
) => (
345+
itemContent={(index, [groupId, group]) => (
359346
<div role="listitem" className={cls.compactCardContainer}>
360347
<WorkflowHistoryCompactEventCard
361348
key={groupId}
362-
status={status}
349+
{...group}
363350
statusReady={
364-
!hasMissingEvents || reachedAvailableHistoryEnd
351+
!group.hasMissingEvents || reachedAvailableHistoryEnd
352+
}
353+
workflowCloseStatus={workflowExecutionInfo?.closeStatus}
354+
workflowIsArchived={
355+
workflowExecutionInfo?.isArchived || false
365356
}
366-
label={label}
367-
secondaryLabel={timeLabel}
368-
showLabelPlaceholder={!label}
369-
badges={badges}
370-
selected={events.some(
357+
workflowCloseTimeMs={wokflowCloseTimeMs}
358+
showLabelPlaceholder={!group.label}
359+
selected={group.events.some(
371360
(e) => e.eventId === queryParams.historySelectedEventId
372361
)}
373-
disabled={!Boolean(events[0].eventId)}
362+
disabled={!Boolean(group.events[0].eventId)}
374363
onClick={() => {
375-
if (events[0].eventId)
364+
if (group.events[0].eventId)
376365
setQueryParams({
377-
historySelectedEventId: events[0].eventId,
366+
historySelectedEventId: group.events[0].eventId,
378367
});
379368
timelineSectionListRef.current?.scrollToIndex({
380369
index,

0 commit comments

Comments
 (0)