Skip to content

Commit bae1348

Browse files
authored
History event details listing (#687)
* history event details list * fix typecheck * use format in export json and move tasklist link dir * fix type check
1 parent 887646a commit bae1348

27 files changed

+871
-21
lines changed

src/components/page-section/page-section.styles.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export const styled = {
88
maxWidth: `${$theme.grid.maxWidth + 2 * margin}px`,
99
paddingRight: `${margin}px`,
1010
paddingLeft: `${margin}px`,
11+
width: '100%',
12+
margin: '0 auto',
1113
})),
1214
})),
1315
};
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import type { HistoryEvent } from '@/__generated__/proto-ts/uber/cadence/api/v1/HistoryEvent';
22

3-
import { getFormatHistoryEventSchema } from '../schema/format-history-event-schema';
3+
import {
4+
type FormattedHistoryEvent,
5+
getFormatHistoryEventSchema,
6+
} from '../schema/format-history-event-schema';
47

5-
export default function formatWorkflowHistoryEvent(event: HistoryEvent) {
8+
export default function formatWorkflowHistoryEvent(
9+
event: HistoryEvent
10+
): FormattedHistoryEvent | null {
611
const schema = getFormatHistoryEventSchema(event);
712
if (schema) {
813
const { data } = schema.safeParse(event);
914
return data ?? null;
1015
}
16+
return null;
1117
}

src/utils/data-formatters/schema/format-history-event-schema.ts

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { type z } from 'zod';
2+
13
import { type HistoryEvent } from '@/__generated__/proto-ts/uber/cadence/api/v1/HistoryEvent';
24

35
import formatActivityTaskCancelRequestedEvent from '../format-workflow-history-event/format-activity-task-cancel-requested-event';
@@ -379,3 +381,173 @@ export const getFormatHistoryEventSchema = function (event: HistoryEvent) {
379381
return unExistingEventType(event.attributes); // should not be unreachable, used to show a type error if not all attributes cases are covered
380382
}
381383
};
384+
385+
export type FormattedWorkflowExecutionStartedEvent = z.infer<
386+
typeof formatWorkflowExecutionStartedEventSchema
387+
>;
388+
export type FormattedWorkflowExecutionCompletedEvent = z.infer<
389+
typeof formatWorkflowExecutionCompletedEventSchema
390+
>;
391+
export type FormattedWorkflowExecutionFailedEvent = z.infer<
392+
typeof formatWorkflowExecutionFailedEventSchema
393+
>;
394+
export type FormattedWorkflowExecutionTimedOutEvent = z.infer<
395+
typeof formatWorkflowExecutionTimedOutEventSchema
396+
>;
397+
export type FormattedWorkflowExecutionSignaledEvent = z.infer<
398+
typeof formatWorkflowExecutionSignaledEventSchema
399+
>;
400+
export type FormattedWorkflowExecutionTerminatedEvent = z.infer<
401+
typeof formatWorkflowExecutionTerminatedEventSchema
402+
>;
403+
export type FormattedWorkflowExecutionCanceledEvent = z.infer<
404+
typeof formatWorkflowExecutionCanceledEventSchema
405+
>;
406+
export type FormattedWorkflowExecutionContinuedAsNewEvent = z.infer<
407+
typeof formatWorkflowExecutionContinuedAsNewEventSchema
408+
>;
409+
export type FormattedWorkflowExecutionCancelRequestedEventAttributesSchema =
410+
z.infer<typeof formatWorkflowExecutionCancelRequestedEventAttributesSchema>;
411+
export type FormattedDecisionTaskCompletedEvent = z.infer<
412+
typeof formatDecisionTaskCompletedEventSchema
413+
>;
414+
export type FormattedDecisionTaskFailedEvent = z.infer<
415+
typeof formatDecisionTaskFailedEventSchema
416+
>;
417+
export type FormattedDecisionTaskScheduledEvent = z.infer<
418+
typeof formatDecisionTaskScheduledEventSchema
419+
>;
420+
export type FormattedDecisionTaskStartedEvent = z.infer<
421+
typeof formatDecisionTaskStartedEventSchema
422+
>;
423+
export type FormattedDecisionTaskTimedOutEvent = z.infer<
424+
typeof formatDecisionTaskTimedOutEventSchema
425+
>;
426+
export type FormattedActivityTaskCancelRequestedEvent = z.infer<
427+
typeof formatActivityTaskCancelRequestedEventSchema
428+
>;
429+
export type FormattedActivityTaskCanceledEvent = z.infer<
430+
typeof formatActivityTaskCanceledEventSchema
431+
>;
432+
export type FormattedActivityTaskCompletedEvent = z.infer<
433+
typeof formatActivityTaskCompletedEventSchema
434+
>;
435+
export type FormattedActivityTaskFailedEvent = z.infer<
436+
typeof formatActivityTaskFailedEventSchema
437+
>;
438+
export type FormattedActivityTaskScheduledEvent = z.infer<
439+
typeof formatActivityTaskScheduledEventSchema
440+
>;
441+
export type FormattedActivityTaskStartedEvent = z.infer<
442+
typeof formatActivityTaskStartedEventSchema
443+
>;
444+
export type FormattedActivityTaskTimedOutEvent = z.infer<
445+
typeof formatActivityTaskTimedOutEventSchema
446+
>;
447+
export type FormattedRequestCancelActivityTaskFailedEvent = z.infer<
448+
typeof formatRequestCancelActivityTaskFailedEventSchema
449+
>;
450+
export type FormattedTimerCanceledEvent = z.infer<
451+
typeof formatTimerCanceledEventSchema
452+
>;
453+
export type FormattedTimerFiredEvent = z.infer<
454+
typeof formatTimerFiredEventSchema
455+
>;
456+
export type FormattedTimerStartedEvent = z.infer<
457+
typeof formatTimerStartedEventSchema
458+
>;
459+
export type FormattedCancelTimerFailedEvent = z.infer<
460+
typeof formatCancelTimerFailedEventSchema
461+
>;
462+
export type FormattedMarkerRecordedEvent = z.infer<
463+
typeof formatMarkerRecordedEventSchema
464+
>;
465+
export type FormattedExternalWorkflowExecutionCancelRequestedEvent = z.infer<
466+
typeof formatExternalWorkflowExecutionCancelRequestedEventSchema
467+
>;
468+
export type FormattedExternalWorkflowExecutionSignaledEvent = z.infer<
469+
typeof formatExternalWorkflowExecutionSignaledEventSchema
470+
>;
471+
export type FormattedSignalExternalWorkflowExecutionFailedEvent = z.infer<
472+
typeof formatSignalExternalWorkflowExecutionFailedEventSchema
473+
>;
474+
export type FormattedSignalExternalWorkflowExecutionInitiatedEvent = z.infer<
475+
typeof formatSignalExternalWorkflowExecutionInitiatedEventSchema
476+
>;
477+
export type FormattedRequestCancelExternalWorkflowExecutionFailedEvent =
478+
z.infer<typeof formatRequestCancelExternalWorkflowExecutionFailedEventSchema>;
479+
export type FormattedRequestCancelExternalWorkflowExecutionInitiatedEvent =
480+
z.infer<
481+
typeof formatRequestCancelExternalWorkflowExecutionInitiatedEventSchema
482+
>;
483+
export type FormattedChildWorkflowExecutionCanceledEvent = z.infer<
484+
typeof formatChildWorkflowExecutionCanceledEventSchema
485+
>;
486+
export type FormattedChildWorkflowExecutionCompletedEvent = z.infer<
487+
typeof formatChildWorkflowExecutionCompletedEventSchema
488+
>;
489+
export type FormattedChildWorkflowExecutionFailedEvent = z.infer<
490+
typeof formatChildWorkflowExecutionFailedEventSchema
491+
>;
492+
export type FormattedChildWorkflowExecutionStartedEvent = z.infer<
493+
typeof formatChildWorkflowExecutionStartedEventSchema
494+
>;
495+
export type FormattedChildWorkflowExecutionTerminatedEvent = z.infer<
496+
typeof formatChildWorkflowExecutionTerminatedEventSchema
497+
>;
498+
export type FormattedChildWorkflowExecutionTimedOutEvent = z.infer<
499+
typeof formatChildWorkflowExecutionTimedOutEventSchema
500+
>;
501+
export type FormattedStartChildWorkflowExecutionFailedEvent = z.infer<
502+
typeof formatStartChildWorkflowExecutionFailedEventSchema
503+
>;
504+
export type FormattedStartChildWorkflowExecutionInitiatedEvent = z.infer<
505+
typeof formatStartChildWorkflowExecutionInitiatedEventSchema
506+
>;
507+
export type FormattedUpsertWorkflowSearchAttributesEvent = z.infer<
508+
typeof formatUpsertWorkflowSearchAttributesEventSchema
509+
>;
510+
511+
export type FormattedHistoryEvent =
512+
| FormattedWorkflowExecutionStartedEvent
513+
| FormattedWorkflowExecutionCompletedEvent
514+
| FormattedWorkflowExecutionFailedEvent
515+
| FormattedWorkflowExecutionTimedOutEvent
516+
| FormattedWorkflowExecutionSignaledEvent
517+
| FormattedWorkflowExecutionTerminatedEvent
518+
| FormattedWorkflowExecutionCanceledEvent
519+
| FormattedWorkflowExecutionContinuedAsNewEvent
520+
| FormattedWorkflowExecutionCancelRequestedEventAttributesSchema
521+
| FormattedDecisionTaskCompletedEvent
522+
| FormattedDecisionTaskFailedEvent
523+
| FormattedDecisionTaskScheduledEvent
524+
| FormattedDecisionTaskStartedEvent
525+
| FormattedDecisionTaskTimedOutEvent
526+
| FormattedActivityTaskCancelRequestedEvent
527+
| FormattedActivityTaskCanceledEvent
528+
| FormattedActivityTaskCompletedEvent
529+
| FormattedActivityTaskFailedEvent
530+
| FormattedActivityTaskScheduledEvent
531+
| FormattedActivityTaskStartedEvent
532+
| FormattedActivityTaskTimedOutEvent
533+
| FormattedRequestCancelActivityTaskFailedEvent
534+
| FormattedTimerCanceledEvent
535+
| FormattedTimerFiredEvent
536+
| FormattedTimerStartedEvent
537+
| FormattedCancelTimerFailedEvent
538+
| FormattedMarkerRecordedEvent
539+
| FormattedExternalWorkflowExecutionCancelRequestedEvent
540+
| FormattedExternalWorkflowExecutionSignaledEvent
541+
| FormattedSignalExternalWorkflowExecutionFailedEvent
542+
| FormattedSignalExternalWorkflowExecutionInitiatedEvent
543+
| FormattedRequestCancelExternalWorkflowExecutionFailedEvent
544+
| FormattedRequestCancelExternalWorkflowExecutionInitiatedEvent
545+
| FormattedChildWorkflowExecutionCanceledEvent
546+
| FormattedChildWorkflowExecutionCompletedEvent
547+
| FormattedChildWorkflowExecutionFailedEvent
548+
| FormattedChildWorkflowExecutionStartedEvent
549+
| FormattedChildWorkflowExecutionTerminatedEvent
550+
| FormattedChildWorkflowExecutionTimedOutEvent
551+
| FormattedStartChildWorkflowExecutionFailedEvent
552+
| FormattedStartChildWorkflowExecutionInitiatedEvent
553+
| FormattedUpsertWorkflowSearchAttributesEvent;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { createElement } from 'react';
2+
3+
import PrettyJson from '@/components/pretty-json/pretty-json';
4+
import formatDate from '@/utils/data-formatters/format-date';
5+
6+
import { type WorkflowHistoryEventDetailsConfig } from '../workflow-history-event-details/workflow-history-event-details.types';
7+
import WorkflowHistoryEventDetailsTaskListLink from '../workflow-history-event-details-task-list-link/workflow-history-event-details-task-list-link';
8+
9+
const workflowHistoryEventDetailsConfig = [
10+
{
11+
name: 'Filter empty value',
12+
customMatcher: ({ value }) => value === null || value === undefined,
13+
hide: () => true,
14+
},
15+
{
16+
name: 'Date object as time string',
17+
customMatcher: ({ value }) => value instanceof Date,
18+
valueComponent: ({ entryValue }) => formatDate(entryValue),
19+
},
20+
{
21+
name: 'Tasklists as links',
22+
key: 'taskList',
23+
valueComponent: WorkflowHistoryEventDetailsTaskListLink,
24+
},
25+
{
26+
name: 'Json as PrettyJson',
27+
pathRegex: '.*(input|result|details|Error)$',
28+
valueComponent: ({ entryValue }) => {
29+
return createElement(PrettyJson, {
30+
json: entryValue,
31+
});
32+
},
33+
},
34+
{
35+
name: 'Duration timeout & backoff seconds',
36+
pathRegex: '.+(TimeoutSeconds|BackoffSeconds)$',
37+
valueComponent: ({ entryValue }) => `${entryValue}s`, // TODO @assem.hafez: format the value as duration
38+
},
39+
] as const satisfies WorkflowHistoryEventDetailsConfig[];
40+
41+
export default workflowHistoryEventDetailsConfig;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from 'react';
2+
3+
import { render } from '@/test-utils/rtl';
4+
5+
import WorkflowHistoryEventDetailsTaskListLink from '../workflow-history-event-details-task-list-link';
6+
import { type Props } from '../workflow-history-event-details-task-list-link.types';
7+
8+
describe('WorkflowHistoryEventDetailsTaskListLink', () => {
9+
const props: Props = {
10+
runId: 'testRunId',
11+
workflowId: 'testWorkflowId',
12+
cluster: 'testCluster',
13+
domain: 'testDomain',
14+
workflowTab: 'history',
15+
entryKey: 'taskList',
16+
entryPath: 'event.taskList',
17+
entryValue: {
18+
name: 'testTaskListName',
19+
},
20+
};
21+
22+
it('should render the link with correct href', () => {
23+
const { getByText } = render(
24+
<WorkflowHistoryEventDetailsTaskListLink {...props} />
25+
);
26+
27+
const linkElement = getByText(props.entryValue.name).closest('a');
28+
expect(linkElement).toHaveAttribute(
29+
'href',
30+
`/domains/${props.domain}/${props.cluster}/task-lists/${props.entryValue.name}`
31+
);
32+
});
33+
34+
it('should render the tasklist name as link text', () => {
35+
const { getByText } = render(
36+
<WorkflowHistoryEventDetailsTaskListLink {...props} />
37+
);
38+
39+
expect(getByText(props.entryValue.name)).toBeInTheDocument();
40+
});
41+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use client';
2+
import React from 'react';
3+
4+
import { StyledLink } from 'baseui/link';
5+
import Link from 'next/link';
6+
7+
import { type Props } from './workflow-history-event-details-task-list-link.types';
8+
9+
export default function WorkflowHistoryEventDetailsTaskListLink({
10+
cluster,
11+
domain,
12+
entryValue,
13+
}: Props) {
14+
return (
15+
<StyledLink
16+
$as={Link}
17+
href={`/domains/${encodeURIComponent(domain)}/${encodeURIComponent(cluster)}/task-lists/${encodeURIComponent(entryValue.name)}`}
18+
style={{ fontWeight: 'inherit' }}
19+
>
20+
{entryValue.name}
21+
</StyledLink>
22+
);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { Props as WorfklowHistoryProps } from '../workflow-history.types';
2+
3+
export type Props = {
4+
entryKey: string;
5+
entryPath: string;
6+
entryValue: any;
7+
} & WorfklowHistoryProps['params'];

0 commit comments

Comments
 (0)