Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Metadata for Activity and Timers #2529

Merged
merged 18 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions src/lib/components/event/event-details-full.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import EventDetailsRowExpanded from './event-details-row-expanded.svelte';
import EventLinksExpanded from './event-links-expanded.svelte';
import EventMetadataExpanded from './event-metadata-expanded.svelte';

export let group: EventGroup | undefined = undefined;
export let event: WorkflowEvent | undefined = undefined;
Expand Down Expand Up @@ -45,6 +46,9 @@
})}
</div>
</div>
{#if groupEvent?.userMetadata?.summary}
<EventMetadataExpanded value={groupEvent.userMetadata.summary} />
{/if}
<EventLinksExpanded links={groupEvent?.links} />
{#each details as [key, value] (key)}
<EventDetailsRowExpanded {key} {value} {attributes} />
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/event/event-details-link.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
export let value: string;
export let attributes: CombinedAttributes;
export let type: EventLinkType;
export let light = false;

$: ({ workflow, namespace } = $page.params);

Expand All @@ -40,6 +39,6 @@
$: href = hrefs[type];
</script>

<Link class={$$restProps.class} {href} {light}>
<Link class={$$restProps.class} {href}>
{value}
</Link>
37 changes: 37 additions & 0 deletions src/lib/components/event/event-metadata-expanded.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script lang="ts">
import Badge from '$lib/holocene/badge.svelte';
import type { Payload } from '$lib/types';

import MetadataDecoder from './metadata-decoder.svelte';

export let value: Payload;
</script>

<div class="flex {$$props.class}">
<div class="content code-block-row">
<div class="flex flex-col">
<p class="text-sm">Summary</p>
<MetadataDecoder {value} fallback="" let:decodedValue>
Alex-Tideman marked this conversation as resolved.
Show resolved Hide resolved
{#if decodedValue}
<Badge type="secondary" class="block select-none truncate">
{decodedValue}
</Badge>
{/if}
</MetadataDecoder>
</div>
</div>
</div>

<style lang="postcss">
.content {
@apply block w-full px-2 py-1 text-left;
}

.code-block-row {
@apply block w-full select-all py-1 text-left;
}

.detail-row {
@apply flex w-full items-center gap-2 py-1 text-left;
}
</style>
23 changes: 20 additions & 3 deletions src/lib/components/event/event-summary-row.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { page } from '$app/stores';

import Badge from '$lib/holocene/badge.svelte';
import Icon from '$lib/holocene/icon/icon.svelte';
import Link from '$lib/holocene/link.svelte';
import Tooltip from '$lib/holocene/tooltip.svelte';
Expand Down Expand Up @@ -35,6 +36,7 @@
import EventDetailsFull from './event-details-full.svelte';
import EventDetailsRow from './event-details-row.svelte';
import EventLink from './event-link.svelte';
import MetadataDecoder from './metadata-decoder.svelte';

export let event: IterableEvent;
export let group: EventGroup | undefined = undefined;
Expand Down Expand Up @@ -198,16 +200,31 @@
{/if}
</div>
{/if}
{#if currentEvent?.userMetadata?.summary}
<MetadataDecoder
value={currentEvent.userMetadata.summary}
fallback=""
Alex-Tideman marked this conversation as resolved.
Show resolved Hide resolved
let:decodedValue
>
{#if decodedValue}
<p class="whitespace-nowrap text-right text-xs">Summary</p>
<Badge type="secondary" class="block select-none truncate">
{decodedValue}
</Badge>
{:else}
<EventDetailsRow {...primaryAttribute} {attributes} />
{/if}
</MetadataDecoder>
{:else if primaryAttribute?.key}
<EventDetailsRow {...primaryAttribute} {attributes} />
{/if}
{#if currentEvent?.links?.length}
<EventLink
link={currentEvent.links[0]}
class="max-w-xl"
linkClass="truncate"
/>
{/if}
{#if primaryAttribute?.key}
<EventDetailsRow {...primaryAttribute} {attributes} />
{/if}
{#if nonPendingActivityAttempt}
<EventDetailsRow
key="attempt"
Expand Down
57 changes: 57 additions & 0 deletions src/lib/components/event/metadata-decoder.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script lang="ts">
import { page } from '$app/stores';

import type { Payload } from '$lib/types';
import { decodeSingleReadablePayloadWithCodec } from '$lib/utilities/decode-payload';
import {
getCodecEndpoint,
getCodecIncludeCredentials,
getCodecPassAccessToken,
} from '$lib/utilities/get-codec';

export let value: Payload | undefined = undefined;
export let fallback: string = '';
export let onDecode: (decodedValue: string) => void | undefined = undefined;

let decodedValue = fallback;

$: endpoint = getCodecEndpoint($page.data.settings);
$: passAccessToken = getCodecPassAccessToken($page.data.settings);
$: includeCredentials = getCodecIncludeCredentials($page.data.settings);
$: settings = {
...$page.data.settings,
codec: {
...$page.data.settings?.codec,
endpoint,
passAccessToken,
includeCredentials,
},
};

const decodePayload = async (_value: Payload | undefined) => {
if (!_value) {
return;
}

try {
const metadata = await decodeSingleReadablePayloadWithCodec(
_value,
settings,
);

if (typeof metadata === 'string') {
decodedValue = metadata;
}

if (onDecode) {
onDecode(decodedValue);
}
} catch (e) {
console.error('Could not decode payloads');
}
};

$: decodePayload(value);
</script>

<slot {decodedValue} />
Alex-Tideman marked this conversation as resolved.
Show resolved Hide resolved
80 changes: 2 additions & 78 deletions src/lib/components/lines-and-dots/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,10 @@ import type {
} from '$lib/types/events';
import type { WorkflowStatus } from '$lib/types/workflows';
import {
formatAttributes,
formatGroupAttributes,
formatPendingAttributes,
} from '$lib/utilities/format-event-attributes';
import {
getGroupForEventOrPendingEvent,
isAssociatedPendingActivity,
} from '$lib/utilities/pending-activities';

export const DetailsChildTimelineHeight = 200;
import { getGroupForEventOrPendingEvent } from '$lib/utilities/pending-activities';

export type GraphConfig = {
height: number;
Expand All @@ -34,8 +28,6 @@ export type GraphConfig = {

const baseRadius = 6;

export const minCompactWidth = 200;

export const TimelineConfig: GraphConfig = {
height: baseRadius * 5,
gutter: baseRadius * 8,
Expand Down Expand Up @@ -84,7 +76,7 @@ export const timelineTextPosition = (
let textAnchor = 'start';
let textIndex = 0;

const textToLeft = firstPoint > (1 / 3) * width;
const textToLeft = firstPoint > (1 / 2) * width;
let textToRight = !textToLeft && lastPoint < (2 / 3) * width && !isPending;

if (textToLeft) textAnchor = 'end';
Expand Down Expand Up @@ -267,25 +259,6 @@ export const getCategoryColor = (type: EventTypeCategory): string => {
}
};

export const activeGroupsHeightAboveGroup = (
activeGroups: string[],
group: EventGroup,
groups: EventGroups,
width: number,
sort: EventSortOrder,
) => {
return activeGroups
.filter((id) => {
if (sort === 'ascending') return parseInt(id) < parseInt(group.id);
return parseInt(id) > parseInt(group.id);
})
.map((id) => {
const group = groups.find((group) => group.id === id);
return getGroupDetailsBoxHeight(group, width);
})
.reduce((acc, height) => acc + height, 0);
};

export const mergeEventGroupDetails = (group: EventGroup) => {
const attributes = formatGroupAttributes(group);
return group.pendingActivity
Expand All @@ -295,55 +268,6 @@ export const mergeEventGroupDetails = (group: EventGroup) => {

export const staticCodeBlockHeight = 200;

export const getGroupDetailsBoxHeight = (group: EventGroup, width: number) => {
const isWide = width >= 960;
const attributes = mergeEventGroupDetails(group);
const codeBlockAttributes = Object.entries(attributes).filter(
([, value]) => typeof value === 'object',
);
const textAttributes = Object.entries(attributes).filter(
([, value]) => typeof value !== 'object',
);

const codeBlockHeight = codeBlockAttributes.length * staticCodeBlockHeight;
const textHeight =
(isWide ? 1 : 2) * textAttributes.length * DetailsConfig.fontSizeRatio +
DetailsConfig.fontSizeRatio;
const totalTextHeight =
group.category === 'child-workflow'
? textHeight + DetailsChildTimelineHeight
: textHeight;
return (
Math.max(codeBlockHeight, totalTextHeight) + 3 * DetailsConfig.fontSizeRatio
);
};

export const getEventDetailsBoxHeight = (
event: WorkflowEvent,
pendingActivity?: PendingActivity,
) => {
const attributes = formatAttributes(event);
const codeBlockAttributes = Object.entries(attributes).filter(
([, value]) => typeof value === 'object',
);
const textAttributes = Object.entries(attributes).filter(
([, value]) => typeof value !== 'object',
);

let pendingActivityHeight = 0;
if (isAssociatedPendingActivity(event, pendingActivity)) {
pendingActivityHeight = getPendingEventDetailHeight(pendingActivity);
}
const codeBlockHeight = codeBlockAttributes.length * staticCodeBlockHeight;
const textHeight = textAttributes.length * DetailsConfig.fontSizeRatio;
return (
pendingActivityHeight +
codeBlockHeight +
textHeight +
+2 * DetailsConfig.fontSizeRatio
);
};

export const getPendingEventDetailHeight = (event: PendingActivity) => {
const textHeight = 5 * DetailsConfig.fontSizeRatio;
let codeBlockHeight = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import Checkbox from '$lib/holocene/checkbox.svelte';
import { clearActiveEvents } from '$lib/stores/active-events';
import { clearActiveGroups } from '$lib/stores/active-events';
import { eventStatusFilter } from '$lib/stores/filters';

const options = [
Expand All @@ -11,7 +11,7 @@
];

const onOptionClick = () => {
clearActiveEvents();
clearActiveGroups();
$eventStatusFilter = !$eventStatusFilter;
};
</script>
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/lines-and-dots/event-type-filter.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
allEventTypeOptions,
compactEventTypeOptions,
} from '$lib/models/event-history/get-event-categorization';
import { clearActiveEvents } from '$lib/stores/active-events';
import { clearActiveGroups } from '$lib/stores/active-events';
import { eventTypeFilter } from '$lib/stores/filters';
import { temporalVersion } from '$lib/stores/versions';
import { nexusEnabled } from '$lib/utilities/nexus-enabled';
Expand Down Expand Up @@ -52,7 +52,7 @@
}

const onOptionClick = ({ value }) => {
clearActiveEvents();
clearActiveGroups();
$eventTypeFilter = $eventTypeFilter.some((type) => type === value)
? $eventTypeFilter.filter((type) => type !== value)
: [...$eventTypeFilter, value];
Expand Down
10 changes: 5 additions & 5 deletions src/lib/components/lines-and-dots/svg/graph-widget.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
export let namespace: string;
export let workflowId: string;
export let runId = '';
export let height = 400;
export let viewportHeight = 360;
export let onLoad: () => void = () => {};

const getWorkflowAndEventHistory = async () => {
const [workflow, history] = await Promise.all([
Expand All @@ -24,17 +25,16 @@
workflow: WorkflowExecution,
history: WorkflowEvents,
) => {
onLoad();
const pendingActivities = workflow?.pendingActivities ?? [];
return groupEvents(history, 'ascending', pendingActivities);
};
</script>

{#await getWorkflowAndEventHistory() then { workflow, history }}
<div
class="cursor-pointer overflow-auto {$$restProps.class}"
style="height: {height}px;"
>
<div class="cursor-pointer overflow-auto {$$restProps.class}">
<TimelineGraph
{viewportHeight}
{workflow}
groups={createGroups(workflow, history)}
readOnly
Expand Down
Loading
Loading