diff --git a/src/views/workflow-history-v2/workflow-history-event-group-duration/__tests__/workflow-history-event-group-duration.test.tsx b/src/views/workflow-history-v2/workflow-history-event-group-duration/__tests__/workflow-history-event-group-duration.test.tsx index b716ef6e7..a73e139f9 100644 --- a/src/views/workflow-history-v2/workflow-history-event-group-duration/__tests__/workflow-history-event-group-duration.test.tsx +++ b/src/views/workflow-history-v2/workflow-history-event-group-duration/__tests__/workflow-history-event-group-duration.test.tsx @@ -16,6 +16,23 @@ jest.mock('../helpers/get-formatted-events-duration', () => ) ); +jest.mock( + '@/views/workflow-history/workflow-history-remaining-duration-badge/workflow-history-remaining-duration-badge', + () => { + return function MockWorkflowHistoryRemainingDurationBadge({ + prefix, + expectedEndTime, + }: { + prefix: string; + expectedEndTime: number; + }) { + return ( +
{`${prefix} ${expectedEndTime}`}
+ ); + }; + } +); + const mockStartTime = new Date('2024-01-01T10:00:00Z').getTime(); const mockCloseTime = new Date('2024-01-01T10:01:00Z').getTime(); const mockNow = new Date('2024-01-01T10:02:00Z').getTime(); @@ -111,15 +128,6 @@ describe('WorkflowHistoryEventGroupDuration', () => { expect(getFormattedEventsDuration).toHaveBeenCalledTimes(2); }); - it('cleans up interval when component unmounts', () => { - const { unmount } = setup(); - - const clearIntervalSpy = jest.spyOn(global, 'clearInterval'); - unmount(); - - expect(clearIntervalSpy).toHaveBeenCalled(); - }); - it('uses workflow close time when close time is not provided', () => { setup({ closeTime: null, @@ -133,6 +141,28 @@ describe('WorkflowHistoryEventGroupDuration', () => { ); expect(screen.getByText('60')).toBeInTheDocument(); }); + + it('renders end time badge when expectedEndTimeInfo is provided', () => { + const expectedEndTime = new Date('2024-01-01T10:05:00Z').getTime(); + setup({ + expectedEndTimeInfo: { + timeMs: expectedEndTime, + prefix: 'Fires in', + }, + }); + + expect(screen.getByTestId('end-time-badge')).toBeInTheDocument(); + expect(screen.getByText(`Fires in ${expectedEndTime}`)).toBeInTheDocument(); + }); + + it('cleans up interval when component unmounts', () => { + const { unmount } = setup(); + + const clearIntervalSpy = jest.spyOn(global, 'clearInterval'); + unmount(); + + expect(clearIntervalSpy).toHaveBeenCalled(); + }); }); function setup({ @@ -144,6 +174,7 @@ function setup({ workflowIsArchived = false, workflowCloseStatus = WorkflowExecutionCloseStatus.WORKFLOW_EXECUTION_CLOSE_STATUS_INVALID, workflowCloseTime = null, + expectedEndTimeInfo, }: Partial = {}) { return render( ); } diff --git a/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.styles.ts b/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.styles.ts new file mode 100644 index 000000000..e69faf8d7 --- /dev/null +++ b/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.styles.ts @@ -0,0 +1,9 @@ +import { styled as createStyled, type Theme } from 'baseui'; + +export const styled = { + DurationContainer: createStyled('div', ({ $theme }: { $theme: Theme }) => ({ + display: 'flex', + alignItems: 'baseline', + gap: $theme.sizing.scale200, + })), +}; diff --git a/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.tsx b/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.tsx index 3672eba58..7e4da3e95 100644 --- a/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.tsx +++ b/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.tsx @@ -1,11 +1,15 @@ import React, { useEffect, useState } from 'react'; +import WorkflowHistoryRemainingDurationBadge from '@/views/workflow-history/workflow-history-remaining-duration-badge/workflow-history-remaining-duration-badge'; + import getFormattedEventsDuration from './helpers/get-formatted-events-duration'; +import { styled } from './workflow-history-event-group-duration.styles'; import { type Props } from './workflow-history-event-group-duration.types'; export default function WorkflowHistoryEventGroupDuration({ startTime, closeTime, + expectedEndTimeInfo, workflowIsArchived, workflowCloseStatus, eventsCount, @@ -42,9 +46,23 @@ export default function WorkflowHistoryEventGroupDuration({ } }, [startTime, endTime, isOngoing]); - if (!startTime || hideDuration) { + if (!startTime) { return null; } - return <>{duration}; + return ( + + {!hideDuration && duration} + {expectedEndTimeInfo ? ( + + ) : null} + + ); } diff --git a/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.types.ts b/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.types.ts index 0b81a2a58..0076c4be3 100644 --- a/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.types.ts +++ b/src/views/workflow-history-v2/workflow-history-event-group-duration/workflow-history-event-group-duration.types.ts @@ -1,8 +1,10 @@ import { type WorkflowExecutionCloseStatus } from '@/__generated__/proto-ts/uber/cadence/api/v1/WorkflowExecutionCloseStatus'; +import { type HistoryEventsGroup } from '@/views/workflow-history/workflow-history.types'; export type Props = { startTime: number | null | undefined; closeTime: number | null | undefined; + expectedEndTimeInfo?: HistoryEventsGroup['expectedEndTimeInfo']; workflowIsArchived: boolean; workflowCloseStatus: WorkflowExecutionCloseStatus | null | undefined; eventsCount: number; diff --git a/src/views/workflow-history-v2/workflow-history-event-group/workflow-history-event-group.tsx b/src/views/workflow-history-v2/workflow-history-event-group/workflow-history-event-group.tsx index 192982f8b..35268b9ce 100644 --- a/src/views/workflow-history-v2/workflow-history-event-group/workflow-history-event-group.tsx +++ b/src/views/workflow-history-v2/workflow-history-event-group/workflow-history-event-group.tsx @@ -36,12 +36,13 @@ export default function WorkflowHistoryEventGroup({ }: Props) { const { status, + firstEventId, label, shortLabel, timeMs, startTimeMs, closeTimeMs, - // expectedEndTimeInfo, + expectedEndTimeInfo, events, eventsMetadata, hasMissingEvents, @@ -86,14 +87,14 @@ export default function WorkflowHistoryEventGroup({ ...(groupSummaryDetails.length > 0 && groupDetailsEntries.length > 1 ? [ getSummaryTabContentEntry({ - groupId: eventGroup.firstEventId ?? 'unknown', + groupId: firstEventId ?? 'unknown', summaryDetails: groupSummaryDetails, }), ] : []), ...groupDetailsEntries, ], - [eventGroup.firstEventId, groupDetailsEntries, groupSummaryDetails] + [firstEventId, groupDetailsEntries, groupSummaryDetails] ); return ( @@ -128,6 +129,7 @@ export default function WorkflowHistoryEventGroup({ loadingMoreEvents={showLoadingMoreEvents} hasMissingEvents={hasMissingEvents} workflowCloseTime={workflowCloseTimeMs} + expectedEndTimeInfo={expectedEndTimeInfo} />