From e9e32d0630cd219c3bebbb95ae025ffb4b8b2f4d Mon Sep 17 00:00:00 2001 From: George Gritsouk <989898+gggritso@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:34:18 -0400 Subject: [PATCH 1/2] fix(dashboards): Rebalance chart interval options and defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace 15m with 10m, add 6h, and remove 1d from interval options to create a more even step progression (alternating 2x/3x multipliers). Rebalance MINIMUM and MAXIMUM interval ladders with new thresholds at 12h, 2d, and 4d for tighter duration bands. Default to second-biggest interval on dashboards so charts are smooth out of the box while still offering a hyper-granular option for power users. Previously, 90d at 3h produced 720 data points per chart, causing UI jank and moiré artifacts on bar charts. Now defaults stay in the 60–360 range across all durations. Refs DAIN-1376 Co-Authored-By: Claude Opus 4.6 --- static/app/components/charts/utils.tsx | 2 ++ static/app/utils/useChartInterval.spec.tsx | 8 ++--- static/app/utils/useChartInterval.tsx | 29 ++++++++++--------- .../app/views/dashboards/dashboard.spec.tsx | 28 +++++++++--------- static/app/views/dashboards/detail.tsx | 9 ++++-- .../components/widgetPreview.tsx | 9 ++++-- 6 files changed, 49 insertions(+), 36 deletions(-) diff --git a/static/app/components/charts/utils.tsx b/static/app/components/charts/utils.tsx index 182463bda435fb..05d960eedefbf0 100644 --- a/static/app/components/charts/utils.tsx +++ b/static/app/components/charts/utils.tsx @@ -27,8 +27,10 @@ export const SIXTY_DAYS = 86400; export const THIRTY_DAYS = 43200; export const TWO_WEEKS = 20160; export const ONE_WEEK = 10080; +export const FOUR_DAYS = 5760; export const FORTY_EIGHT_HOURS = 2880; export const TWENTY_FOUR_HOURS = 1440; +export const TWELVE_HOURS = 720; export const SIX_HOURS = 360; const THREE_HOURS = 180; export const ONE_HOUR = 60; diff --git a/static/app/utils/useChartInterval.spec.tsx b/static/app/utils/useChartInterval.spec.tsx index c599149b1f2cf2..ce8997d7327773 100644 --- a/static/app/utils/useChartInterval.spec.tsx +++ b/static/app/utils/useChartInterval.spec.tsx @@ -26,8 +26,7 @@ describe('useChartInterval', () => { expect(intervalOptions).toEqual([ {value: '1h', label: '1 hour'}, {value: '3h', label: '3 hours'}, - {value: '12h', label: '12 hours'}, - {value: '1d', label: '1 day'}, + {value: '6h', label: '6 hours'}, ]); expect(chartInterval).toBe('1h'); // default @@ -47,12 +46,11 @@ describe('useChartInterval', () => { expect(intervalOptions).toEqual([ {value: '1m', label: '1 minute'}, {value: '5m', label: '5 minutes'}, - {value: '15m', label: '15 minutes'}, ]); act(() => { - setChartInterval('15m'); + setChartInterval('5m'); }); - expect(chartInterval).toBe('15m'); + expect(chartInterval).toBe('5m'); }); }); diff --git a/static/app/utils/useChartInterval.tsx b/static/app/utils/useChartInterval.tsx index 93c8a06f916fdc..f07879ad8c912c 100644 --- a/static/app/utils/useChartInterval.tsx +++ b/static/app/utils/useChartInterval.tsx @@ -4,12 +4,13 @@ import type {Location} from 'history'; import { FIVE_MINUTES, FORTY_EIGHT_HOURS, + FOUR_DAYS, getDiffInMinutes, GranularityLadder, ONE_HOUR, - ONE_WEEK, SIX_HOURS, THIRTY_DAYS, + TWELVE_HOURS, TWO_WEEKS, } from 'sentry/components/charts/utils'; import {usePageFilters} from 'sentry/components/pageFilters/usePageFilters'; @@ -20,7 +21,7 @@ import {decodeScalar} from 'sentry/utils/queryString'; import {useLocation} from 'sentry/utils/useLocation'; import {useNavigate} from 'sentry/utils/useNavigate'; -enum ChartIntervalUnspecifiedStrategy { +export enum ChartIntervalUnspecifiedStrategy { /** Use the second biggest possible interval (e.g., pretty big buckets) */ USE_SECOND_BIGGEST = 'use_second_biggest', /** Use the smallest possible interval (e.g., the smallest possible buckets) */ @@ -104,12 +105,12 @@ function useChartIntervalImpl({ const ALL_INTERVAL_OPTIONS = [ {value: '1m', label: t('1 minute')}, {value: '5m', label: t('5 minutes')}, - {value: '15m', label: t('15 minutes')}, + {value: '10m', label: t('10 minutes')}, {value: '30m', label: t('30 minutes')}, {value: '1h', label: t('1 hour')}, {value: '3h', label: t('3 hours')}, + {value: '6h', label: t('6 hours')}, {value: '12h', label: t('12 hours')}, - {value: '1d', label: t('1 day')}, ]; /** @@ -119,19 +120,21 @@ const ALL_INTERVAL_OPTIONS = [ const MINIMUM_INTERVAL = new GranularityLadder([ [THIRTY_DAYS, '3h'], [TWO_WEEKS, '1h'], - [ONE_WEEK, '30m'], - [FORTY_EIGHT_HOURS, '15m'], - [SIX_HOURS, '5m'], + [FOUR_DAYS, '30m'], + [FORTY_EIGHT_HOURS, '10m'], + [TWELVE_HOURS, '5m'], + [SIX_HOURS, '1m'], [0, '1m'], ]); const MAXIMUM_INTERVAL = new GranularityLadder([ - [THIRTY_DAYS, '1d'], - [TWO_WEEKS, '1d'], - [ONE_WEEK, '12h'], - [FORTY_EIGHT_HOURS, '4h'], - [SIX_HOURS, '1h'], - [ONE_HOUR, '15m'], + [THIRTY_DAYS, '12h'], + [TWO_WEEKS, '6h'], + [FOUR_DAYS, '3h'], + [FORTY_EIGHT_HOURS, '1h'], + [TWELVE_HOURS, '30m'], + [SIX_HOURS, '10m'], + [ONE_HOUR, '5m'], [FIVE_MINUTES, '5m'], [0, '1m'], ]); diff --git a/static/app/views/dashboards/dashboard.spec.tsx b/static/app/views/dashboards/dashboard.spec.tsx index 2ba0775ceb9b62..025e58fe10981b 100644 --- a/static/app/views/dashboards/dashboard.spec.tsx +++ b/static/app/views/dashboards/dashboard.spec.tsx @@ -548,11 +548,11 @@ describe('Dashboards > Dashboard', () => { body: [], match: [MockApiClient.matchQuery({interval: '5m'})], }); - const hourlyIntervalMock = MockApiClient.addMockResponse({ + const thirtyMinuteMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-stats/', method: 'GET', body: [], - match: [MockApiClient.matchQuery({interval: '1h'})], + match: [MockApiClient.matchQuery({interval: '30m'})], }); // No interval in the URL — the 5m default is derived purely from the @@ -564,16 +564,16 @@ describe('Dashboards > Dashboard', () => { await screen.findByText('Test Spans Widget'); await waitFor(() => expect(fiveMinuteMock).toHaveBeenCalled()); - expect(hourlyIntervalMock).not.toHaveBeenCalled(); + expect(thirtyMinuteMock).not.toHaveBeenCalled(); - // Click the interval selector and choose '1 hour'. FiltersBar writes - // interval=1h to the URL, DashboardWithIntervalSelector re-renders with + // Click the interval selector and choose '30 minutes'. FiltersBar writes + // interval=30m to the URL, DashboardWithIntervalSelector re-renders with // the new widgetInterval, and the widget re-fetches with the new interval. await userEvent.click(screen.getByRole('button', {name: '5 minutes'})); - await userEvent.click(screen.getByRole('option', {name: '1 hour'})); + await userEvent.click(screen.getByRole('option', {name: '30 minutes'})); - await waitFor(() => expect(hourlyIntervalMock).toHaveBeenCalled()); - expect(router.location.query.interval).toBe('1h'); + await waitFor(() => expect(thirtyMinuteMock).toHaveBeenCalled()); + expect(router.location.query.interval).toBe('30m'); }); }); @@ -592,11 +592,11 @@ describe('Dashboards > Dashboard', () => { match: [MockApiClient.matchQuery({interval: '5m'})], }); - const hourlyIntervalMock = MockApiClient.addMockResponse({ + const tenMinuteMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-stats/', method: 'GET', body: [], - match: [MockApiClient.matchQuery({interval: '1h'})], + match: [MockApiClient.matchQuery({interval: '10m'})], }); const {router} = render(, { @@ -615,16 +615,16 @@ describe('Dashboards > Dashboard', () => { // Selecting a new interval updates the URL and triggers a re-fetch. await userEvent.click(screen.getByRole('button', {name: '30 minutes'})); - await userEvent.click(screen.getByRole('option', {name: '1 hour'})); + await userEvent.click(screen.getByRole('option', {name: '10 minutes'})); - await waitFor(() => expect(hourlyIntervalMock).toHaveBeenCalled()); - expect(router.location.query.interval).toBe('1h'); + await waitFor(() => expect(tenMinuteMock).toHaveBeenCalled()); + expect(router.location.query.interval).toBe('10m'); }); }); describe('URL interval not valid for the dashboard period', () => { beforeEach(() => { - // Override the outer 24h store setup — valid intervals for 30d are 3h, 12h, 1d. + // Override the outer 24h store setup — valid intervals for 30d are 3h, 6h, 12h. PageFiltersStore.init(); PageFiltersStore.onInitializeUrlState( getSavedFiltersAsPageFilters(thirtyDayDashboard) diff --git a/static/app/views/dashboards/detail.tsx b/static/app/views/dashboards/detail.tsx index 47aed9a222d246..f2e8b4b7cc7606 100644 --- a/static/app/views/dashboards/detail.tsx +++ b/static/app/views/dashboards/detail.tsx @@ -53,7 +53,10 @@ import {OnRouteLeave} from 'sentry/utils/reactRouter6Compat/onRouteLeave'; import {scheduleMicroTask} from 'sentry/utils/scheduleMicroTask'; import {normalizeUrl} from 'sentry/utils/url/normalizeUrl'; import {useApi} from 'sentry/utils/useApi'; -import {useChartInterval} from 'sentry/utils/useChartInterval'; +import { + ChartIntervalUnspecifiedStrategy, + useChartInterval, +} from 'sentry/utils/useChartInterval'; import {useLocation} from 'sentry/utils/useLocation'; import type {ReactRouter3Navigate} from 'sentry/utils/useNavigate'; import {useNavigate} from 'sentry/utils/useNavigate'; @@ -1462,7 +1465,9 @@ export function DashboardDetailWithInjectedProps( const location = useLocation(); const params = useParams(); const router = useRouter(); - const [chartInterval] = useChartInterval(); + const [chartInterval] = useChartInterval({ + unspecifiedStrategy: ChartIntervalUnspecifiedStrategy.USE_SECOND_BIGGEST, + }); const queryClient = useQueryClient(); // Always use the validated chart interval so the UI dropdown and widget // requests stay in sync. chartInterval is validated against the current page diff --git a/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx b/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx index 5f4909a8c4b49f..8f18f7b41876a2 100644 --- a/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx @@ -3,7 +3,10 @@ import {useState} from 'react'; import {usePageFilters} from 'sentry/components/pageFilters/usePageFilters'; import {dedupeArray} from 'sentry/utils/dedupeArray'; import type {Sort} from 'sentry/utils/discover/fields'; -import {useChartInterval} from 'sentry/utils/useChartInterval'; +import { + ChartIntervalUnspecifiedStrategy, + useChartInterval, +} from 'sentry/utils/useChartInterval'; import {useLocation} from 'sentry/utils/useLocation'; import {useNavigate} from 'sentry/utils/useNavigate'; import {useOrganization} from 'sentry/utils/useOrganization'; @@ -44,7 +47,9 @@ export function WidgetPreview({ const location = useLocation(); const navigate = useNavigate(); const pageFilters = usePageFilters(); - const [chartInterval] = useChartInterval(); + const [chartInterval] = useChartInterval({ + unspecifiedStrategy: ChartIntervalUnspecifiedStrategy.USE_SECOND_BIGGEST, + }); const {state, dispatch} = useWidgetBuilderContext(); const [tableWidths, setTableWidths] = useState(); From 56cca500116d4e34204e6af93e2ce6e0fad7af86 Mon Sep 17 00:00:00 2001 From: George Gritsouk <989898+gggritso@users.noreply.github.com> Date: Thu, 9 Apr 2026 11:02:33 -0400 Subject: [PATCH 2/2] ref(dashboards): extract useDashboardChartInterval hook Consolidate the three dashboard useChartInterval call sites into a single wrapper hook that hardcodes USE_SECOND_BIGGEST strategy. This prevents detail.tsx, widgetPreview.tsx, and filtersBar.tsx from going out of sync. Also fixes filtersBar.tsx which was previously using the default USE_SMALLEST strategy instead of USE_SECOND_BIGGEST. --- .../app/views/dashboards/dashboard.spec.tsx | 41 ++++++++++--------- static/app/views/dashboards/detail.tsx | 9 +--- static/app/views/dashboards/filtersBar.tsx | 4 +- .../hooks/useDashboardChartInterval.tsx | 15 +++++++ .../components/widgetPreview.tsx | 9 +--- 5 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 static/app/views/dashboards/hooks/useDashboardChartInterval.tsx diff --git a/static/app/views/dashboards/dashboard.spec.tsx b/static/app/views/dashboards/dashboard.spec.tsx index 025e58fe10981b..ee1a25a8e0b3f3 100644 --- a/static/app/views/dashboards/dashboard.spec.tsx +++ b/static/app/views/dashboards/dashboard.spec.tsx @@ -11,10 +11,10 @@ import {resetMockDate, setMockDate} from 'sentry-test/utils'; import {PageFiltersStore} from 'sentry/components/pageFilters/store'; import {MemberListStore} from 'sentry/stores/memberListStore'; import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting'; -import {useChartInterval} from 'sentry/utils/useChartInterval'; import {useLocation} from 'sentry/utils/useLocation'; import {Dashboard} from 'sentry/views/dashboards/dashboard'; import {FiltersBar} from 'sentry/views/dashboards/filtersBar'; +import {useDashboardChartInterval} from 'sentry/views/dashboards/hooks/useDashboardChartInterval'; import type { DashboardDetails, DashboardFilters, @@ -499,7 +499,7 @@ describe('Dashboards > Dashboard', () => { dashboard?: DashboardDetails; } = {}) { const location = useLocation(); - const [widgetInterval] = useChartInterval(); + const [widgetInterval] = useDashboardChartInterval(); return ( Dashboard', () => { }); describe('no interval set in URL', () => { - it('defaults to the smallest valid interval for the dashboard period', async () => { - const fiveMinuteMock = MockApiClient.addMockResponse({ + it('defaults to the second-biggest valid interval for the dashboard period', async () => { + const tenMinuteMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-stats/', method: 'GET', body: [], - match: [MockApiClient.matchQuery({interval: '5m'})], + match: [MockApiClient.matchQuery({interval: '10m'})], }); const thirtyMinuteMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-stats/', @@ -555,21 +555,21 @@ describe('Dashboards > Dashboard', () => { match: [MockApiClient.matchQuery({interval: '30m'})], }); - // No interval in the URL — the 5m default is derived purely from the - // dashboard's saved 24h period via PageFiltersStore → useChartInterval. + // No interval in the URL — the 10m default (second-biggest of [5m, 10m, 30m]) + // is derived from the dashboard's saved 24h period via useDashboardChartInterval. const {router} = render(, { organization: orgWithFlag, initialRouterConfig: {location: {pathname: '/'}}, }); await screen.findByText('Test Spans Widget'); - await waitFor(() => expect(fiveMinuteMock).toHaveBeenCalled()); + await waitFor(() => expect(tenMinuteMock).toHaveBeenCalled()); expect(thirtyMinuteMock).not.toHaveBeenCalled(); // Click the interval selector and choose '30 minutes'. FiltersBar writes // interval=30m to the URL, DashboardWithIntervalSelector re-renders with // the new widgetInterval, and the widget re-fetches with the new interval. - await userEvent.click(screen.getByRole('button', {name: '5 minutes'})); + await userEvent.click(screen.getByRole('button', {name: '10 minutes'})); await userEvent.click(screen.getByRole('option', {name: '30 minutes'})); await waitFor(() => expect(thirtyMinuteMock).toHaveBeenCalled()); @@ -632,11 +632,11 @@ describe('Dashboards > Dashboard', () => { }); it('ignores the URL interval and falls back to the period default', async () => { - const threeHourMock = MockApiClient.addMockResponse({ + const sixHourMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-stats/', method: 'GET', body: [], - match: [MockApiClient.matchQuery({interval: '3h'})], + match: [MockApiClient.matchQuery({interval: '6h'})], }); const fiveMinuteMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/events-stats/', @@ -653,11 +653,12 @@ describe('Dashboards > Dashboard', () => { await screen.findByText('Test Spans Widget'); - // The selector should show the period-derived default, not the invalid URL value. - expect(screen.getByRole('button', {name: '3 hours'})).toBeInTheDocument(); + // The selector should show the period-derived default (6h = second-biggest + // of [3h, 6h, 12h]), not the invalid URL value (5m). + expect(screen.getByRole('button', {name: '6 hours'})).toBeInTheDocument(); // The widget should query with the valid default interval, not the URL value. - await waitFor(() => expect(threeHourMock).toHaveBeenCalled()); + await waitFor(() => expect(sixHourMock).toHaveBeenCalled()); expect(fiveMinuteMock).not.toHaveBeenCalled(); }); }); @@ -681,11 +682,11 @@ describe('Dashboards > Dashboard', () => { it('ignores the URL interval and falls back to the period default', async () => { // Uses the /sessions/ endpoint (session.status in columns → useSessionAPI=true), // which surfaces the "intervals too granular" error in production. - const threeHourMock = MockApiClient.addMockResponse({ + const sixHourMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/sessions/', method: 'GET', body: emptySessionsBody, - match: [MockApiClient.matchQuery({interval: '3h'})], + match: [MockApiClient.matchQuery({interval: '6h'})], }); const fiveMinuteMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/sessions/', @@ -701,13 +702,13 @@ describe('Dashboards > Dashboard', () => { await screen.findByText('Test Releases Widget'); - // The selector should show the period-derived default (3h), not the - // invalid URL value (5m). - expect(screen.getByRole('button', {name: '3 hours'})).toBeInTheDocument(); + // The selector should show the period-derived default (6h = second-biggest + // of [3h, 6h, 12h]), not the invalid URL value (5m). + expect(screen.getByRole('button', {name: '6 hours'})).toBeInTheDocument(); // The widget should query the sessions endpoint with the valid default // interval, not the 5m value from the URL. - await waitFor(() => expect(threeHourMock).toHaveBeenCalled()); + await waitFor(() => expect(sixHourMock).toHaveBeenCalled()); expect(fiveMinuteMock).not.toHaveBeenCalled(); }); }); diff --git a/static/app/views/dashboards/detail.tsx b/static/app/views/dashboards/detail.tsx index f2e8b4b7cc7606..2f7711e2442dd2 100644 --- a/static/app/views/dashboards/detail.tsx +++ b/static/app/views/dashboards/detail.tsx @@ -53,10 +53,6 @@ import {OnRouteLeave} from 'sentry/utils/reactRouter6Compat/onRouteLeave'; import {scheduleMicroTask} from 'sentry/utils/scheduleMicroTask'; import {normalizeUrl} from 'sentry/utils/url/normalizeUrl'; import {useApi} from 'sentry/utils/useApi'; -import { - ChartIntervalUnspecifiedStrategy, - useChartInterval, -} from 'sentry/utils/useChartInterval'; import {useLocation} from 'sentry/utils/useLocation'; import type {ReactRouter3Navigate} from 'sentry/utils/useNavigate'; import {useNavigate} from 'sentry/utils/useNavigate'; @@ -64,6 +60,7 @@ import {useOrganization} from 'sentry/utils/useOrganization'; import {useParams} from 'sentry/utils/useParams'; import {useProjects} from 'sentry/utils/useProjects'; import {useRouter} from 'sentry/utils/useRouter'; +import {useDashboardChartInterval} from 'sentry/views/dashboards/hooks/useDashboardChartInterval'; import { cloneDashboard, getCurrentPageFilters, @@ -1465,9 +1462,7 @@ export function DashboardDetailWithInjectedProps( const location = useLocation(); const params = useParams(); const router = useRouter(); - const [chartInterval] = useChartInterval({ - unspecifiedStrategy: ChartIntervalUnspecifiedStrategy.USE_SECOND_BIGGEST, - }); + const [chartInterval] = useDashboardChartInterval(); const queryClient = useQueryClient(); // Always use the validated chart interval so the UI dropdown and widget // requests stay in sync. chartInterval is validated against the current page diff --git a/static/app/views/dashboards/filtersBar.tsx b/static/app/views/dashboards/filtersBar.tsx index bc807621ac2fae..e2cda97867f23d 100644 --- a/static/app/views/dashboards/filtersBar.tsx +++ b/static/app/views/dashboards/filtersBar.tsx @@ -25,7 +25,6 @@ import type {User} from 'sentry/types/user'; import {defined} from 'sentry/utils'; import {trackAnalytics} from 'sentry/utils/analytics'; import {ToggleOnDemand} from 'sentry/utils/performance/contexts/onDemandControl'; -import {useChartInterval} from 'sentry/utils/useChartInterval'; import {useMaxPickableDays} from 'sentry/utils/useMaxPickableDays'; import {useOrganization} from 'sentry/utils/useOrganization'; import {useUser} from 'sentry/utils/useUser'; @@ -33,6 +32,7 @@ import {useUserTeams} from 'sentry/utils/useUserTeams'; import {AddFilter} from 'sentry/views/dashboards/globalFilter/addFilter'; import {GenericFilterSelector} from 'sentry/views/dashboards/globalFilter/genericFilterSelector'; import {globalFilterKeysAreEqual} from 'sentry/views/dashboards/globalFilter/utils'; +import {useDashboardChartInterval} from 'sentry/views/dashboards/hooks/useDashboardChartInterval'; import {useDatasetSearchBarData} from 'sentry/views/dashboards/hooks/useDatasetSearchBarData'; import {useInvalidateStarredDashboards} from 'sentry/views/dashboards/hooks/useInvalidateStarredDashboards'; import {getDashboardFiltersFromURL} from 'sentry/views/dashboards/utils'; @@ -234,7 +234,7 @@ export function FiltersBar({ const hasIntervalSelection = organization.features.includes( 'dashboards-interval-selection' ); - const [interval, setInterval, intervalOptions] = useChartInterval(); + const [interval, setInterval, intervalOptions] = useDashboardChartInterval(); return ( diff --git a/static/app/views/dashboards/hooks/useDashboardChartInterval.tsx b/static/app/views/dashboards/hooks/useDashboardChartInterval.tsx new file mode 100644 index 00000000000000..d147f9a5304112 --- /dev/null +++ b/static/app/views/dashboards/hooks/useDashboardChartInterval.tsx @@ -0,0 +1,15 @@ +import { + ChartIntervalUnspecifiedStrategy, + useChartInterval, +} from 'sentry/utils/useChartInterval'; + +/** + * Wrapper around `useChartInterval` that uses the `USE_SECOND_BIGGEST` + * strategy for dashboards. This keeps the dashboard detail page, widget + * builder preview, and filters bar in sync. + */ +export function useDashboardChartInterval() { + return useChartInterval({ + unspecifiedStrategy: ChartIntervalUnspecifiedStrategy.USE_SECOND_BIGGEST, + }); +} diff --git a/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx b/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx index 8f18f7b41876a2..aa55709dda7c13 100644 --- a/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/widgetPreview.tsx @@ -3,13 +3,10 @@ import {useState} from 'react'; import {usePageFilters} from 'sentry/components/pageFilters/usePageFilters'; import {dedupeArray} from 'sentry/utils/dedupeArray'; import type {Sort} from 'sentry/utils/discover/fields'; -import { - ChartIntervalUnspecifiedStrategy, - useChartInterval, -} from 'sentry/utils/useChartInterval'; import {useLocation} from 'sentry/utils/useLocation'; import {useNavigate} from 'sentry/utils/useNavigate'; import {useOrganization} from 'sentry/utils/useOrganization'; +import {useDashboardChartInterval} from 'sentry/views/dashboards/hooks/useDashboardChartInterval'; import { DisplayType, WidgetType, @@ -47,9 +44,7 @@ export function WidgetPreview({ const location = useLocation(); const navigate = useNavigate(); const pageFilters = usePageFilters(); - const [chartInterval] = useChartInterval({ - unspecifiedStrategy: ChartIntervalUnspecifiedStrategy.USE_SECOND_BIGGEST, - }); + const [chartInterval] = useDashboardChartInterval(); const {state, dispatch} = useWidgetBuilderContext(); const [tableWidths, setTableWidths] = useState();