Skip to content

Commit fe37e3c

Browse files
committed
Create connection for organization
1 parent a7ea7a6 commit fe37e3c

5 files changed

Lines changed: 39 additions & 14 deletions

File tree

packages/ui/src/components/ConfigureSSO/ConfigureSSO.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,17 @@ const AuthenticatedContent = withCoreUserGuard(() => {
5252
const { organizationSettings } = useEnvironment();
5353
const { parsedOptions } = useAppearance();
5454
const hasLogo = Boolean(parsedOptions.logoImageUrl || logoImageUrl);
55+
const { organization } = useOrganization();
5556

5657
// Gate the entire wizard behind the org-level permission. When the
5758
// user can't manage enterprise connections, we still render the
5859
// outer sidebar/title chrome but replace the wizard with a
5960
// permissions-error message so the layout stays consistent
60-
const canManageEnterpriseConnections = useProtect({
61-
permission: 'org:sys_enterprise_connections:manage',
62-
});
61+
const canManageEnterpriseConnections =
62+
!!organization &&
63+
useProtect({
64+
permission: 'org:sys_enterprise_connections:manage',
65+
});
6366

6467
const {
6568
data: enterpriseConnections,
@@ -69,7 +72,7 @@ const AuthenticatedContent = withCoreUserGuard(() => {
6972
deleteEnterpriseConnection,
7073
revalidate: revalidateEnterpriseConnections,
7174
} = __internal_useUserEnterpriseConnections({
72-
enabled: canManageEnterpriseConnections,
75+
enabled: true,
7376
});
7477
// Currently FAPI only supports one enterprise connection per user
7578
const enterpriseConnection = enterpriseConnections?.[0];
@@ -148,7 +151,7 @@ const AuthenticatedContent = withCoreUserGuard(() => {
148151
flex: 1,
149152
})}
150153
>
151-
{canManageEnterpriseConnections ? (
154+
{canManageEnterpriseConnections || !organization ? (
152155
<ConfigureSSOFlowProvider
153156
enterpriseConnection={enterpriseConnection}
154157
isLoading={isLoadingEnterpriseConnections}
@@ -185,6 +188,7 @@ const ConfigureSSOSteps = () => {
185188
id='select-provider'
186189
path='select-provider'
187190
label='Select provider'
191+
hideFromBreadcrumb
188192
>
189193
<SelectProviderStep />
190194
</ConfigureSSOWizard.Step>

packages/ui/src/components/ConfigureSSO/steps/ConfigureCreateAppStep.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useUser } from '@clerk/shared/react';
1+
import { useOrganization, useUser } from '@clerk/shared/react';
22
import React from 'react';
33

44
import { Box, Button, Col, descriptors, Flex, Flow, Icon, Input, Spinner, Text } from '@/customizables';
@@ -19,6 +19,7 @@ export const ConfigureCreateApp = (): JSX.Element => {
1919
useConfigureSSOFlow();
2020
const { user } = useUser();
2121
const card = useCardState();
22+
const { organization } = useOrganization();
2223

2324
const primaryEmail = user?.primaryEmailAddress?.emailAddress ?? '';
2425
const emailDomain = getEmailDomain(primaryEmail);
@@ -51,6 +52,7 @@ export const ConfigureCreateApp = (): JSX.Element => {
5152
createEnterpriseConnection({
5253
provider: selectedProvider,
5354
name: emailDomain,
55+
organizationId: organization?.id,
5456
})
5557
.catch(err => handleError(err as Error, [], card.setError))
5658
.finally(() => setIsCreating(false));

packages/ui/src/components/ConfigureSSO/steps/VerifyDomainStep.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export const VerifyDomainStep = (): JSX.Element | null => {
154154
variant='body'
155155
sx={t => ({ color: t.colors.$colorMutedForeground })}
156156
>
157-
Contact the application's administrator to get access through the existing connection.
157+
Contact the application&apos;s administrator to get access through the existing connection.
158158
</Text>
159159
</Col>
160160
</>

packages/ui/src/components/ConfigureSSO/wizard/ConfigureSSOWizard.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function extractSteps(children: React.ReactNode): ConfigureSSOWizardActiveStep[]
5555
path: props.path,
5656
label: props.label,
5757
isCompleted: props.isCompleted,
58+
hideFromBreadcrumb: props.hideFromBreadcrumb,
5859
children: props.children,
5960
});
6061
});
@@ -265,12 +266,16 @@ const StepBody = ({ step }: { step: ConfigureSSOWizardActiveStep }): JSX.Element
265266
/**
266267
* Numbered breadcrumb of the outermost wizard's active steps.
267268
* Completed and current steps are clickable for backwards navigation,
268-
* future steps are disabled
269+
* future steps are disabled. Steps marked with `hideFromBreadcrumb`
270+
* are silently skipped over and the visible steps are renumbered, so
271+
* dropping a hidden step from the wizard later doesn't shift numbers
269272
*/
270273
const Header = (): JSX.Element => {
271274
const { activeSteps, currentIndex, isLoading, goToStep } = useConfigureSSOWizard();
272275
const { t } = useLocalizations();
273276

277+
const visibleSteps = React.useMemo(() => activeSteps.filter(s => !s.hideFromBreadcrumb), [activeSteps]);
278+
274279
return (
275280
<Flex
276281
elementDescriptor={descriptors.configureSSOWizardHeader}
@@ -284,10 +289,15 @@ const Header = (): JSX.Element => {
284289
flexWrap: 'wrap',
285290
})}
286291
>
287-
{activeSteps.map((step, index) => {
288-
const isCurrent = index === currentIndex;
289-
const isCompleted = step.isCompleted ?? index < currentIndex;
290-
const isReachable = isCompleted || index <= currentIndex;
292+
{visibleSteps.map((step, visibleIndex) => {
293+
// `currentIndex` is computed against the full `activeSteps`
294+
// list, so look the visible step back up there to keep
295+
// current/completed/reachable consistent with the wizard's
296+
// own routing state
297+
const actualIndex = activeSteps.findIndex(s => s.id === step.id);
298+
const isCurrent = actualIndex === currentIndex;
299+
const isCompleted = step.isCompleted ?? actualIndex < currentIndex;
300+
const isReachable = isCompleted || actualIndex <= currentIndex;
291301
const labelText = step.label ? (typeof step.label === 'string' ? step.label : t(step.label)) : '';
292302

293303
return (
@@ -342,7 +352,7 @@ const Header = (): JSX.Element => {
342352
size='xs'
343353
/>
344354
) : (
345-
index + 1
355+
visibleIndex + 1
346356
)}
347357
</Flex>
348358
<Text
@@ -356,7 +366,7 @@ const Header = (): JSX.Element => {
356366
</Text>
357367
</Button>
358368
)}
359-
{index < activeSteps.length - 1 && (
369+
{visibleIndex < visibleSteps.length - 1 && (
360370
<Icon
361371
elementDescriptor={descriptors.configureSSOWizardHeaderSeparator}
362372
icon={CaretRight}

packages/ui/src/components/ConfigureSSO/wizard/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ export interface ConfigureSSOWizardStepProps {
3131
* to the current step
3232
*/
3333
isCompleted?: boolean;
34+
/**
35+
* Hides this step from the wizard breadcrumb/header while keeping
36+
* it routable. Useful for "pre-flight" steps like provider
37+
* selection that shouldn't be visible (or clickable) once the user
38+
* has moved past them — and to avoid the visible step count
39+
* shifting when the step is later dropped from the wizard
40+
*/
41+
hideFromBreadcrumb?: boolean;
3442
/**
3543
* The step body. Anything React, including a nested
3644
* `<ConfigureSSOWizard>` for inner sub-steps
@@ -74,6 +82,7 @@ export interface ConfigureSSOWizardActiveStep {
7482
path: string;
7583
label?: LocalizationKey | string;
7684
isCompleted?: boolean;
85+
hideFromBreadcrumb?: boolean;
7786
children: React.ReactNode;
7887
}
7988

0 commit comments

Comments
 (0)