Skip to content

Commit 8f598e9

Browse files
committed
squash
1 parent ad67332 commit 8f598e9

File tree

14 files changed

+1020
-1228
lines changed

14 files changed

+1020
-1228
lines changed

static/app/components/repositories/scmIntegrationTree/providerConfigLink.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import {IconOpen} from 'sentry/icons';
66
import {t} from 'sentry/locale';
77
import type {OrganizationIntegration} from 'sentry/types/integrations';
88

9-
function getProviderConfigUrl(integration: OrganizationIntegration): string | null {
9+
export function getProviderConfigUrl(
10+
integration: OrganizationIntegration
11+
): string | null {
1012
const {externalId, provider, domainName, accountType} = integration;
1113
if (!externalId) {
1214
return null;

static/app/components/repositories/scmRepoTreeModal.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,20 @@ import type {ModalRenderProps} from 'sentry/actionCreators/modal';
88
import {ScmIntegrationTree} from 'sentry/components/repositories/scmIntegrationTree/scmIntegrationTree';
99
import {ScmTreeFilters} from 'sentry/components/repositories/scmIntegrationTree/scmTreeFilters';
1010
import type {RepoFilter} from 'sentry/components/repositories/scmIntegrationTree/types';
11-
import {t, tct} from 'sentry/locale';
11+
import {tct} from 'sentry/locale';
1212

13-
export function ScmRepoTreeModal({Header, Body}: ModalRenderProps) {
13+
interface Props extends ModalRenderProps {
14+
title: string;
15+
}
16+
17+
export function ScmRepoTreeModal({Header, Body, title}: Props) {
1418
const [search, setSearch] = useState('');
1519
const [repoFilter, setRepoFilter] = useState<RepoFilter>('all');
1620

1721
return (
1822
<Fragment>
1923
<Header closeButton>
20-
<Heading as="h4">{t('Add Repository')}</Heading>
24+
<Heading as="h4">{title}</Heading>
2125
</Header>
2226
<Body>
2327
<Stack gap="2xl">

static/app/utils/api/apiFetch.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import {useEffect} from 'react';
12
import type {QueryFunctionContext} from '@tanstack/react-query';
23

34
import {parseQueryKey} from 'sentry/utils/api/apiQueryKey';
45
import type {ApiQueryKey, InfiniteApiQueryKey} from 'sentry/utils/api/apiQueryKey';
56
import type {ParsedHeader} from 'sentry/utils/parseLinkHeader';
6-
import {QUERY_API_CLIENT} from 'sentry/utils/queryClient';
7+
import {QUERY_API_CLIENT, type UseInfiniteQueryResult} from 'sentry/utils/queryClient';
78

89
export type ApiResponse<TResponseData = unknown> = {
910
headers: {
@@ -68,3 +69,18 @@ export async function apiFetchInfinite<TQueryFnData = unknown>(
6869
json: json as TQueryFnData,
6970
};
7071
}
72+
73+
export function useFetchAllPages<TQueryFnData = unknown>({
74+
result,
75+
enabled = true,
76+
}: {
77+
result: UseInfiniteQueryResult<TQueryFnData, Error>;
78+
enabled?: boolean;
79+
}) {
80+
const {fetchNextPage, hasNextPage, isError, isFetchingNextPage} = result;
81+
useEffect(() => {
82+
if (enabled && !isError && !isFetchingNextPage && hasNextPage) {
83+
fetchNextPage();
84+
}
85+
}, [enabled, hasNextPage, fetchNextPage, isError, isFetchingNextPage]);
86+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import {Grid} from '@sentry/scraps/layout';
2+
3+
import * as Storybook from 'sentry/stories';
4+
import type {OrganizationIntegration} from 'sentry/types/integrations';
5+
import {
6+
AutofixOverviewSection,
7+
CodeReviewOverviewSection,
8+
SCMOverviewSection,
9+
} from 'sentry/views/settings/seer/overview/seerOverview';
10+
import type {useSeerOverviewData} from 'sentry/views/settings/seer/overview/useSeerOverviewData';
11+
12+
function OrganizationIntegrationsFixture(
13+
params: Partial<OrganizationIntegration> = {}
14+
): OrganizationIntegration {
15+
return {
16+
accountType: '',
17+
gracePeriodEnd: '',
18+
organizationIntegrationStatus: 'active',
19+
domainName: 'github.com',
20+
icon: 'https://secure.gravatar.com/avatar/8b4cb68e40b74c90427d8262256bd1c8',
21+
id: '5',
22+
name: 'NisanthanNanthakumar',
23+
provider: {
24+
aspects: {},
25+
canAdd: true,
26+
canDisable: false,
27+
features: ['commits', 'issue-basic'],
28+
key: 'github',
29+
name: 'Github',
30+
slug: 'github',
31+
},
32+
status: 'active',
33+
configData: null,
34+
configOrganization: [],
35+
externalId: 'ext-integration-1',
36+
organizationId: '1',
37+
...params,
38+
};
39+
}
40+
41+
const seerIntegrationsFixture = [
42+
OrganizationIntegrationsFixture({id: '1', name: 'Integration A'}),
43+
OrganizationIntegrationsFixture({id: '2', name: 'Integration B'}),
44+
];
45+
46+
const baseStats: ReturnType<typeof useSeerOverviewData>['stats'] = {
47+
integrationCount: 2,
48+
scmIntegrationCount: 2,
49+
seerIntegrations: seerIntegrationsFixture,
50+
seerIntegrationCount: 2,
51+
totalRepoCount: 10,
52+
seerRepoCount: 10, // equal to totalRepoCount: no "Add all repos" button
53+
reposWithSettingsCount: 10,
54+
projectsWithReposCount: 6, // equal to totalProjects: no "Handoff all to" CompactSelect
55+
projectsWithAutomationCount: 6,
56+
projectsWithCreatePrCount: 6,
57+
totalProjects: 6,
58+
reposWithCodeReviewCount: 10, // equal to seerRepoCount
59+
};
60+
61+
function SeerOverview({
62+
stats,
63+
isLoading,
64+
}: {
65+
isLoading: boolean;
66+
stats: ReturnType<typeof useSeerOverviewData>['stats'];
67+
}) {
68+
return (
69+
<Grid columns="minmax(max-content, 140px) max-content 1fr" gap="xl">
70+
<SCMOverviewSection stats={stats} isLoading={isLoading} />
71+
<AutofixOverviewSection stats={stats} isLoading={isLoading} />
72+
<CodeReviewOverviewSection stats={stats} isLoading={isLoading} />
73+
</Grid>
74+
);
75+
}
76+
77+
export default Storybook.story('SeerOverview', story => {
78+
story('No alerts (healthy state)', () => (
79+
<SeerOverview stats={baseStats} isLoading={false} />
80+
));
81+
82+
story('Loading state', () => <SeerOverview stats={baseStats} isLoading />);
83+
84+
// SCM stories
85+
86+
story('SCM: No SCM integrations installed', () => (
87+
<SeerOverview
88+
stats={{
89+
...baseStats,
90+
integrationCount: 0,
91+
scmIntegrationCount: 0,
92+
seerIntegrations: [],
93+
seerIntegrationCount: 0,
94+
totalRepoCount: 0,
95+
seerRepoCount: 0,
96+
reposWithSettingsCount: 0,
97+
projectsWithReposCount: 0,
98+
projectsWithAutomationCount: 0,
99+
projectsWithCreatePrCount: 0,
100+
reposWithCodeReviewCount: 0,
101+
}}
102+
isLoading={false}
103+
/>
104+
));
105+
106+
story('SCM: Integrations installed but no repos connected', () => (
107+
<SeerOverview
108+
stats={{
109+
...baseStats,
110+
totalRepoCount: 0,
111+
seerRepoCount: 0,
112+
reposWithSettingsCount: 0,
113+
projectsWithReposCount: 0,
114+
projectsWithAutomationCount: 0,
115+
projectsWithCreatePrCount: 0,
116+
reposWithCodeReviewCount: 0,
117+
}}
118+
isLoading={false}
119+
/>
120+
));
121+
122+
story('SCM: Some repos not yet added to Seer', () => (
123+
<SeerOverview
124+
stats={{
125+
...baseStats,
126+
totalRepoCount: 10,
127+
seerRepoCount: 6, // seerRepoCount !== totalRepoCount → shows "Add all repos"
128+
reposWithSettingsCount: 6,
129+
projectsWithReposCount: 3,
130+
projectsWithAutomationCount: 2,
131+
projectsWithCreatePrCount: 1,
132+
reposWithCodeReviewCount: 2,
133+
}}
134+
isLoading={false}
135+
/>
136+
));
137+
138+
// Autofix stories
139+
140+
story('Autofix: No projects have repos linked', () => (
141+
<SeerOverview
142+
stats={{
143+
...baseStats,
144+
projectsWithReposCount: 0, // hides header link, CompactSelect, and ButtonBar
145+
projectsWithAutomationCount: 0,
146+
projectsWithCreatePrCount: 0,
147+
}}
148+
isLoading={false}
149+
/>
150+
));
151+
152+
story('Autofix: Some projects with repos (partial)', () => (
153+
<SeerOverview
154+
stats={{
155+
...baseStats,
156+
projectsWithReposCount: 3, // < totalProjects (6) → shows "Handoff all to" CompactSelect
157+
projectsWithAutomationCount: 2,
158+
projectsWithCreatePrCount: 1,
159+
}}
160+
isLoading={false}
161+
/>
162+
));
163+
164+
// Code Review stories
165+
166+
story('Code Review: No repos have code review enabled', () => (
167+
<SeerOverview
168+
stats={{
169+
...baseStats,
170+
reposWithCodeReviewCount: 0, // seerRepoCount > 0 → ButtonBar visible, shows 0/10
171+
}}
172+
isLoading={false}
173+
/>
174+
));
175+
});

0 commit comments

Comments
 (0)