From 8450e060d805e985624a79b0edf12a3195684582 Mon Sep 17 00:00:00 2001 From: lordspline <74811063+lordspline@users.noreply.github.com> Date: Fri, 19 Jun 2026 04:41:56 +0000 Subject: [PATCH 1/2] Show actual previous-period date in insight tooltips Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- .../insightTooltipUtils.test.ts | 12 ++- .../InsightTooltip/insightTooltipUtils.tsx | 6 +- .../insights/views/LineGraph/LineGraph.tsx | 45 ++++++---- .../views/LineGraph/tooltip-data.test.ts | 89 +++++++++++++++++++ .../insights/views/LineGraph/tooltip-data.ts | 27 +++++- 5 files changed, 155 insertions(+), 24 deletions(-) create mode 100644 frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts diff --git a/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.test.ts b/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.test.ts index 6ee24c25a965..39f4787fa416 100644 --- a/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.test.ts +++ b/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.test.ts @@ -1,4 +1,4 @@ -import { getFormattedDate } from 'scenes/insights/InsightTooltip/insightTooltipUtils' +import { formatCompareLabelWithDate, getFormattedDate } from 'scenes/insights/InsightTooltip/insightTooltipUtils' import { IntervalType } from '~/types' @@ -157,3 +157,13 @@ describe('getFormattedDate', () => { }) }) }) + +describe('formatCompareLabelWithDate', () => { + it('appends the actual period date when present', () => { + expect(formatCompareLabelWithDate('previous', '3 Jun 2024')).toBe('Previous (3 Jun 2024)') + }) + + it('keeps the existing label when no date is available', () => { + expect(formatCompareLabelWithDate('previous')).toBe('Previous') + }) +}) diff --git a/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.tsx b/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.tsx index cc7265785d62..af5a8425ff27 100644 --- a/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.tsx +++ b/frontend/src/scenes/insights/InsightTooltip/insightTooltipUtils.tsx @@ -115,6 +115,10 @@ export const INTERVAL_UNIT_TO_DAYJS_FORMAT: Record = { month: 'MMMM YYYY', } +export function formatCompareLabelWithDate(label: string, dateLabel?: string): string { + return `${capitalizeFirstLetter(label)}${dateLabel ? ` (${dateLabel})` : ''}` +} + const INTERVAL_UNIT_TO_DAYJS_FORMAT_SHORT: Record = { second: 'D MMM HH:mm:ss', minute: 'D MMM HH:mm', @@ -207,7 +211,7 @@ function getPillValues( if (s.compare_label) { const formattedLabel = formatCompareLabel ? formatCompareLabel(String(s.compare_label), s.date_label) - : capitalizeFirstLetter(String(s.compare_label)) + : formatCompareLabelWithDate(String(s.compare_label), s.date_label) pillValues.push(formattedLabel) } return pillValues diff --git a/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx b/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx index 345c6c994205..e3201e952f76 100644 --- a/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx +++ b/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx @@ -344,7 +344,7 @@ export function LineGraph_({ const { aggregationLabel } = useValues(groupsModel) const { isDarkModeOn } = useValues(themeLogic) - const { baseCurrency } = useValues(teamLogic) + const { baseCurrency, weekStartDay } = useValues(teamLogic) const { insightProps, insight } = useValues(insightLogic) const { timezone, isTrends, isStickiness, isFunnels, breakdownFilter, interval, insightData } = useValues( @@ -850,25 +850,34 @@ export function LineGraph_({ const referenceDataPoint = tooltip.dataPoints[0] const dataset = processedDatasets[referenceDataPoint.datasetIndex] const date = dataset?.days?.[referenceDataPoint.dataIndex] - const seriesData = createTooltipData(tooltip.dataPoints, (dp) => { - // For stacked bar charts when shift is pressed, show only the hovered bar - if (isHighlightBarMode) { - return dp.datasetIndex === referenceDataPoint.datasetIndex - } + const seriesData = createTooltipData( + tooltip.dataPoints, + (dp) => { + // For stacked bar charts when shift is pressed, show only the hovered bar + if (isHighlightBarMode) { + return dp.datasetIndex === referenceDataPoint.datasetIndex + } - if (tooltipConfig?.filter) { - return tooltipConfig.filter(dp) - } + if (tooltipConfig?.filter) { + return tooltipConfig.filter(dp) + } - const hasDotted = - hasAnyDottedDataset && - dp.dataIndex - processedDatasets?.[dp.datasetIndex]?.data?.length >= - incompletenessOffsetFromEnd - return ( - dp.datasetIndex >= (hasDotted ? _datasets.length : 0) && - dp.datasetIndex < (hasDotted ? _datasets.length * 2 : _datasets.length) - ) - }) + const hasDotted = + hasAnyDottedDataset && + dp.dataIndex - processedDatasets?.[dp.datasetIndex]?.data?.length >= + incompletenessOffsetFromEnd + return ( + dp.datasetIndex >= (hasDotted ? _datasets.length : 0) && + dp.datasetIndex < (hasDotted ? _datasets.length * 2 : _datasets.length) + ) + }, + { + interval, + dateRange: insightData?.resolved_date_range, + timezone, + weekStartDay, + } + ) const referenceSeriesDatum = seriesData.find( (datum) => datum.datasetIndex === referenceDataPoint.datasetIndex && diff --git a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts new file mode 100644 index 000000000000..4d22743f7e97 --- /dev/null +++ b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts @@ -0,0 +1,89 @@ +import { TooltipItem } from 'lib/Chart' + +import { createTooltipData } from './tooltip-data' + +function tooltipItem(dataset: Record, dataIndex = 0, datasetIndex = 0): TooltipItem { + return { + dataIndex, + datasetIndex, + dataset, + } as TooltipItem +} + +describe('createTooltipData', () => { + it.each([ + ['day interval', '2024-06-03', 'day', 'UTC', '3 Jun 2024'], + ['month interval', '2024-02-01', 'month', 'UTC', 'February 2024'], + ['timezone boundary', '2024-04-28T23:30:00Z', 'day', 'Asia/Tokyo', '29 Apr 2024'], + ])('formats compare date labels for %s', (_, day, interval, timezone, expectedDateLabel) => { + const data = createTooltipData( + [ + tooltipItem({ + data: [10], + days: [day], + label: '$pageview', + compare: true, + compare_label: 'previous', + }), + ], + undefined, + { interval: interval as any, timezone } + ) + + expect(data[0].date_label).toBe(expectedDateLabel) + }) + + it('formats week interval labels as actual date ranges', () => { + const data = createTooltipData( + [ + tooltipItem({ + data: [10], + days: ['2024-04-28'], + label: '$pageview', + compare: true, + compare_label: 'previous', + }), + ], + undefined, + { interval: 'week', timezone: 'UTC' } + ) + + expect(data[0].date_label).toBe('28 Apr - 4 May 2024') + }) + + it('respects explicit date boundaries for weekly labels', () => { + const data = createTooltipData( + [ + tooltipItem({ + data: [10], + days: ['2024-04-30'], + label: '$pageview', + compare: true, + compare_label: 'current', + }), + ], + undefined, + { + interval: 'week', + timezone: 'UTC', + dateRange: { date_from: '2024-04-30', date_to: '2024-05-02' }, + } + ) + + expect(data[0].date_label).toBe('30 Apr - 2 May 2024') + }) + + it('falls back to backend labels when a dataset has no day values', () => { + const data = createTooltipData([ + tooltipItem({ + data: [10], + labels: ['3-Jun-2024'], + label: '$pageview', + compare: true, + compare_label: 'previous', + }), + ]) + + expect(data[0].date_label).toBe('3-Jun-2024') + }) +}) diff --git a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts index b0abe2efc84e..dd63800c78fd 100644 --- a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts +++ b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts @@ -1,11 +1,20 @@ import { TooltipItem } from 'lib/Chart' -import { SeriesDatum } from 'scenes/insights/InsightTooltip/insightTooltipUtils' +import { getFormattedDate, SeriesDatum } from 'scenes/insights/InsightTooltip/insightTooltipUtils' -import { GraphDataset } from '~/types' +import { DateRange } from '~/queries/schema/schema-general' +import { GraphDataset, IntervalType } from '~/types' + +export interface TooltipDataOptions { + interval?: IntervalType | null + dateRange?: DateRange | null + timezone?: string + weekStartDay?: number +} export function createTooltipData( tooltipDataPoints: TooltipItem[], - filterFn?: (s: SeriesDatum) => boolean + filterFn?: (s: SeriesDatum) => boolean, + options?: TooltipDataOptions ): SeriesDatum[] { if (!tooltipDataPoints) { return [] @@ -13,6 +22,16 @@ export function createTooltipData( let data = tooltipDataPoints .map((dp, idx) => { const pointDataset = (dp?.dataset ?? {}) as GraphDataset + const date = pointDataset?.days?.[dp.dataIndex] + const dateLabel = + typeof date === 'string' + ? getFormattedDate(date, { + interval: options?.interval, + dateRange: options?.dateRange, + timezone: options?.timezone, + weekStartDay: options?.weekStartDay, + }) + : (pointDataset?.labels?.[dp.dataIndex] ?? undefined) return { id: idx, dataIndex: dp.dataIndex, @@ -27,7 +46,7 @@ export function createTooltipData( compare_label: pointDataset?.compare_label ?? pointDataset?.compareLabels?.[dp.dataIndex] ?? undefined, action: pointDataset?.action ?? pointDataset?.actions?.[dp.dataIndex] ?? undefined, label: pointDataset?.label ?? pointDataset.labels?.[dp.dataIndex] ?? undefined, - date_label: pointDataset?.labels?.[dp.dataIndex] ?? undefined, + date_label: dateLabel, order: pointDataset?.order ?? 0, color: Array.isArray(pointDataset.borderColor) ? pointDataset.borderColor?.[dp.dataIndex] From 30201d0713427ebd4229a9d6945ca4f182dc625f Mon Sep 17 00:00:00 2001 From: lordspline <74811063+lordspline@users.noreply.github.com> Date: Fri, 19 Jun 2026 05:20:53 +0000 Subject: [PATCH 2/2] fix(insights): use compare range for tooltip dates Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- .../insights/views/LineGraph/LineGraph.tsx | 1 + .../views/LineGraph/tooltip-data.test.ts | 39 +++++++++++++++++++ .../insights/views/LineGraph/tooltip-data.ts | 10 +++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx b/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx index e3201e952f76..5c5d26d88fa5 100644 --- a/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx +++ b/frontend/src/scenes/insights/views/LineGraph/LineGraph.tsx @@ -874,6 +874,7 @@ export function LineGraph_({ { interval, dateRange: insightData?.resolved_date_range, + compareDateRange: insightData?.resolved_compare_date_range, timezone, weekStartDay, } diff --git a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts index 4d22743f7e97..d9279338817c 100644 --- a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts +++ b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.test.ts @@ -73,6 +73,29 @@ describe('createTooltipData', () => { expect(data[0].date_label).toBe('30 Apr - 2 May 2024') }) + it('uses the compare date range for previous weekly labels', () => { + const data = createTooltipData( + [ + tooltipItem({ + data: [10], + days: ['2024-06-03'], + label: '$pageview', + compare: true, + compare_label: 'previous', + }), + ], + undefined, + { + interval: 'week', + timezone: 'UTC', + dateRange: { date_from: '2024-06-06', date_to: '2024-06-12' }, + compareDateRange: { date_from: '2024-05-30', date_to: '2024-06-05' }, + } + ) + + expect(data[0].date_label).toBe('2-5 Jun 2024') + }) + it('falls back to backend labels when a dataset has no day values', () => { const data = createTooltipData([ tooltipItem({ @@ -86,4 +109,20 @@ describe('createTooltipData', () => { expect(data[0].date_label).toBe('3-Jun-2024') }) + + it('falls back to backend labels when formatting options are omitted', () => { + const data = createTooltipData([ + tooltipItem( + { + data: [10, 20], + days: ['2024-06-03', '2024-06-04'], + labels: ['Pageview', 'Signup'], + compareLabels: ['previous', 'current'], + }, + 1 + ), + ]) + + expect(data[0].date_label).toBe('Signup') + }) }) diff --git a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts index dd63800c78fd..72f15a38f488 100644 --- a/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts +++ b/frontend/src/scenes/insights/views/LineGraph/tooltip-data.ts @@ -7,6 +7,7 @@ import { GraphDataset, IntervalType } from '~/types' export interface TooltipDataOptions { interval?: IntervalType | null dateRange?: DateRange | null + compareDateRange?: DateRange | null timezone?: string weekStartDay?: number } @@ -23,11 +24,14 @@ export function createTooltipData( .map((dp, idx) => { const pointDataset = (dp?.dataset ?? {}) as GraphDataset const date = pointDataset?.days?.[dp.dataIndex] + const compareLabel = pointDataset?.compare_label ?? pointDataset?.compareLabels?.[dp.dataIndex] ?? undefined + const dateRange = + compareLabel === 'previous' ? (options?.compareDateRange ?? options?.dateRange) : options?.dateRange const dateLabel = - typeof date === 'string' + typeof date === 'string' && options ? getFormattedDate(date, { interval: options?.interval, - dateRange: options?.dateRange, + dateRange, timezone: options?.timezone, weekStartDay: options?.weekStartDay, }) @@ -43,7 +47,7 @@ export function createTooltipData( pointDataset?.breakdownLabels?.[dp.dataIndex] ?? pointDataset?.breakdownValues?.[dp.dataIndex] ?? undefined, - compare_label: pointDataset?.compare_label ?? pointDataset?.compareLabels?.[dp.dataIndex] ?? undefined, + compare_label: compareLabel, action: pointDataset?.action ?? pointDataset?.actions?.[dp.dataIndex] ?? undefined, label: pointDataset?.label ?? pointDataset.labels?.[dp.dataIndex] ?? undefined, date_label: dateLabel,