Skip to content

Commit 9ea1f40

Browse files
committed
ref(onboarding): Inline dropdown into ScmProviderPills
Merge ScmProvidersDropdown back into ScmProviderPills to keep the dropdown logic colocated with the provider layout. Also clean up the grid column template into readable variables.
1 parent 8dc5224 commit 9ea1f40

File tree

2 files changed

+71
-88
lines changed

2 files changed

+71
-88
lines changed

static/app/views/onboarding/components/scmProviderPills.tsx

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
import {Fragment, useEffect, useRef} from 'react';
2+
13
import {Flex, Grid} from '@sentry/scraps/layout';
24

5+
import {DropdownMenu} from 'sentry/components/dropdownMenu';
6+
import {t} from 'sentry/locale';
37
import type {Integration, IntegrationProvider} from 'sentry/types/integrations';
48
import {getIntegrationIcon} from 'sentry/utils/integrationUtil';
9+
import {useOrganization} from 'sentry/utils/useOrganization';
10+
import {useAddIntegration} from 'sentry/views/settings/organizationIntegrations/addIntegration';
511
import {IntegrationButton} from 'sentry/views/settings/organizationIntegrations/integrationButton';
612
import {IntegrationContext} from 'sentry/views/settings/organizationIntegrations/integrationContext';
713

8-
import {ScmProvidersDropdown} from './scmProvidersDropdown';
9-
1014
/**
1115
* Provider keys shown as top-level pill buttons. Everything else is grouped
1216
* into the "More" dropdown to reduce visual clutter.
@@ -19,17 +23,24 @@ interface ScmProviderPillsProps {
1923
}
2024

2125
export function ScmProviderPills({providers, onInstall}: ScmProviderPillsProps) {
26+
const flowMapRef = useRef<Map<string, () => void>>(new Map());
2227
const primaryProviders = providers.filter(p => PRIMARY_PROVIDER_KEYS.has(p.key));
2328
const moreProviders = providers.filter(p => !PRIMARY_PROVIDER_KEYS.has(p.key));
2429

30+
const columnPrimaryProviders = primaryProviders.length
31+
? `repeat(${primaryProviders.length}, 1fr)`
32+
: '';
33+
const columnMoreProviders = moreProviders.length ? 'min-content' : '';
34+
const columnSpacer = primaryProviders.length && moreProviders.length ? ' ' : '';
35+
36+
const columnsMd = `${columnPrimaryProviders}${columnSpacer}${columnMoreProviders}`;
37+
2538
return (
2639
<Flex justify="center">
2740
<Grid
2841
columns={{
2942
xs: '1fr 1fr',
30-
md: primaryProviders.length
31-
? `repeat(${primaryProviders.length}, 1fr) min-content`
32-
: 'min-content',
43+
md: columnsMd,
3344
}}
3445
rows={{xs: 2}}
3546
justify="center"
@@ -60,9 +71,63 @@ export function ScmProviderPills({providers, onInstall}: ScmProviderPillsProps)
6071
</IntegrationContext>
6172
))}
6273
{moreProviders.length > 0 && (
63-
<ScmProvidersDropdown providers={moreProviders} onInstall={onInstall} />
74+
<Fragment>
75+
{moreProviders.map(provider => (
76+
<ScmProviderFlowSetup
77+
key={provider.key}
78+
provider={provider}
79+
onInstall={onInstall}
80+
flowMapRef={flowMapRef}
81+
/>
82+
))}
83+
<DropdownMenu
84+
triggerLabel={t('More')}
85+
position="bottom-end"
86+
items={moreProviders.map(provider => ({
87+
key: provider.key,
88+
label: provider.name,
89+
leadingItems: getIntegrationIcon(provider.key, 'sm'),
90+
onAction: () => flowMapRef.current.get(provider.key)?.(),
91+
}))}
92+
/>
93+
</Fragment>
6494
)}
6595
</Grid>
6696
</Flex>
6797
);
6898
}
99+
100+
interface ScmProviderFlowSetupProps {
101+
flowMapRef: React.RefObject<Map<string, () => void>>;
102+
onInstall: (data: Integration) => void;
103+
provider: IntegrationProvider;
104+
}
105+
106+
/**
107+
* Invisible component that initializes {@link useAddIntegration} for a single
108+
* provider and registers the resulting `startFlow` function in a shared ref
109+
* map. This lets the parent's {@link DropdownMenu} trigger the correct
110+
* OAuth/pipeline flow from a data-driven menu item.
111+
*/
112+
function ScmProviderFlowSetup({
113+
provider,
114+
onInstall,
115+
flowMapRef,
116+
}: ScmProviderFlowSetupProps) {
117+
const organization = useOrganization();
118+
const {startFlow} = useAddIntegration({
119+
provider,
120+
organization,
121+
onInstall,
122+
analyticsParams: {
123+
view: 'onboarding',
124+
already_installed: false,
125+
},
126+
});
127+
128+
useEffect(() => {
129+
flowMapRef.current.set(provider.key, startFlow);
130+
}, [flowMapRef, provider.key, startFlow]);
131+
132+
return null;
133+
}

static/app/views/onboarding/components/scmProvidersDropdown.tsx

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)