Skip to content

Commit 9854a76

Browse files
bcoemchen-sentry
authored andcommitted
feat(dashboards): allow interval selection similar to explore (#108416)
Allows for interval selection similar to the behaviour of individual charts in explore.
1 parent 0809bad commit 9854a76

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+653
-222
lines changed
File renamed without changes.
File renamed without changes.

static/app/views/dashboards/dashboard.spec.tsx

Lines changed: 359 additions & 60 deletions
Large diffs are not rendered by default.

static/app/views/dashboards/dashboard.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type Props = {
9292
onNewWidgetScrollComplete?: () => void;
9393
onSetNewWidget?: () => void;
9494
useTimeseriesVisualization?: boolean;
95+
widgetInterval?: string;
9596
};
9697

9798
interface LayoutState extends Record<string, Layout[]> {
@@ -116,6 +117,7 @@ function Dashboard({
116117
onNewWidgetScrollComplete,
117118
onSetNewWidget,
118119
useTimeseriesVisualization,
120+
widgetInterval,
119121
}: Props) {
120122
const theme = useTheme();
121123
const location = useLocation();
@@ -442,6 +444,7 @@ function Dashboard({
442444
newlyAddedWidget={newlyAddedWidget}
443445
onNewWidgetScrollComplete={onNewWidgetScrollComplete}
444446
useTimeseriesVisualization={useTimeseriesVisualization}
447+
widgetInterval={widgetInterval}
445448
/>
446449
</div>
447450
))}

static/app/views/dashboards/datasetConfig/base.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ export type WidgetQueryParams = {
115115
* Skip adding parentheses around widget conditions when applying dashboard filters.
116116
*/
117117
skipDashboardFilterParens?: boolean;
118+
/**
119+
* Optional user-selected interval override for timeseries queries.
120+
*/
121+
widgetInterval?: string;
118122
};
119123

120124
export interface DatasetConfig<SeriesResponse, TableResponse> {

static/app/views/dashboards/datasetConfig/utils/getSeriesRequestData.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ export function getSeriesRequestData(
2323
organization: Organization,
2424
pageFilters: PageFilters,
2525
dataset: DiscoverDatasets,
26-
referrer?: string
26+
referrer?: string,
27+
widgetInterval?: string
2728
): EventsStatsOptions<true> {
2829
const widgetQuery = widget.queries[queryIndex]!;
2930
const {displayType, limit} = widget;
3031
const {environments, projects} = pageFilters;
3132
const {start, end, period: statsPeriod} = pageFilters.datetime;
32-
const interval = getWidgetInterval(widget, {start, end, period: statsPeriod}, '1m');
33+
const interval =
34+
widgetInterval ?? getWidgetInterval(widget, {start, end, period: statsPeriod}, '1m');
3335

3436
let requestData: EventsStatsOptions<true>;
3537
if (displayType === DisplayType.TOP_N) {

static/app/views/dashboards/detail.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import {OnRouteLeave} from 'sentry/utils/reactRouter6Compat/onRouteLeave';
5151
import {scheduleMicroTask} from 'sentry/utils/scheduleMicroTask';
5252
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
5353
import useApi from 'sentry/utils/useApi';
54+
import {useChartInterval} from 'sentry/utils/useChartInterval';
5455
import {useLocation} from 'sentry/utils/useLocation';
5556
import type {ReactRouter3Navigate} from 'sentry/utils/useNavigate';
5657
import {useNavigate} from 'sentry/utils/useNavigate';
@@ -142,6 +143,7 @@ type Props = {
142143
children?: React.ReactNode;
143144
onDashboardUpdate?: (updatedDashboard: DashboardDetails) => void;
144145
useTimeseriesVisualization?: boolean;
146+
widgetInterval?: string;
145147
};
146148

147149
type State = {
@@ -1311,6 +1313,7 @@ class DashboardDetail extends Component<Props, State> {
13111313
useTimeseriesVisualization={
13121314
useTimeseriesVisualization
13131315
}
1316+
widgetInterval={this.props.widgetInterval}
13141317
/>
13151318
</WidgetQueryQueueProvider>
13161319

@@ -1395,6 +1398,14 @@ export default function DashboardDetailWithInjectedProps(
13951398
const location = useLocation();
13961399
const params = useParams<RouteParams>();
13971400
const router = useRouter();
1401+
const [chartInterval] = useChartInterval();
1402+
1403+
// Always use the validated chart interval so the UI dropdown and widget
1404+
// requests stay in sync. chartInterval is validated against the current page
1405+
// filter period (e.g. won't return 1m for a 30d range) and always has a value.
1406+
const widgetInterval = organization.features.includes('dashboards-interval-selection')
1407+
? chartInterval
1408+
: undefined;
13981409

13991410
return (
14001411
<DashboardDetail
@@ -1407,6 +1418,7 @@ export default function DashboardDetailWithInjectedProps(
14071418
location={location}
14081419
params={params}
14091420
router={router}
1421+
widgetInterval={widgetInterval}
14101422
/>
14111423
);
14121424
}

0 commit comments

Comments
 (0)