Skip to content

Commit 5235b8f

Browse files
gggritsoclaude
andcommitted
feat(dashboards): Enable heat map cross-navigation
Wire up opening a dashboard heat map widget in Explore (getWidgetMetricsUrl maps DisplayType.HEATMAP -> ChartType.HEATMAP) and adding an Explore heat map to a dashboard (useAddToDashboard maps ChartType.HEATMAP -> DisplayType.HEATMAP; useSaveAsMetricItems drops the heat-map guards). Adds the DisplayType.HEATMAP enum value as a prerequisite. Dormant behind the data-browsing-heat-map-widget flag. Split out of the heat map dashboard widget work so it can merge independently. Refs DAIN-1654 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 35c7844 commit 5235b8f

5 files changed

Lines changed: 37 additions & 16 deletions

File tree

static/app/views/dashboards/types.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export enum DisplayType {
5252
CATEGORICAL_BAR = 'categorical_bar',
5353
AGENTS_TRACES_TABLE = 'agents_traces_table',
5454
TEXT = 'text',
55+
HEATMAP = 'heatmap',
5556
}
5657

5758
export enum WidgetType {

static/app/views/dashboards/utils/getWidgetMetricsUrl.spec.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,34 @@ describe('getWidgetMetricsUrl', () => {
444444
const metricQuery = JSON.parse(metrics[0]!);
445445
expect(metricQuery.aggregateFields[0].chartType).toBe(ChartType.AREA);
446446
});
447+
448+
it('maps HEATMAP display type to HEATMAP chart type', () => {
449+
const widget: Widget = {
450+
id: '1',
451+
title: 'Heat Map',
452+
displayType: DisplayType.HEATMAP,
453+
interval: '5m',
454+
widgetType: WidgetType.TRACEMETRICS,
455+
queries: [
456+
{
457+
name: 'Query 1',
458+
fields: [],
459+
aggregates: ['count(value,duration,d,none)'],
460+
columns: [],
461+
conditions: '',
462+
orderby: '',
463+
fieldAliases: [],
464+
},
465+
],
466+
};
467+
468+
const url = getWidgetMetricsUrl(widget, undefined, selection, organization);
469+
const {params} = parseMetricsUrl(url);
470+
471+
const metrics = Array.isArray(params.metric) ? params.metric : [params.metric];
472+
const metricQuery = JSON.parse(metrics[0]!);
473+
expect(metricQuery.aggregateFields[0].chartType).toBe(ChartType.HEATMAP);
474+
});
447475
});
448476

449477
it('handles empty query conditions', () => {

static/app/views/dashboards/utils/getWidgetMetricsUrl.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ function getChartTypeFromDisplayType(displayType: DisplayType): ChartType {
127127
return ChartType.AREA;
128128
case DisplayType.BAR:
129129
return ChartType.BAR;
130+
case DisplayType.HEATMAP:
131+
return ChartType.HEATMAP;
130132
case DisplayType.TABLE:
131133
case DisplayType.BIG_NUMBER:
132134
default:

static/app/views/explore/hooks/useAddToDashboard.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ export const CHART_TYPE_TO_DISPLAY_TYPE: Record<ChartType, DisplayType> = {
3030
[ChartType.LINE]: DisplayType.LINE,
3131
[ChartType.BAR]: DisplayType.BAR,
3232
[ChartType.AREA]: DisplayType.AREA,
33-
// Heatmaps are filtered out before reaching dashboard code, but the
34-
// mapping must be exhaustive because other consumers index by ChartType.
35-
[ChartType.HEATMAP]: DisplayType.LINE,
33+
[ChartType.HEATMAP]: DisplayType.HEATMAP,
3634
};
3735

3836
export function useAddToDashboard() {

static/app/views/explore/metrics/useSaveAsMetricItems.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import {
2929
} from 'sentry/views/explore/queryParams/visualize';
3030
import {getVisualizeLabel} from 'sentry/views/explore/toolbar/toolbarVisualize';
3131
import {TraceItemDataset} from 'sentry/views/explore/types';
32-
import {ChartType} from 'sentry/views/insights/common/components/chart';
3332
import {getAlertsUrl} from 'sentry/views/insights/common/utils/getAlertsUrl';
3433

3534
import {
@@ -197,14 +196,10 @@ export function useSaveAsMetricItems(options: UseSaveAsMetricItemsOptions) {
197196
addToDashboard(
198197
metricQueries.filter(
199198
metricQuery =>
200-
metricQuery.queryParams.visualizes[0]?.chartType !==
201-
ChartType.HEATMAP &&
202199
// Allow all charts if you have the flag, otherwise only allow non-equation charts without the flag
203-
(metricsEquationsInDashboardsEnabled ||
204-
(!metricsEquationsInDashboardsEnabled &&
205-
!isVisualizeEquation(
206-
metricQuery.queryParams.visualizes[0]!
207-
)))
200+
metricsEquationsInDashboardsEnabled ||
201+
(!metricsEquationsInDashboardsEnabled &&
202+
!isVisualizeEquation(metricQuery.queryParams.visualizes[0]!))
208203
)
209204
);
210205
},
@@ -214,8 +209,7 @@ export function useSaveAsMetricItems(options: UseSaveAsMetricItemsOptions) {
214209
...metricQueries.map((metricQuery, index) => {
215210
const visualize = metricQuery.queryParams.visualizes[0]!;
216211
const isUnsupported =
217-
(!metricsEquationsInDashboardsEnabled && isVisualizeEquation(visualize)) ||
218-
visualize.chartType === ChartType.HEATMAP;
212+
!metricsEquationsInDashboardsEnabled && isVisualizeEquation(visualize);
219213
const label = isVisualizeFunction(visualize)
220214
? `${metricQuery.label ?? getVisualizeLabel(index, isVisualizeEquation(visualize))}: ${
221215
formatTraceMetricsFunction(
@@ -238,9 +232,7 @@ export function useSaveAsMetricItems(options: UseSaveAsMetricItemsOptions) {
238232
tooltip:
239233
!metricsEquationsInDashboardsEnabled && isVisualizeEquation(visualize)
240234
? t('Equations cannot currently be added to a dashboard')
241-
: visualize.chartType === ChartType.HEATMAP
242-
? t('Heat maps cannot currently be added to a dashboard')
243-
: undefined,
235+
: undefined,
244236
};
245237
}),
246238
],

0 commit comments

Comments
 (0)