From f37e28a5ada23fdd611f46cdc0472163bedf3830 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 8 Apr 2026 08:53:32 -0500 Subject: [PATCH 1/6] Redesign event detail layout with payloads left, info right - Reorder event card columns so input/payloads appear first - Extract EventPayloads and EventDetailsSection sub-components - Two-column layout in EventDetailsFull: unified payloads on left, per-event details with headers on right - Sort payloads: input, result, failures, then header/searchAttributes/memo - Apply same payloads-left pattern to pending activity and nexus cards - Remove duplicate status/name headers from pending cards - Disable hover background on expanded event history rows - Fix scheduleToStartTimeout displaying wrong value in nexus card - Add collapsible workflow details with persisted preference --- src/lib/components/event/event-card.svelte | 14 +- .../event/event-details-full.svelte | 108 +++++++++++- .../event/event-details-section.svelte | 157 ++++++++++++++++++ .../components/event/event-payloads.svelte | 75 +++++++++ .../components/event/event-summary-row.svelte | 4 +- .../pending-activity-card.svelte | 36 ++-- .../pending-nexus-operation-card.svelte | 71 ++++---- src/lib/i18n/locales/en/workflows.ts | 2 + src/lib/layouts/workflow-header.svelte | 2 +- 9 files changed, 397 insertions(+), 72 deletions(-) create mode 100644 src/lib/components/event/event-details-section.svelte create mode 100644 src/lib/components/event/event-payloads.svelte diff --git a/src/lib/components/event/event-card.svelte b/src/lib/components/event/event-card.svelte index d183f3fc4a..4343cdbe49 100644 --- a/src/lib/components/event/event-card.svelte +++ b/src/lib/components/event/event-card.svelte @@ -97,6 +97,13 @@
+ {#if payloadFields.length} +
+ {#each payloadFields as [key, value] (key)} + {@render payloads(key, value)} + {/each} +
+ {/if}
{#if event?.links?.length} {@render eventLinks(event.links)} @@ -111,13 +118,6 @@ {@render link(key, value)} {/each}
- {#if payloadFields.length} -
- {#each payloadFields as [key, value] (key)} - {@render payloads(key, value)} - {/each} -
- {/if}
diff --git a/src/lib/components/event/event-details-full.svelte b/src/lib/components/event/event-details-full.svelte index b638f7ed94..55ec8ddae5 100644 --- a/src/lib/components/event/event-details-full.svelte +++ b/src/lib/components/event/event-details-full.svelte @@ -1,11 +1,17 @@ {#if showEventGroup} @@ -27,9 +95,43 @@ {:else if group?.pendingNexusOperation} {/if} - {#each group.eventList as groupEvent} - - {/each} + + {#if hasAnyPayloads} +
+
+ +
+
+ {#each processedEvents as processed (processed.event.id)} +
+
+ +
+
+ {/each} +
+
+ {:else} + {#each processedEvents as processed (processed.event.id)} +
+
+ +
+
+ {/each} + {/if} {:else if event} diff --git a/src/lib/components/event/event-details-section.svelte b/src/lib/components/event/event-details-section.svelte new file mode 100644 index 0000000000..6b404384a6 --- /dev/null +++ b/src/lib/components/event/event-details-section.svelte @@ -0,0 +1,157 @@ + + +{#if showHeader} +
+
+ {event.id} +

+ {displayName} +

+
+ +
+{/if} + +{#if event?.links?.length} + {#each event.links as link} + {@const href = getEventLinkHref(link)} + {@const value = href.split('workflows/')?.[1] || href} +
+

+ {translate('nexus.link')} +

+ + {value} + +
+ {@const nsHref = routeForNamespace({ + namespace: link.workflowEvent.namespace, + })} +
+

+ {translate('nexus.link-namespace')} +

+ + {link.workflowEvent.namespace} + +
+ {/each} +{/if} + +{#if event?.userMetadata?.summary} +
+

Summary

+

+ + {decodedValue} + +

+
+{/if} + +{#each detailFields as [key, value] (key)} +
+

+ {format(key)} +

+

+ {#if shouldDisplayAsTime(key)} + + {:else} + {value} + {/if} +

+
+{/each} + +{#each linkFields as [key, value] (key)} +
+

+ {format(key)} +

+ + + +
+{/each} diff --git a/src/lib/components/event/event-payloads.svelte b/src/lib/components/event/event-payloads.svelte new file mode 100644 index 0000000000..28ab6dbf9a --- /dev/null +++ b/src/lib/components/event/event-payloads.svelte @@ -0,0 +1,75 @@ + + +{#each payloadFields as [key, value] (key)} + {@const codeBlockValue = getCodeBlockValue(value)} + {@const stackTrace = getStackTrace(codeBlockValue)} +
+

+ {format(key)} +

+ {#if value?.payloads} + + {#snippet children(decodedValue)} + + {/snippet} + + {:else if key === 'searchAttributes'} + + {#snippet children(decodedValue)} + + {/snippet} + + {:else} + + {#snippet children(decodedValue)} + + {/snippet} + + {/if} +
+ {#if stackTrace} +
+

+ {translate('workflows.call-stack-tab')} +

+ +
+ {/if} +{/each} diff --git a/src/lib/components/event/event-summary-row.svelte b/src/lib/components/event/event-summary-row.svelte index 9c9417b833..04d3602783 100644 --- a/src/lib/components/event/event-summary-row.svelte +++ b/src/lib/components/event/event-summary-row.svelte @@ -201,7 +201,7 @@ {#if expanded} diff --git a/src/lib/components/workflow/pending-activity/pending-activity-card.svelte b/src/lib/components/workflow/pending-activity/pending-activity-card.svelte index ee1075e49f..42e5bb32e1 100644 --- a/src/lib/components/workflow/pending-activity/pending-activity-card.svelte +++ b/src/lib/components/workflow/pending-activity/pending-activity-card.svelte @@ -47,16 +47,24 @@
-
-
- -

{activity.activityType}

-
- {#if showActivityCommands} + {#if showActivityCommands} +
- {/if} -
+
+ {/if}
+
+ {#if failed} + {#if totalPending > 20} + {@render failuresAccordion()} + {:else} + {@render failuresCodeBlock()} + {/if} + {/if} + {#if activity.heartbeatDetails} + {@render heartbeat()} + {/if} +
{@render detail(translate('workflows.activity-id'), activity.activityId)} {#if activity.paused && activity.pauseInfo} @@ -136,18 +144,6 @@ {/if} {/if}
-
- {#if failed} - {#if totalPending > 20} - {@render failuresAccordion()} - {:else} - {@render failuresCodeBlock()} - {/if} - {/if} - {#if activity.heartbeatDetails} - {@render heartbeat()} - {/if} -
diff --git a/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte b/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte index 40207607bd..65af0c2712 100644 --- a/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte +++ b/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte @@ -19,14 +19,38 @@
-
-
- {operation.state} -

{translate('workflows.pending-nexus-operation')}

-
-
-
+
+ {#if failed} + {@render failures()} + {/if} + {#if operation.blockedReason} +
+

+ {translate('nexus.blocked-reason')} +

+ +
+ {/if} + {#if Object.keys(operation.cancellationInfo ?? {}).length > 0} +
+

+ {translate('nexus.cancellation-info')} +

+ +
+ {/if} +
{#if operation.endpoint} {@render detail(translate('nexus.endpoint'), operation.endpoint)} @@ -80,7 +104,7 @@ {#if operation.scheduleToStartTimeout} {@render detail( translate('workflows.schedule-to-start-timeout'), - operation.scheduleToCloseTimeout as string, + operation.scheduleToStartTimeout as string, )} {/if} {#if operation.startToCloseTimeout} @@ -90,37 +114,6 @@ )} {/if}
-
- {#if failed} - {@render failures()} - {/if} - {#if operation.blockedReason} -
-

- {translate('nexus.blocked-reason')} -

- -
- {/if} - {#if Object.keys(operation.cancellationInfo ?? {}).length > 0} -
-

- {translate('nexus.cancellation-info')} -

- -
- {/if} -
diff --git a/src/lib/i18n/locales/en/workflows.ts b/src/lib/i18n/locales/en/workflows.ts index d06ea88181..bb8cdfe8f0 100644 --- a/src/lib/i18n/locales/en/workflows.ts +++ b/src/lib/i18n/locales/en/workflows.ts @@ -171,6 +171,8 @@ export const Strings = { children_one: '1 Child', children_other: '{{count}} Children', 'show-children': 'View Child Workflows', + 'show-workflow-details': 'Show Workflow Details', + 'hide-workflow-details': 'Hide Workflow Details', first: '{{count}} First', previous: '{{count}} Previous', next: '{{count}} Next', diff --git a/src/lib/layouts/workflow-header.svelte b/src/lib/layouts/workflow-header.svelte index 0d0e80a1d5..161d19f5e8 100644 --- a/src/lib/layouts/workflow-header.svelte +++ b/src/lib/layouts/workflow-header.svelte @@ -1,5 +1,5 @@
- {#if pendingActivities.length} + {#if pendingGroups.length}
- {#each pendingActivities as activity (activity.id)} - + {#each pendingGroups as group (group.id)} + {/each}
{:else} From 747bf4c8d72e0e564d60f1a5d1290c2e1e7ac826 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 10 Apr 2026 09:41:30 -0500 Subject: [PATCH 4/6] Move payload fields to the right instead of the left for better consistency with current UI --- src/lib/components/event/event-card.svelte | 14 ++--- .../event/event-details-full.svelte | 6 +- .../pending-activity-card.svelte | 34 +++++----- .../pending-nexus-operation-card.svelte | 62 +++++++++---------- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/lib/components/event/event-card.svelte b/src/lib/components/event/event-card.svelte index 4343cdbe49..d183f3fc4a 100644 --- a/src/lib/components/event/event-card.svelte +++ b/src/lib/components/event/event-card.svelte @@ -97,13 +97,6 @@
- {#if payloadFields.length} -
- {#each payloadFields as [key, value] (key)} - {@render payloads(key, value)} - {/each} -
- {/if}
{#if event?.links?.length} {@render eventLinks(event.links)} @@ -118,6 +111,13 @@ {@render link(key, value)} {/each}
+ {#if payloadFields.length} +
+ {#each payloadFields as [key, value] (key)} + {@render payloads(key, value)} + {/each} +
+ {/if}
diff --git a/src/lib/components/event/event-details-full.svelte b/src/lib/components/event/event-details-full.svelte index 6a8fd4000c..e20bda33af 100644 --- a/src/lib/components/event/event-details-full.svelte +++ b/src/lib/components/event/event-details-full.svelte @@ -100,9 +100,6 @@
-
- -
{#each processedEvents as processed, i (processed.event.id)}
{/each}
+
+ +
{:else} {#each processedEvents as processed (processed.event.id)} diff --git a/src/lib/components/workflow/pending-activity/pending-activity-card.svelte b/src/lib/components/workflow/pending-activity/pending-activity-card.svelte index 42e5bb32e1..03e9acbe28 100644 --- a/src/lib/components/workflow/pending-activity/pending-activity-card.svelte +++ b/src/lib/components/workflow/pending-activity/pending-activity-card.svelte @@ -47,24 +47,7 @@
- {#if showActivityCommands} -
- -
- {/if}
-
- {#if failed} - {#if totalPending > 20} - {@render failuresAccordion()} - {:else} - {@render failuresCodeBlock()} - {/if} - {/if} - {#if activity.heartbeatDetails} - {@render heartbeat()} - {/if} -
{@render detail(translate('workflows.activity-id'), activity.activityId)} {#if activity.paused && activity.pauseInfo} @@ -143,6 +126,23 @@ )} {/if} {/if} + {#if showActivityCommands} +
+ +
+ {/if} +
+
+ {#if failed} + {#if totalPending > 20} + {@render failuresAccordion()} + {:else} + {@render failuresCodeBlock()} + {/if} + {/if} + {#if activity.heartbeatDetails} + {@render heartbeat()} + {/if}
diff --git a/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte b/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte index 65af0c2712..eb7c7bc75d 100644 --- a/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte +++ b/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte @@ -20,37 +20,6 @@ class="surface-primary flex flex-1 cursor-default flex-col gap-2 border-b border-subtle p-4" >
-
- {#if failed} - {@render failures()} - {/if} - {#if operation.blockedReason} -
-

- {translate('nexus.blocked-reason')} -

- -
- {/if} - {#if Object.keys(operation.cancellationInfo ?? {}).length > 0} -
-

- {translate('nexus.cancellation-info')} -

- -
- {/if} -
{#if operation.endpoint} {@render detail(translate('nexus.endpoint'), operation.endpoint)} @@ -114,6 +83,37 @@ )} {/if}
+
+ {#if failed} + {@render failures()} + {/if} + {#if operation.blockedReason} +
+

+ {translate('nexus.blocked-reason')} +

+ +
+ {/if} + {#if Object.keys(operation.cancellationInfo ?? {}).length > 0} +
+

+ {translate('nexus.cancellation-info')} +

+ +
+ {/if} +
From 2802e2c20beb274043e82f6c845c195bfc69fb68 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 13 Apr 2026 21:19:07 -0500 Subject: [PATCH 5/6] Better styles, add distance between events --- .../event/event-details-full.svelte | 16 ++--- .../event/event-details-section.svelte | 68 +++++++++++-------- .../components/event/event-payloads.svelte | 4 +- .../components/event/event-summary-row.svelte | 2 +- .../pending-activity-card.svelte | 19 +++--- .../pending-nexus-operation-card.svelte | 12 ++-- 6 files changed, 67 insertions(+), 54 deletions(-) diff --git a/src/lib/components/event/event-details-full.svelte b/src/lib/components/event/event-details-full.svelte index e20bda33af..142539581e 100644 --- a/src/lib/components/event/event-details-full.svelte +++ b/src/lib/components/event/event-details-full.svelte @@ -89,7 +89,9 @@ {#if showEventGroup} -
+
{#if group?.pendingActivity} {:else if group?.pendingNexusOperation} @@ -97,10 +99,8 @@ {/if} {#if hasAnyPayloads} -
-
+
+
{#each processedEvents as processed, i (processed.event.id)}
@@ -125,14 +125,14 @@
{:else} {#each processedEvents as processed (processed.event.id)} -
+
diff --git a/src/lib/components/event/event-details-section.svelte b/src/lib/components/event/event-details-section.svelte index 6b404384a6..73d30d39df 100644 --- a/src/lib/components/event/event-details-section.svelte +++ b/src/lib/components/event/event-details-section.svelte @@ -2,12 +2,10 @@ import { page } from '$app/state'; import Timestamp from '$lib/components/timestamp.svelte'; - import CodeBlock from '$lib/holocene/code-block.svelte'; import Copyable from '$lib/holocene/copyable/index.svelte'; import Link from '$lib/holocene/link.svelte'; import { translate } from '$lib/i18n/translate'; - import type { EventLink as ELink } from '$lib/types'; - import { type Payload } from '$lib/types'; + import type { EventGroup } from '$lib/models/event-groups/event-groups'; import type { WorkflowEvent } from '$lib/types/events'; import { getEventLinkHref } from '$lib/utilities/event-link-href'; import { @@ -15,6 +13,7 @@ spaceBetweenCapitalLetters, } from '$lib/utilities/format-camel-case'; import type { CombinedAttributes } from '$lib/utilities/format-event-attributes'; + import { formatDistanceAbbreviated } from '$lib/utilities/format-time'; import { displayLinkType, shouldDisplayAsTime, @@ -30,16 +29,16 @@ let { event, + group, attributes, detailFields, linkFields, - showHeader = false, }: { event: WorkflowEvent; + group?: EventGroup; attributes: CombinedAttributes; detailFields: [string, unknown][]; linkFields: [string, unknown][]; - showHeader?: boolean; } = $props(); const { namespace, workflow, run } = $derived(page.params); @@ -49,33 +48,48 @@ ? translate('events.category.local-activity') : spaceBetweenCapitalLetters(event.name), ); + + const durationSinceLastEvent = $derived.by(() => { + if (!group) return ''; + const eventIndex = group.eventList.findIndex((evt) => evt.id === event.id); + if (eventIndex === -1 || eventIndex === 0) return ''; + const previousEvent = group.eventList[eventIndex - 1]; + return formatDistanceAbbreviated({ + start: event.eventTime, + end: previousEvent.eventTime, + includeMilliseconds: true, + }); + }); -{#if showHeader} -
-
- {event.id} -

- {displayName} -

-
- +
+
+ {event.id} +

+ {displayName} +

-{/if} +
+ + {#if durationSinceLastEvent} +

+{durationSinceLastEvent}

+ {/if} +
+
{#if event?.links?.length} {#each event.links as link} {@const href = getEventLinkHref(link)} {@const value = href.split('workflows/')?.[1] || href}
-

+

{translate('nexus.link')}

-

+

{translate('nexus.link-namespace')}

-

Summary

+

Summary

-

+

{format(key)}

@@ -138,7 +152,7 @@ {#each linkFields as [key, value] (key)}

-

+

{format(key)}

-

+

{format(key)}

{#if value?.payloads} @@ -60,7 +60,7 @@
{#if stackTrace}
-

+

{translate('workflows.call-stack-tab')}

-
-
+
+
{@render detail(translate('workflows.activity-id'), activity.activityId)} {#if activity.paused && activity.pauseInfo} {@render detail( @@ -132,7 +131,7 @@
{/if}
-
+
{#if failed} {#if totalPending > 20} {@render failuresAccordion()} @@ -149,7 +148,7 @@ {#snippet detail(label: string, value: string | number | Snippet)}
-

+

{label}

@@ -164,7 +163,7 @@ {#snippet heartbeat()}

-

+

{translate('workflows.heartbeat-details')}

{#key activity.attempt} @@ -186,7 +185,7 @@
{#if activity.lastFailure} -

+

{translate('workflows.last-failure')}

{#key activity.attempt} @@ -207,7 +206,7 @@
{#if activity.lastFailure?.stackTrace}
-

+

{translate('common.stack-trace')}

-

+

{translate('workflows.next-retry')}

diff --git a/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte b/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte index eb7c7bc75d..99fc83596f 100644 --- a/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte +++ b/src/lib/components/workflow/pending-nexus-operation/pending-nexus-operation-card.svelte @@ -89,7 +89,7 @@ {/if} {#if operation.blockedReason}

-

+

{translate('nexus.blocked-reason')}

0}
-

+

{translate('nexus.cancellation-info')}

-

+

{translate('workflows.next-retry')}

@@ -131,7 +131,7 @@ {#snippet detail(label: string, value: string | number | Snippet)}

-

+

{label}

@@ -155,7 +155,7 @@

{#if operation.lastAttemptFailure} -

+

{translate('workflows.last-failure')}

{#if operation.lastAttemptFailure?.stackTrace} -

+

{translate('common.stack-trace')}

Date: Mon, 13 Apr 2026 22:23:32 -0500 Subject: [PATCH 6/6] Fix event card label text styles to match --- src/lib/components/event/event-card.svelte | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib/components/event/event-card.svelte b/src/lib/components/event/event-card.svelte index d183f3fc4a..75d5961018 100644 --- a/src/lib/components/event/event-card.svelte +++ b/src/lib/components/event/event-card.svelte @@ -125,7 +125,7 @@ {@const href = getEventLinkHref(link)} {@const value = href.split('workflows/')?.[1] || href}
-

+

{translate('nexus.link')}

-

+

{translate('nexus.link-namespace')}

-

Summary

+

Summary

-

+

{format(key)}

{#if value?.payloads} @@ -225,7 +225,7 @@
{#if stackTrace}
-

+

{translate('workflows.call-stack-tab')}

-

+

{format(key)}

-

+

{format(key)}