From 47cb0a2cc969da6edfbe2d159ab1de1f07dd17cb Mon Sep 17 00:00:00 2001 From: waleed Date: Mon, 2 Feb 2026 23:44:22 -0800 Subject: [PATCH] fix(formatting): return null for missing values, strip trailing zeros --- apps/sim/app/workspace/[workspaceId]/logs/utils.ts | 2 +- .../[workflowId]/components/terminal/terminal.tsx | 6 +++--- .../background/workspace-notification-delivery.ts | 6 +++--- apps/sim/lib/core/utils/formatting.ts | 14 +++++++++----- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts index 1a35685c8..570262d10 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts +++ b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts @@ -370,7 +370,7 @@ export function mapToExecutionLogAlt(log: RawLogResponse): ExecutionLog { */ export function formatLatency(ms: number): string { if (!Number.isFinite(ms) || ms <= 0) return '—' - return formatDuration(ms, { precision: 2 }) + return formatDuration(ms, { precision: 2 }) ?? '—' } export const formatDate = (dateString: string) => { diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/terminal.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/terminal.tsx index c357d8c80..540f97bba 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/terminal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/terminal.tsx @@ -128,7 +128,7 @@ const BlockRow = memo(function BlockRow({ @@ -201,7 +201,7 @@ const IterationNodeRow = memo(function IterationNodeRow({ @@ -314,7 +314,7 @@ const SubflowNodeRow = memo(function SubflowNodeRow({ diff --git a/apps/sim/background/workspace-notification-delivery.ts b/apps/sim/background/workspace-notification-delivery.ts index 68bfa2fe8..0d9a8254b 100644 --- a/apps/sim/background/workspace-notification-delivery.ts +++ b/apps/sim/background/workspace-notification-delivery.ts @@ -297,7 +297,7 @@ async function deliverEmail( workflowName: payload.data.workflowName || 'Unknown Workflow', status: payload.data.status, trigger: payload.data.trigger, - duration: formatDuration(payload.data.totalDurationMs, { precision: 1 }), + duration: formatDuration(payload.data.totalDurationMs, { precision: 1 }) ?? '-', cost: formatCost(payload.data.cost), logUrl, alertReason, @@ -310,7 +310,7 @@ async function deliverEmail( to: subscription.emailRecipients, subject, html, - text: `${subject}\n${alertReason ? `\nReason: ${alertReason}\n` : ''}\nWorkflow: ${payload.data.workflowName}\nStatus: ${statusText}\nTrigger: ${payload.data.trigger}\nDuration: ${formatDuration(payload.data.totalDurationMs, { precision: 1 })}\nCost: ${formatCost(payload.data.cost)}\n\nView Log: ${logUrl}${includedDataText}`, + text: `${subject}\n${alertReason ? `\nReason: ${alertReason}\n` : ''}\nWorkflow: ${payload.data.workflowName}\nStatus: ${statusText}\nTrigger: ${payload.data.trigger}\nDuration: ${formatDuration(payload.data.totalDurationMs, { precision: 1 }) ?? '-'}\nCost: ${formatCost(payload.data.cost)}\n\nView Log: ${logUrl}${includedDataText}`, emailType: 'notifications', }) @@ -370,7 +370,7 @@ async function deliverSlack( { type: 'mrkdwn', text: `*Trigger:*\n${payload.data.trigger}` }, { type: 'mrkdwn', - text: `*Duration:*\n${formatDuration(payload.data.totalDurationMs, { precision: 1 })}`, + text: `*Duration:*\n${formatDuration(payload.data.totalDurationMs, { precision: 1 }) ?? '-'}`, }, { type: 'mrkdwn', text: `*Cost:*\n${formatCost(payload.data.cost)}` }, ], diff --git a/apps/sim/lib/core/utils/formatting.ts b/apps/sim/lib/core/utils/formatting.ts index 0e6dcd016..a7051df03 100644 --- a/apps/sim/lib/core/utils/formatting.ts +++ b/apps/sim/lib/core/utils/formatting.ts @@ -156,15 +156,15 @@ export function formatCompactTimestamp(iso: string): string { * Format a duration to a human-readable format * @param duration - Duration in milliseconds (number) or as string (e.g., "500ms") * @param options - Optional formatting options - * @param options.precision - Number of decimal places for seconds (default: 0) - * @returns A formatted duration string + * @param options.precision - Number of decimal places for seconds (default: 0), trailing zeros are stripped + * @returns A formatted duration string, or null if input is null/undefined */ export function formatDuration( duration: number | string | undefined | null, options?: { precision?: number } -): string { +): string | null { if (duration === undefined || duration === null) { - return '-' + return null } // Parse string durations (e.g., "500ms", "0.44ms", "1234") @@ -192,7 +192,11 @@ export function formatDuration( const seconds = ms / 1000 if (seconds < 60) { - return precision > 0 ? `${seconds.toFixed(precision)}s` : `${Math.floor(seconds)}s` + if (precision > 0) { + // Strip trailing zeros (e.g., "5.00s" -> "5s", "5.10s" -> "5.1s") + return `${seconds.toFixed(precision).replace(/\.?0+$/, '')}s` + } + return `${Math.floor(seconds)}s` } const minutes = Math.floor(seconds / 60)