Skip to content

Commit fb3bf11

Browse files
fix repo bug
1 parent 8945a59 commit fb3bf11

File tree

3 files changed

+37
-45
lines changed

3 files changed

+37
-45
lines changed

static/app/views/prevent/preventAI/manageRepos.tsx

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ import {Heading, Text} from 'sentry/components/core/text';
1313
import {Tooltip} from 'sentry/components/core/tooltip';
1414
import {IconSettings} from 'sentry/icons';
1515
import {t, tct} from 'sentry/locale';
16-
import type {OrganizationIntegration} from 'sentry/types/integrations';
16+
import type {OrganizationIntegration, Repository} from 'sentry/types/integrations';
1717
import {useInfiniteRepositories} from 'sentry/views/prevent/preventAI/hooks/usePreventAIInfiniteRepositories';
1818
import ManageReposPanel from 'sentry/views/prevent/preventAI/manageReposPanel';
19-
import ManageReposToolbar, {
20-
ALL_REPOS_VALUE,
21-
} from 'sentry/views/prevent/preventAI/manageReposToolbar';
19+
import ManageReposToolbar from 'sentry/views/prevent/preventAI/manageReposToolbar';
2220

2321
import {FeatureOverview} from './onboarding';
2422

@@ -29,7 +27,7 @@ function ManageReposPage({integratedOrgs}: {integratedOrgs: OrganizationIntegrat
2927
const [selectedOrgId, setSelectedOrgId] = useState<string>(
3028
() => integratedOrgs[0]?.id ?? ''
3129
);
32-
const [selectedRepoId, setSelectedRepoId] = useState<string>(() => ALL_REPOS_VALUE);
30+
const [selectedRepo, setSelectedRepo] = useState<Repository | null>(() => null);
3331

3432
const queryResult = useInfiniteRepositories({
3533
integrationId: selectedOrgId,
@@ -46,48 +44,37 @@ function ManageReposPage({integratedOrgs}: {integratedOrgs: OrganizationIntegrat
4644
return found ?? integratedOrgs[0];
4745
}, [integratedOrgs, selectedOrgId]);
4846

49-
// If the selected repo is not present in the list of repos, use null (for "All Repos")
50-
const selectedRepo = useMemo(() => {
51-
if (selectedRepoId === ALL_REPOS_VALUE) {
52-
return null;
53-
}
54-
const found = reposData.find(repo => repo.id === selectedRepoId);
55-
return found ?? null;
56-
}, [reposData, selectedRepoId]);
57-
5847
// When the org changes, reset to "All Repos"
5948
const setSelectedOrgIdWithCascadeRepoId = useCallback((orgId: string) => {
6049
setSelectedOrgId(orgId);
61-
setSelectedRepoId(ALL_REPOS_VALUE);
50+
setSelectedRepo(null);
6251
}, []);
6352

6453
const isOrgSelected = !!selectedOrg;
65-
const isRepoSelected = selectedRepoId === ALL_REPOS_VALUE || !!selectedRepo;
6654

6755
return (
6856
<Flex direction="column" maxWidth="1000px" gap="xl">
6957
<Flex align="center" justify="between">
7058
<ManageReposToolbar
7159
integratedOrgs={integratedOrgs}
7260
selectedOrg={selectedOrgId}
73-
selectedRepo={selectedRepoId}
74-
selectedRepoData={selectedRepo}
61+
selectedRepo={selectedRepo}
7562
onOrgChange={setSelectedOrgIdWithCascadeRepoId}
76-
onRepoChange={setSelectedRepoId}
63+
onRepoChange={setSelectedRepo}
7764
/>
7865
<Flex style={{transform: 'translateY(-70px)'}}>
7966
<Tooltip
8067
title="Select an organization and repository to configure settings"
81-
disabled={isOrgSelected && isRepoSelected}
68+
disabled={isOrgSelected}
8269
position="left"
8370
>
8471
<Button
8572
borderless
8673
icon={<IconSettings size="md" />}
8774
aria-label="Settings"
8875
onClick={() => setIsPanelOpen(true)}
89-
disabled={!isOrgSelected || !isRepoSelected}
90-
tabIndex={!isOrgSelected || !isRepoSelected ? -1 : 0}
76+
disabled={!isOrgSelected}
77+
tabIndex={isOrgSelected ? 0 : -1}
9178
data-test-id="manage-repos-settings-button"
9279
/>
9380
</Tooltip>
@@ -141,15 +128,15 @@ function ManageReposPage({integratedOrgs}: {integratedOrgs: OrganizationIntegrat
141128
/>
142129
</Flex>
143130

144-
{selectedOrg && (selectedRepoId === ALL_REPOS_VALUE || selectedRepo) && (
131+
{selectedOrg && (
145132
<ManageReposPanel
146-
key={`${selectedOrgId || 'no-org'}-${selectedRepoId || 'no-repo'}`}
133+
key={`${selectedOrgId || 'no-org'}-${selectedRepo?.id || 'all-repos'}`}
147134
collapsed={!isPanelOpen}
148135
onClose={() => setIsPanelOpen(false)}
149136
org={selectedOrg}
150137
repo={selectedRepo}
151138
allRepos={reposData}
152-
isEditingOrgDefaults={selectedRepoId === ALL_REPOS_VALUE}
139+
isEditingOrgDefaults={selectedRepo === null}
153140
/>
154141
)}
155142
</Flex>

static/app/views/prevent/preventAI/manageReposToolbar.spec.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ describe('ManageReposToolbar', () => {
107107
const defaultProps = {
108108
integratedOrgs: mockIntegratedOrgs,
109109
selectedOrg: '1',
110-
selectedRepo: '1',
111-
selectedRepoData: mockRepositories[0] ?? null,
110+
selectedRepo: mockRepositories[0] ?? null,
112111
onOrgChange: jest.fn(),
113112
onRepoChange: jest.fn(),
114113
};
@@ -213,7 +212,7 @@ describe('ManageReposToolbar', () => {
213212
const repoOption = screen.getByText('repo-2');
214213
await userEvent.click(repoOption);
215214

216-
expect(defaultProps.onRepoChange).toHaveBeenCalledWith('2');
215+
expect(defaultProps.onRepoChange).toHaveBeenCalledWith(mockRepositories[1]);
217216
});
218217

219218
it('shows only repos for the selected org', async () => {
@@ -232,8 +231,7 @@ describe('ManageReposToolbar', () => {
232231
<ManageReposToolbar
233232
{...defaultProps}
234233
selectedOrg="2"
235-
selectedRepo="3"
236-
selectedRepoData={mockOrg2Repositories[0] ?? null}
234+
selectedRepo={mockOrg2Repositories[0] ?? null}
237235
/>,
238236
{
239237
organization: OrganizationFixture({slug: 'org-slug'}),
@@ -273,7 +271,7 @@ describe('ManageReposToolbar', () => {
273271
expect(await screen.findByText('All Repos')).toBeInTheDocument();
274272
});
275273

276-
it('calls onRepoChange with "__$ALL_REPOS__" when "All Repos" is selected', async () => {
274+
it('calls onRepoChange with null when "All Repos" is selected', async () => {
277275
MockApiClient.addMockResponse({
278276
url: '/organizations/org-slug/repos/',
279277
body: mockRepositories,
@@ -295,6 +293,6 @@ describe('ManageReposToolbar', () => {
295293
const allReposOption = await screen.findByText('All Repos');
296294
await userEvent.click(allReposOption);
297295

298-
expect(defaultProps.onRepoChange).toHaveBeenCalledWith('__$ALL_REPOS__');
296+
expect(defaultProps.onRepoChange).toHaveBeenCalledWith(null);
299297
});
300298
});

static/app/views/prevent/preventAI/manageReposToolbar.tsx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,20 @@ import {useDebouncedValue} from 'sentry/utils/useDebouncedValue';
1111
import {useInfiniteRepositories} from 'sentry/views/prevent/preventAI/hooks/usePreventAIInfiniteRepositories';
1212
import {getRepoNameWithoutOrg} from 'sentry/views/prevent/preventAI/utils';
1313

14-
export const ALL_REPOS_VALUE = '__$ALL_REPOS__';
14+
const ALL_REPOS_VALUE = '__$ALL_REPOS__';
1515

1616
function ManageReposToolbar({
1717
integratedOrgs,
1818
onOrgChange,
1919
onRepoChange,
2020
selectedOrg,
2121
selectedRepo,
22-
selectedRepoData,
2322
}: {
2423
integratedOrgs: OrganizationIntegration[];
2524
onOrgChange: (orgId: string) => void;
26-
onRepoChange: (repoId: string) => void;
25+
onRepoChange: (repo: Repository | null) => void;
2726
selectedOrg: string;
28-
selectedRepo: string;
29-
selectedRepoData: Repository | null;
27+
selectedRepo: Repository | null;
3028
}) {
3129
const [searchValue, setSearchValue] = useState<string | undefined>();
3230
const debouncedSearch = useDebouncedValue(searchValue, 300);
@@ -119,19 +117,19 @@ function ManageReposToolbar({
119117
label: getRepoNameWithoutOrg(repo.name),
120118
}));
121119

122-
if (selectedRepoData && selectedRepo !== ALL_REPOS_VALUE) {
120+
if (selectedRepo) {
123121
repoOptions = [
124122
{
125-
value: selectedRepoData.id,
126-
label: getRepoNameWithoutOrg(selectedRepoData.name),
123+
value: selectedRepo.id,
124+
label: getRepoNameWithoutOrg(selectedRepo.name),
127125
},
128126
...repoOptions,
129127
];
130128
}
131129

132130
const dedupedRepoOptions = uniqBy(repoOptions, 'value');
133131
return [{value: ALL_REPOS_VALUE, label: t('All Repos')}, ...dedupedRepoOptions];
134-
}, [filteredReposData, selectedRepo, selectedRepoData]);
132+
}, [filteredReposData, selectedRepo]);
135133

136134
const getRepoEmptyMessage = () => {
137135
if (isLoading) return t('Loading repositories...');
@@ -162,11 +160,19 @@ function ManageReposToolbar({
162160
/>
163161

164162
<CompactSelect
165-
value={selectedRepo}
163+
value={selectedRepo?.id ?? ALL_REPOS_VALUE}
166164
options={repositoryOptions}
167165
loading={isLoading}
168166
disabled={!selectedOrg || isLoading}
169-
onChange={option => onRepoChange(option?.value ?? '')}
167+
onChange={option => {
168+
const repoId = option?.value;
169+
if (repoId === ALL_REPOS_VALUE) {
170+
onRepoChange(null);
171+
} else {
172+
const foundRepo = allReposData.find(repo => repo.id === repoId);
173+
onRepoChange(foundRepo ?? null);
174+
}
175+
}}
170176
searchable
171177
disableSearchFilter
172178
onSearch={setSearchValue}
@@ -181,8 +187,9 @@ function ManageReposToolbar({
181187
icon: <IconRepository />,
182188
children: (
183189
<TriggerLabel>
184-
{repositoryOptions.find(opt => opt.value === selectedRepo)?.label ||
185-
t('Select repository')}
190+
{repositoryOptions.find(
191+
opt => opt.value === (selectedRepo?.id ?? ALL_REPOS_VALUE)
192+
)?.label || t('Select repository')}
186193
</TriggerLabel>
187194
),
188195
}}

0 commit comments

Comments
 (0)