Skip to content

Commit 082ea7e

Browse files
authored
Merge branch 'master' into tkdodo/ref/detectors-endpoint-to-apiOptions
2 parents 501dddf + f1383e4 commit 082ea7e

File tree

4 files changed

+91
-71
lines changed

4 files changed

+91
-71
lines changed

static/app/components/modals/bulkEditMonitorsModal.tsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Fragment, useState} from 'react';
22
import {css} from '@emotion/react';
33
import styled from '@emotion/styled';
4+
import {useQuery, useQueryClient} from '@tanstack/react-query';
45

56
import {Button} from '@sentry/scraps/button';
67
import {Checkbox} from '@sentry/scraps/checkbox';
@@ -15,7 +16,7 @@ import {PanelTable} from 'sentry/components/panels/panelTable';
1516
import {Placeholder} from 'sentry/components/placeholder';
1617
import {SearchBar} from 'sentry/components/searchBar';
1718
import {t, tct, tn} from 'sentry/locale';
18-
import {setApiQueryData, useApiQuery, useQueryClient} from 'sentry/utils/queryClient';
19+
import {selectJsonWithHeaders} from 'sentry/utils/api/apiOptions';
1920
import {useApi} from 'sentry/utils/useApi';
2021
import {useLocation} from 'sentry/utils/useLocation';
2122
import {useOrganization} from 'sentry/utils/useOrganization';
@@ -25,7 +26,7 @@ import {
2526
SortSelector,
2627
} from 'sentry/views/insights/crons/components/overviewTimeline/sortSelector';
2728
import type {Monitor} from 'sentry/views/insights/crons/types';
28-
import {makeMonitorListQueryKey} from 'sentry/views/insights/crons/utils';
29+
import {monitorListApiOptions} from 'sentry/views/insights/crons/utils';
2930
import {scheduleAsText} from 'sentry/views/insights/crons/utils/scheduleAsText';
3031

3132
interface Props extends ModalRenderProps {}
@@ -46,10 +47,12 @@ export function BulkEditMonitorsModal({Header, Body, Footer, closeModal}: Props)
4647
sort: MonitorSortOption;
4748
}>({sort: MonitorSortOption.STATUS, order: MonitorSortOrder.ASCENDING});
4849

49-
const queryKey = makeMonitorListQueryKey(organization, {
50-
...location.query,
51-
query: searchQuery,
50+
const monitorListOptions = monitorListApiOptions(organization, {
5251
cursor,
52+
query: searchQuery,
53+
project: location.query.project,
54+
environment: location.query.environment,
55+
owner: location.query.owner,
5356
sort: sortSelection.sort,
5457
asc: sortSelection.order,
5558
});
@@ -84,24 +87,28 @@ export function BulkEditMonitorsModal({Header, Body, Footer, closeModal}: Props)
8487
setSelectedMonitors([]);
8588

8689
if (resp?.updated) {
87-
setApiQueryData<Monitor[]>(queryClient, queryKey, oldMonitorList => {
88-
return oldMonitorList?.map(
89-
monitor =>
90-
resp.updated.find(newMonitor => newMonitor.slug === monitor.slug) ?? monitor
91-
);
90+
queryClient.setQueryData(monitorListOptions.queryKey, previous => {
91+
if (!previous) {
92+
return previous;
93+
}
94+
return {
95+
...previous,
96+
json: previous.json.map(
97+
monitor =>
98+
resp.updated.find(newMonitor => newMonitor.slug === monitor.slug) ?? monitor
99+
),
100+
};
92101
});
93102
}
94103
setIsUpdating(false);
95104
};
96105

97-
const {
98-
data: monitorList,
99-
getResponseHeader: monitorListHeaders,
100-
isPending,
101-
} = useApiQuery<Monitor[]>(queryKey, {
102-
staleTime: 0,
106+
const {data, isPending} = useQuery({
107+
...monitorListOptions,
108+
select: selectJsonWithHeaders,
103109
});
104-
const monitorPageLinks = monitorListHeaders?.('Link');
110+
const monitorList = data?.json;
111+
const monitorPageLinks = data?.headers.Link;
105112

106113
const headers = [t('Monitor'), t('State'), t('Muted'), t('Schedule')];
107114
const shouldDisable = selectedMonitors.every(monitor => monitor.status !== 'disabled');

static/app/views/insights/crons/components/overviewTimeline/index.tsx

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ import {useDateNavigation} from 'sentry/components/checkInTimeline/hooks/useDate
1717
import {useTimeWindowConfig} from 'sentry/components/checkInTimeline/hooks/useTimeWindowConfig';
1818
import {Panel} from 'sentry/components/panels/panel';
1919
import {Sticky} from 'sentry/components/sticky';
20-
import {setApiQueryData, useQueryClient} from 'sentry/utils/queryClient';
20+
import {useQueryClient} from 'sentry/utils/queryClient';
2121
import {useApi} from 'sentry/utils/useApi';
2222
import {useDebouncedValue} from 'sentry/utils/useDebouncedValue';
2323
import {useDimensions} from 'sentry/utils/useDimensions';
2424
import {useLocation} from 'sentry/utils/useLocation';
2525
import {useOrganization} from 'sentry/utils/useOrganization';
2626
import {CronServiceIncidents} from 'sentry/views/insights/crons/components/serviceIncidents';
2727
import type {Monitor} from 'sentry/views/insights/crons/types';
28-
import {makeMonitorListQueryKey} from 'sentry/views/insights/crons/utils';
28+
import {monitorListApiOptions} from 'sentry/views/insights/crons/utils';
2929

3030
import {OverviewRow} from './overviewRow';
3131
import {SortSelector} from './sortSelector';
@@ -53,14 +53,16 @@ export function OverviewTimeline({monitorList}: Props) {
5353
return;
5454
}
5555

56-
const queryKey = makeMonitorListQueryKey(organization, location.query);
57-
setApiQueryData<Monitor[]>(queryClient, queryKey, oldMonitorList => {
58-
if (!oldMonitorList) {
56+
const monitorListOptions = monitorListApiOptions(organization, location.query);
57+
58+
queryClient.setQueryData(monitorListOptions.queryKey, old => {
59+
if (!old) {
5960
return undefined;
6061
}
62+
const oldMonitorList = old.json;
6163
const oldMonitorIdx = oldMonitorList.findIndex(m => m.slug === monitor.slug);
6264
if (oldMonitorIdx < 0) {
63-
return oldMonitorList;
65+
return old;
6466
}
6567

6668
const oldMonitor = oldMonitorList[oldMonitorIdx]!;
@@ -74,10 +76,10 @@ export function OverviewTimeline({monitorList}: Props) {
7476
const right = oldMonitorList.slice(oldMonitorIdx + 1);
7577

7678
if (newEnvList.length === 0) {
77-
return [...left, ...right];
79+
return {...old, json: [...left, ...right]};
7880
}
7981

80-
return [...left, updatedMonitor, ...right];
82+
return {...old, json: [...left, updatedMonitor, ...right]};
8183
});
8284
};
8385

@@ -98,11 +100,14 @@ export function OverviewTimeline({monitorList}: Props) {
98100
return;
99101
}
100102

101-
const queryKey = makeMonitorListQueryKey(organization, location.query);
102-
setApiQueryData<Monitor[]>(queryClient, queryKey, oldMonitorList => {
103-
return oldMonitorList
104-
? // TODO(davidenwang): in future only change the specifically modified environment for optimistic updates
105-
oldMonitorList.map(m => (m.slug === monitor.slug ? resp : m))
103+
const monitorListOptions = monitorListApiOptions(organization, location.query);
104+
queryClient.setQueryData(monitorListOptions.queryKey, old => {
105+
return old
106+
? {
107+
...old,
108+
// TODO(davidenwang): in future only change the specifically modified environment for optimistic updates
109+
json: old.json.map(m => (m.slug === monitor.slug ? resp : m)),
110+
}
106111
: undefined;
107112
});
108113
};
@@ -115,12 +120,15 @@ export function OverviewTimeline({monitorList}: Props) {
115120
return;
116121
}
117122

118-
const queryKey = makeMonitorListQueryKey(organization, location.query);
119-
setApiQueryData<Monitor[]>(queryClient, queryKey, oldMonitorList => {
120-
return oldMonitorList
121-
? oldMonitorList.map(m =>
122-
m.slug === monitor.slug ? {...m, status: resp.status} : m
123-
)
123+
const monitorListOptions = monitorListApiOptions(organization, location.query);
124+
queryClient.setQueryData(monitorListOptions.queryKey, old => {
125+
return old
126+
? {
127+
...old,
128+
json: old.json.map(m =>
129+
m.slug === monitor.slug ? {...m, status: resp.status} : m
130+
),
131+
}
124132
: undefined;
125133
});
126134
};

static/app/views/insights/crons/utils.tsx

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,36 @@ import type {TickStyle} from 'sentry/components/checkInTimeline/types';
22
import {t, tn} from 'sentry/locale';
33
import type {SelectValue} from 'sentry/types/core';
44
import type {Organization} from 'sentry/types/organization';
5+
import {apiOptions} from 'sentry/utils/api/apiOptions';
56
import {getApiUrl} from 'sentry/utils/api/getApiUrl';
67

7-
import {CheckInStatus} from './types';
8+
import {CheckInStatus, type Monitor} from './types';
89

9-
export function makeMonitorListQueryKey(
10+
export function monitorListApiOptions(
1011
organization: Organization,
11-
params: Record<string, any>
12+
queryParams: Partial<
13+
Record<
14+
'asc' | 'cursor' | 'environment' | 'owner' | 'project' | 'query' | 'sort',
15+
unknown
16+
>
17+
>
1218
) {
13-
const {query, project, environment, owner, cursor, sort, asc} = params;
14-
15-
return [
16-
getApiUrl('/organizations/$organizationIdOrSlug/monitors/', {
17-
path: {organizationIdOrSlug: organization.slug},
18-
}),
19-
{
20-
query: {
21-
cursor,
22-
query,
23-
project,
24-
environment,
25-
owner,
26-
includeNew: true,
27-
per_page: 20,
28-
sort,
29-
asc,
30-
},
19+
const {query, project, environment, owner, cursor, sort, asc} = queryParams;
20+
return apiOptions.as<Monitor[]>()('/organizations/$organizationIdOrSlug/monitors/', {
21+
path: {organizationIdOrSlug: organization.slug},
22+
query: {
23+
cursor,
24+
query,
25+
project,
26+
environment,
27+
owner,
28+
includeNew: true,
29+
per_page: 20,
30+
sort,
31+
asc,
3132
},
32-
] as const;
33+
staleTime: 0,
34+
});
3335
}
3436

3537
export function makeMonitorDetailsQueryKey(

static/app/views/insights/crons/views/overview.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {Fragment} from 'react';
22
import styled from '@emotion/styled';
3+
import {useQuery} from '@tanstack/react-query';
34
import * as qs from 'query-string';
45

56
import {Alert} from '@sentry/scraps/alert';
@@ -28,7 +29,7 @@ import {SearchBar} from 'sentry/components/searchBar';
2829
import {SentryDocumentTitle} from 'sentry/components/sentryDocumentTitle';
2930
import {IconAdd, IconList} from 'sentry/icons';
3031
import {t, tct} from 'sentry/locale';
31-
import {useApiQuery} from 'sentry/utils/queryClient';
32+
import {selectJsonWithHeaders} from 'sentry/utils/api/apiOptions';
3233
import {decodeList, decodeScalar} from 'sentry/utils/queryString';
3334
import {useRouteAnalyticsEventNames} from 'sentry/utils/routeAnalytics/useRouteAnalyticsEventNames';
3435
import {useRouteAnalyticsParams} from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
@@ -43,8 +44,7 @@ import {OwnerFilter} from 'sentry/views/insights/crons/components/ownerFilter';
4344
import {GlobalMonitorProcessingErrors} from 'sentry/views/insights/crons/components/processingErrors/globalMonitorProcessingErrors';
4445
import {useCronsUpsertGuideState} from 'sentry/views/insights/crons/components/useCronsUpsertGuideState';
4546
import {MODULE_DESCRIPTION, MODULE_DOC_LINK} from 'sentry/views/insights/crons/settings';
46-
import type {Monitor} from 'sentry/views/insights/crons/types';
47-
import {makeMonitorListQueryKey} from 'sentry/views/insights/crons/utils';
47+
import {monitorListApiOptions} from 'sentry/views/insights/crons/utils';
4848

4949
const CronsListPageHeader = HookOrDefault({
5050
hookName: 'component:crons-list-page-header',
@@ -57,21 +57,24 @@ function CronsOverview() {
5757
const {guideVisible} = useCronsUpsertGuideState();
5858
const project = decodeList(location.query?.project);
5959

60-
const queryKey = makeMonitorListQueryKey(organization, location.query);
61-
62-
const {
63-
data: monitorList,
64-
getResponseHeader: monitorListHeaders,
65-
isPending,
66-
refetch,
67-
} = useApiQuery<Monitor[]>(queryKey, {
68-
staleTime: 0,
60+
const {data, isPending, refetch} = useQuery({
61+
...monitorListApiOptions(organization, {
62+
cursor: location.query.cursor,
63+
query: location.query.query,
64+
project: location.query.project,
65+
environment: location.query.environment,
66+
owner: location.query.owner,
67+
sort: location.query.sort,
68+
asc: location.query.asc,
69+
}),
70+
select: selectJsonWithHeaders,
6971
});
72+
const monitorList = data?.json;
7073

7174
useRouteAnalyticsEventNames('monitors.page_viewed', 'Monitors: Page Viewed');
7275
useRouteAnalyticsParams({empty_state: !monitorList || monitorList.length === 0});
7376

74-
const monitorListPageLinks = monitorListHeaders?.('Link');
77+
const monitorListPageLinks = data?.headers.Link;
7578

7679
const handleSearch = (query: string) => {
7780
const currentQuery = {...location.query, cursor: undefined};

0 commit comments

Comments
 (0)