Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
da0bb84
Svelte5
Alex-Tideman Jun 5, 2025
b9d8bdc
Add search-attributes tab, memo tab, user metadata tab
Alex-Tideman Jun 5, 2025
bd41961
add tests
GraceGardner Jun 30, 2025
c8af4e8
rm console logs
GraceGardner Jun 30, 2025
6f8511d
rm inspect
GraceGardner Jun 30, 2025
34dd7f4
rm unused mock data
GraceGardner Jun 30, 2025
5bc9a1f
add typing to overrideTheme
GraceGardner Jun 30, 2025
8715bb4
Merge branch 'main' into user-metadata
GraceGardner Jun 30, 2025
a0d54a2
center divs
GraceGardner Jun 30, 2025
dc9a041
add metadata-tab to translate
GraceGardner Jul 1, 2025
3a0aff2
add markdown override-theme to go
GraceGardner Jul 1, 2025
d9445ae
add banner
GraceGardner Jul 16, 2025
dd02933
fix function
GraceGardner Jul 22, 2025
99623ee
rm consols
GraceGardner Jul 22, 2025
e9451b6
Merge branch 'main' into user-metadata
GraceGardner Jul 22, 2025
fe713b7
update event display, fix markdown, make summary and details and curr…
GraceGardner Jul 28, 2025
f18c994
quick tweak to view height
GraceGardner Jul 28, 2025
27d1ab3
fix errors caused by runes mode/legacy mismatch
GraceGardner Jul 28, 2025
c269080
fix conflicts/merge main
GraceGardner Jul 28, 2025
a8026c9
<<Merge branch 'main' into user-metadata
GraceGardner Jul 29, 2025
1b07d4c
add summary back in and remove event id
GraceGardner Jul 29, 2025
31ae005
Do some refactoring, move events into the left side
Alex-Tideman Jul 29, 2025
ba71313
move memo into component
GraceGardner Jul 29, 2025
9690395
mv search attr into component
GraceGardner Jul 29, 2025
7e09057
updates from feedback
GraceGardner Jul 31, 2025
cf5b784
Merge branch 'main' into user-metadata
GraceGardner Aug 5, 2025
dc2a742
put usermetadata into single component
GraceGardner Aug 5, 2025
7b109cc
clean up metadata events
GraceGardner Aug 5, 2025
e0159a0
rm ('Metadata groups:', metadataGroups);
GraceGardner Aug 5, 2025
805f0ca
Style updates
Alex-Tideman Aug 6, 2025
67f5def
Move tab
Alex-Tideman Aug 6, 2025
bd3d51e
standardize the time stamp with other time formats
GraceGardner Aug 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions server/server/route/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ func SetRenderRoute(e *echo.Echo, publicPath string) {
e.GET(renderPath, func(c echo.Context) error {
content := c.QueryParam("content")
theme := c.QueryParam("theme")
overrideTheme := c.QueryParam("overrideTheme")

finalTheme := theme
if theme != "" && overrideTheme != "" {
finalTheme = fmt.Sprintf("%s-%s", theme, overrideTheme)
}

// Process markdown to HTML
renderedHTML := processMarkdown(content)
Expand All @@ -175,7 +181,7 @@ func SetRenderRoute(e *echo.Echo, publicPath string) {
}{
Content: template.HTML(renderedHTML),
Nonce: nonce,
Theme: theme,
Theme: finalTheme,
CSS: `*,
body {
margin: 0;
Expand Down Expand Up @@ -311,7 +317,43 @@ func SetRenderRoute(e *echo.Echo, publicPath string) {

body[data-theme='dark'] a {
color: #8098f9;
}`,
}

body[data-theme='light-background'] {
background-color: #f8fafc;
color: #121416;
}

body[data-theme='light-background']a {
color: #444ce7;
}

body[data-theme='dark-background'] {
background-color: #141414;
color: #f8fafc;
}
body[data-theme='dark-background'] a {
color: #8098f9;
}

body[data-theme='light-primary'] {
background-color: #fff;
color: #121416;
}
body[data-theme='light-primary']a {
color: #444ce7;
}

body[data-theme='dark-primary'] {
background-color: #000;
color: #f8fafc;
}

body[data-theme='dark-primary']a {
color: #8098f9;
}
`,

}

// Set headers
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/bottom-nav-links.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

{#if open}
<div
class="flex h-full flex-col flex-col-reverse justify-start gap-6 overflow-auto px-4 py-8"
class="flex h-full flex-col-reverse justify-start gap-6 overflow-auto px-4 py-8"
>
{#each linkList as item}
{#if item.divider}
Expand Down
84 changes: 84 additions & 0 deletions src/lib/components/workflow/metadata/metadata-events.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<script lang="ts">
import MetadataDecoder from '$lib/components/event/metadata-decoder.svelte';
import Badge from '$lib/holocene/badge.svelte';
import Icon from '$lib/holocene/icon/icon.svelte';
import TableHeaderRow from '$lib/holocene/table/table-header-row.svelte';
import TableRow from '$lib/holocene/table/table-row.svelte';
import Table from '$lib/holocene/table/table.svelte';
import { translate } from '$lib/i18n/translate';
import type { EventGroups } from '$lib/models/event-groups/event-groups';
import { relativeTime, timeFormat } from '$lib/stores/time-format';
import { formatDate } from '$lib/utilities/format-date';
export let groups: EventGroups;
const getBadgeType = (classification: string) => {
switch (classification) {
case 'Completed':
return 'success';
case 'Failed':
case 'Terminated':
return 'danger';
case 'TimedOut':
case 'Canceled':
return 'warning';
default:
return 'default';
}
};
</script>

<div class="overflow-x-auto">
<Table class="min-w-full table-fixed" data-testid="metadata-events-table">
<caption class="sr-only" slot="caption">
{translate('workflows.user-metadata-tab')}
</caption>
<TableHeaderRow slot="headers">
<th class="w-1/5 px-3 py-3 text-left">{translate('common.event-type')}</th
>
<th class="w-1/6 px-3 py-3 text-left">{translate('common.status')}</th>
<th class="w-1/4 px-3 py-3 text-left">{translate('common.time')}</th>
<th class="w-auto px-3 py-3 text-left">{translate('common.summary')}</th>
</TableHeaderRow>

{#each groups as group}
<TableRow class="hover:bg-interactive-table-hover">
<td class="px-3 py-3 text-left">
<div class="flex flex-col gap-1 capitalize">
{group.category}
</div>
</td>
<td class="px-3 py-3 text-left">
<Badge type={getBadgeType(group.finalClassification)} class="text-xs">
{group.finalClassification}
</Badge>
</td>
<td class="px-3 py-3 text-left">
<div class="flex items-center gap-2">
<Icon name="clock" class="h-3 w-3 text-secondary/60" />
<span class="truncate text-sm">
{formatDate(group.eventTime, $timeFormat, {
relative: $relativeTime,
})}
</span>
</div>
</td>
<td class="px-3 py-3 text-left">
{#if group.userMetadata?.summary}
<MetadataDecoder
value={group.userMetadata.summary}
fallback={translate('events.decode-failed')}
let:decodedValue
>
<span class="font-mono text-sm text-secondary"
>{decodedValue}</span
>
</MetadataDecoder>
{:else}
<span class="font-mono text-sm text-secondary">-</span>
{/if}
</td>
</TableRow>
{/each}
</Table>
</div>
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
<script lang="ts">
import { page } from '$app/stores';
import { onMount } from 'svelte';
import { page } from '$app/state';
import AccordionLight from '$lib/holocene/accordion/accordion-light.svelte';
import Button from '$lib/holocene/button.svelte';
import Icon from '$lib/holocene/icon/icon.svelte';
import Markdown from '$lib/holocene/monaco/markdown.svelte';
import Tooltip from '$lib/holocene/tooltip.svelte';
import { translate } from '$lib/i18n/translate';
import { getWorkflowMetadata } from '$lib/services/query-service';
import { authUser } from '$lib/stores/auth-user';
import { workflowRun } from '$lib/stores/workflow-run';
$: ({ namespace } = $page.params);
$: ({ workflow } = $workflowRun);
$: currentDetails = $workflowRun?.metadata?.currentDetails || '';
$: closedWithoutDetails = !workflow.isRunning && !currentDetails;
const { namespace } = $derived(page.params);
const { workflow } = $derived($workflowRun);
const currentDetails = $derived($workflowRun?.metadata?.currentDetails || '');
let loading = false;
let loading = $state(false);
const fetchCurrentDetails = async () => {
if (loading) return;
loading = true;
try {
const { settings } = $page.data;
const { settings } = page.data;
const metadata = await getWorkflowMetadata(
{
namespace,
Expand All @@ -41,34 +41,47 @@
loading = false;
}
};
onMount(() => {
fetchCurrentDetails();
});
const handleKeydown = (event) => {
if (event.key === 'r' || event.key === 'R') {
event.preventDefault();
fetchCurrentDetails();
}
};
</script>

<AccordionLight
let:open
onToggle={closedWithoutDetails ? fetchCurrentDetails : undefined}
icon={closedWithoutDetails ? 'retry' : undefined}
>
<div slot="title" class="flex w-full items-center gap-2 p-2 text-xl">
<Icon name="flag" class="text-brand" width={32} height={32} />
{translate('workflows.current-details')}
{#if loading}{translate('common.loading')}{/if}
<svelte:window onkeydown={handleKeydown} />

<div class="flex h-full flex-1 flex-col border-l border-subtle">
<div class="surface-information w-full px-6 py-2">
<p class="hidden sm:block">
Press the <span
class="mx-1 rounded bg-subtle px-1 text-sm font-medium leading-4"
>R</span
> for freshness.
</p>
<div class="flex items-center sm:hidden">
<p>Press for freshness</p>
<Button variant="ghost" on:click={fetchCurrentDetails} disabled={loading}>
<Icon name="retry" />
</Button>
</div>
</div>
{#if open}
<div
class="surface-background flex h-full flex-col justify-between gap-2 p-6"
>
<div class="flex flex-col gap-2">
<h3 class="pl-6 pt-6">{translate('workflows.current-details')}</h3>
</div>
{#key currentDetails}
<Markdown content={currentDetails} />
<Markdown
className="p-3"
overrideTheme="background"
content={currentDetails}
/>
{/key}
{/if}
<svelte:fragment slot="action">
{#if workflow.isRunning}
<Tooltip text={translate('workflows.update-details')} left>
<Button
variant="ghost"
on:click={fetchCurrentDetails}
disabled={loading}
>
<Icon name="retry" />
</Button>
</Tooltip>
{/if}
</svelte:fragment>
</AccordionLight>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
<script lang="ts">
import AccordionLight from '$lib/holocene/accordion/accordion-light.svelte';
import Icon from '$lib/holocene/icon/icon.svelte';
import Markdown from '$lib/holocene/monaco/markdown.svelte';
import { translate } from '$lib/i18n/translate';
import { workflowRun } from '$lib/stores/workflow-run';

$: summary = $workflowRun?.userMetadata?.summary;
$: details = $workflowRun?.userMetadata?.details;
$: hasUserMetadata = summary || details;
const summary = $derived($workflowRun?.userMetadata?.summary);
const details = $derived($workflowRun?.userMetadata?.details);
</script>

{#if hasUserMetadata}
<AccordionLight let:open>
<div slot="title" class="flex w-full items-center gap-2 p-2 text-xl">
<Icon name="info" class="text-brand" width={32} height={32} />{translate(
'workflows.summary-and-details',
)}
</div>
{#if open && summary}
<h3>{translate('workflows.summary')}</h3>
<Markdown content={summary} />
<div class="flex min-h-full flex-1 flex-col gap-2 p-6">
<div class="border border-subtle">
<h3 class="pl-6 pt-6" data-testid="user-metadata-summary-heading">
{translate('workflows.summary')}
</h3>
{#if summary}
<Markdown className="p-3" overrideTheme="primary" content={summary} />
{:else}
<div class="pb-6 pl-6 text-secondary/70">
<p class="text-sm italic">
{translate('workflows.no-summary-available')}
</p>
</div>
{/if}
{#if open && details}
<h3>{translate('workflows.details')}</h3>
<Markdown content={details} />
</div>
<div class="border border-subtle">
<h3 class="pl-6 pt-6" data-testid="user-metadata-details-heading">
{translate('workflows.details')}
</h3>
{#if details}
<Markdown className="p-3" overrideTheme="primary" content={details} />
{:else}
<div class="pb-6 pl-6 text-secondary/70">
<p class="text-sm italic">
{translate('workflows.no-details-available')}
</p>
</div>
{/if}
</AccordionLight>
{/if}
</div>
</div>
4 changes: 1 addition & 3 deletions src/lib/holocene/empty-state.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
class="my-12 flex w-full flex-col items-center justify-start gap-2 text-primary {$$props.class}"
data-testid={$$props.testId}
>
<span
class="surface-secondary flex h-16 w-16 items-center justify-center rounded-full"
>
<span class=" flex h-16 w-16 items-center justify-center rounded-full">
<Icon name={icon} class="block h-full w-full" /></span
>
<p class="text-xl font-medium">{title}</p>
Expand Down
12 changes: 10 additions & 2 deletions src/lib/holocene/monaco/markdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
import { useDarkMode } from '$lib/utilities/dark-mode';
export let content: string;
export let className: string = '';
export let overrideTheme:
| 'background'
| 'primary'
| 'info'
| 'details'
| ''
| undefined = '';
let iframe;
Expand Down Expand Up @@ -40,13 +48,13 @@
const templatedContent = replaceTemplate(content);
</script>

<section class="h-full w-full" in:fade={{ duration: 1000 }}>
<section class={`h-full w-full ${className}`} in:fade={{ duration: 1000 }}>
{#key theme}
<iframe
bind:this={iframe}
on:load={resizeIframe}
title="output"
src="/render?content={encodeURIComponent(templatedContent)}&theme={theme}"
src={`/render?content=${encodeURIComponent(templatedContent)}&theme=${theme}&overrideTheme=${overrideTheme}`}
class="w-full"
></iframe>
{/key}
Expand Down
3 changes: 3 additions & 0 deletions src/lib/i18n/locales/en/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,7 @@ export const Strings = {
'event-types': 'Event Types',
'decode-failed': 'Decoding failed',
'view-raw-history': 'View Raw History',
'empty-search-attributes': 'No Search Attributes Found',
'empty-memo-attributes': 'No Memo Attributes Found',
'empty-header-attributes': 'No Header Attributes Found',
} as const;
Loading
Loading