diff --git a/apps/dashboard/src/components/analytics/charts/workflow-runs-trend-chart.tsx b/apps/dashboard/src/components/analytics/charts/workflow-runs-trend-chart.tsx index 18909076904..629ceaa1de9 100644 --- a/apps/dashboard/src/components/analytics/charts/workflow-runs-trend-chart.tsx +++ b/apps/dashboard/src/components/analytics/charts/workflow-runs-trend-chart.tsx @@ -1,6 +1,6 @@ import { FeatureFlagsKeysEnum } from '@novu/shared'; import { ArrowRight } from 'lucide-react'; -import { useCallback, useId, useMemo } from 'react'; +import { useCallback, useId, useMemo, type ComponentProps } from 'react'; import { Link } from 'react-router-dom'; import { Area, ComposedChart, XAxis, YAxis } from 'recharts'; import { type WorkflowRunsTrendDataPoint } from '../../../api/activity'; @@ -14,6 +14,31 @@ import { type WorkflowRunsChartData } from './chart-types'; import { ChartWrapper } from './chart-wrapper'; import { FlickeringGrid } from './flickering-grid'; +function periodHasWorkflowErrors(points: WorkflowRunsTrendDataPoint[] | undefined): boolean { + if (!points?.length) { + return false; + } + + return points.some((p) => (p.error ?? 0) > 0); +} + +function WorkflowRunsChartTooltip({ + omitDataKeys, + ...props +}: ComponentProps & { omitDataKeys?: readonly string[] }) { + const filteredPayload = useMemo(() => { + if (!omitDataKeys?.length || !props.payload) { + return props.payload; + } + + const omit = new Set(omitDataKeys); + + return props.payload.filter((item) => !omit.has(String(item.dataKey))); + }, [omitDataKeys, props.payload]); + + return ; +} + type WorkflowRunsChartDataWithTotal = WorkflowRunsChartData & { total: number }; const CHART_HEIGHT = 180; @@ -100,9 +125,17 @@ type ChartContentParams = { config: ChartConfig; seriesKeys: readonly string[]; baseId: string; + omitTooltipDataKeys?: readonly string[]; }; -function renderWorkflowRunsChartContent({ data, includeTooltip, config, seriesKeys, baseId }: ChartContentParams) { +function renderWorkflowRunsChartContent({ + data, + includeTooltip, + config, + seriesKeys, + baseId, + omitTooltipDataKeys, +}: ChartContentParams) { return (
@@ -143,7 +176,18 @@ function renderWorkflowRunsChartContent({ data, includeTooltip, config, seriesKe padding={{ left: 8, right: 8 }} /> - {includeTooltip && } />} + {includeTooltip && ( + + ) : ( + + ) + } + /> + )} {seriesKeys.map((key) => { const entry = config[key as keyof typeof config]; if (!entry || !('color' in entry)) return null; @@ -223,7 +267,30 @@ function WorkflowRunsTrendChartInner({ error, }: WorkflowRunsTrendChartProps & { variant: Variant }) { const baseId = useId(); - const { config, seriesKeys, getTotal } = VARIANT_CONFIG[variant]; + const { config: fullChartConfig, seriesKeys: allSeriesKeys, getTotal } = VARIANT_CONFIG[variant]; + + const showErrorSeries = useMemo(() => periodHasWorkflowErrors(data), [data]); + + const { chartConfig, seriesKeys, omitTooltipDataKeys } = useMemo(() => { + if (showErrorSeries) { + return { + chartConfig: fullChartConfig, + seriesKeys: allSeriesKeys, + omitTooltipDataKeys: undefined as readonly string[] | undefined, + }; + } + + const seriesKeysFiltered = allSeriesKeys.filter((key) => key !== 'error'); + const chartConfig = Object.fromEntries( + Object.entries(fullChartConfig).filter(([key]) => key !== 'error') + ) as ChartConfig; + + return { + chartConfig, + seriesKeys: seriesKeysFiltered, + omitTooltipDataKeys: ['error'] as const, + }; + }, [allSeriesKeys, fullChartConfig, showErrorSeries]); const chartData = useMemo( () => data?.map((p) => VARIANT_CONFIG[variant].mapDataPoint(p)) ?? undefined, @@ -246,11 +313,12 @@ function WorkflowRunsTrendChartInner({ renderWorkflowRunsChartContent({ data: chartDataToRender, includeTooltip, - config, + config: chartConfig, seriesKeys, baseId, + omitTooltipDataKeys, }), - [baseId, config, seriesKeys] + [baseId, chartConfig, omitTooltipDataKeys, seriesKeys] ); const renderEmptyState = useCallback( diff --git a/apps/dashboard/src/pages/domain-detail.tsx b/apps/dashboard/src/pages/domain-detail.tsx index 409f1288c39..4835576d6be 100644 --- a/apps/dashboard/src/pages/domain-detail.tsx +++ b/apps/dashboard/src/pages/domain-detail.tsx @@ -478,7 +478,7 @@ export function DomainDetailPage() { disabled={!canWriteDomains || updateDomainMeta.isPending} isPersisting={updateDomainMeta.isPending} spellCheck={false} - textareaClassName="font-code text-code-xs min-h-[120px] resize-y" + textareaClassName="font-code text-code-xs min-h-[120px]" /> )}