|
1 | | -import { |
2 | | - __internal_useOrganizationEnterpriseConnections, |
3 | | - __internal_useOrganizationEnterpriseConnectionTestRuns, |
4 | | - useSession, |
5 | | -} from '@clerk/shared/react'; |
6 | | -import type { ConfigureSSOProps, EnterpriseConnectionResource } from '@clerk/shared/types'; |
| 1 | +import { useSession } from '@clerk/shared/react'; |
| 2 | +import type { ConfigureSSOProps } from '@clerk/shared/types'; |
7 | 3 | import React from 'react'; |
8 | 4 |
|
9 | 5 | import { useProtect } from '@/common'; |
10 | 6 | import { withCoreUserGuard } from '@/contexts'; |
11 | 7 | import { Col, Flex, Flow, Heading, Icon, localizationKeys, Text } from '@/customizables'; |
12 | | -import { useCardState, withCardStateProvider } from '@/elements/contexts'; |
| 8 | +import { withCardStateProvider } from '@/elements/contexts'; |
13 | 9 | import { ProfileCard } from '@/elements/ProfileCard'; |
14 | 10 | import { ExclamationTriangle } from '@/icons'; |
15 | 11 | import { Route, Switch } from '@/router'; |
16 | 12 |
|
17 | | -import { ConfigureSSOProvider, useConfigureSSO } from './ConfigureSSOContext'; |
18 | | -import { ConfigureSSOHeader } from './ConfigureSSOHeader'; |
| 13 | +import { ConfigureSSOProvider } from './ConfigureSSOContext'; |
19 | 14 | import { ConfigureSSONavbar } from './ConfigureSSONavbar'; |
20 | 15 | import { ConfigureSSOSkeleton } from './ConfigureSSOSkeleton'; |
| 16 | +import { ConfigureSSOSteps } from './ConfigureSSOSteps'; |
21 | 17 | import { ProfileCardFooter, ProfileCardHeader } from './elements/ProfileCard'; |
22 | 18 | import { Step } from './elements/Step'; |
23 | | -import { useWizard, Wizard } from './elements/Wizard'; |
24 | | -import { ConfigureStep, ConfirmationStep, SelectProviderStep, TestConfigurationStep, VerifyDomainStep } from './steps'; |
| 19 | +import { useOrganizationEnterpriseConnection } from './hooks/useOrganizationEnterpriseConnection'; |
25 | 20 |
|
26 | 21 | const ConfigureSSOInternal = () => { |
27 | 22 | return ( |
@@ -51,90 +46,38 @@ const AuthenticatedContent = withCoreUserGuard(() => { |
51 | 46 |
|
52 | 47 | export const ConfigureSSOContent = ({ contentRef }: { contentRef: React.RefObject<HTMLDivElement> }) => { |
53 | 48 | const { |
54 | | - data: enterpriseConnections, |
55 | | - isLoading: isLoadingEnterpriseConnections, |
56 | | - createEnterpriseConnection, |
57 | | - updateEnterpriseConnection, |
58 | | - deleteEnterpriseConnection, |
59 | | - } = __internal_useOrganizationEnterpriseConnections({ enabled: true }); |
60 | | - // Currently the self-serve SSO UI flow only supports one enterprise connection per organization |
61 | | - const enterpriseConnection = enterpriseConnections?.[0]; |
62 | | - |
63 | | - const { hasSuccessfulTestRun, isLoading: isLoadingTestRuns } = useHasSuccessfulTestRun(enterpriseConnection); |
64 | | - |
65 | | - const isLoading = isLoadingEnterpriseConnections || isLoadingTestRuns; |
| 49 | + isLoading, |
| 50 | + enterpriseConnection, |
| 51 | + organizationEnterpriseConnection, |
| 52 | + testRuns, |
| 53 | + mutations, |
| 54 | + primaryEmailAddress, |
| 55 | + } = useOrganizationEnterpriseConnection(); |
| 56 | + |
| 57 | + // Gate loading one level above the provider so the context never observes a |
| 58 | + // loading state. The single test-run source is part of this initial fetch |
| 59 | + // when a connection exists at load, so a cold landing on the test step is |
| 60 | + // covered by the full skeleton here. |
66 | 61 | if (isLoading) { |
67 | 62 | return <ConfigureSSOSkeleton />; |
68 | 63 | } |
69 | 64 |
|
70 | 65 | return ( |
71 | 66 | <ConfigureSSOProtect> |
72 | 67 | <ConfigureSSOProvider |
73 | | - hasSuccessfulTestRun={hasSuccessfulTestRun} |
| 68 | + organizationEnterpriseConnection={organizationEnterpriseConnection} |
| 69 | + testRuns={testRuns} |
74 | 70 | enterpriseConnection={enterpriseConnection} |
75 | 71 | contentRef={contentRef} |
76 | | - createEnterpriseConnection={createEnterpriseConnection} |
77 | | - updateEnterpriseConnection={updateEnterpriseConnection} |
78 | | - deleteEnterpriseConnection={deleteEnterpriseConnection} |
| 72 | + mutations={mutations} |
| 73 | + primaryEmailAddress={primaryEmailAddress} |
79 | 74 | > |
80 | 75 | <ConfigureSSOSteps /> |
81 | 76 | </ConfigureSSOProvider> |
82 | 77 | </ConfigureSSOProtect> |
83 | 78 | ); |
84 | 79 | }; |
85 | 80 |
|
86 | | -const ConfigureSSOSteps = () => { |
87 | | - const { initialStepId, enterpriseConnection } = useConfigureSSO(); |
88 | | - |
89 | | - return ( |
90 | | - <Wizard initialStepId={initialStepId}> |
91 | | - <ResetCardErrorOnStepChange /> |
92 | | - <ConfigureSSOHeader /> |
93 | | - |
94 | | - {/* |
95 | | - * `select-provider` is only a wizard step while there's no enterprise |
96 | | - * connection yet — creating one unregisters this step, which: |
97 | | - * 1. Hides it from the breadcrumb (no need for a manual filter), and |
98 | | - * 2. Prevents `goPrev` from any later step (e.g. configure's first |
99 | | - * substep) from ever bubbling back into provider selection. |
100 | | - */} |
101 | | - {!enterpriseConnection && ( |
102 | | - <Wizard.Step id='select-provider'> |
103 | | - <SelectProviderStep /> |
104 | | - </Wizard.Step> |
105 | | - )} |
106 | | - |
107 | | - <Wizard.Step |
108 | | - id='verify-domain' |
109 | | - label='Verify domain' |
110 | | - > |
111 | | - <VerifyDomainStep /> |
112 | | - </Wizard.Step> |
113 | | - |
114 | | - <Wizard.Step |
115 | | - id='configure' |
116 | | - label='Configure' |
117 | | - > |
118 | | - <ConfigureStep /> |
119 | | - </Wizard.Step> |
120 | | - |
121 | | - <Wizard.Step |
122 | | - id='test' |
123 | | - label='Test' |
124 | | - > |
125 | | - <TestConfigurationStep /> |
126 | | - </Wizard.Step> |
127 | | - |
128 | | - <Wizard.Step |
129 | | - id='confirmation' |
130 | | - label='Confirmation' |
131 | | - > |
132 | | - <ConfirmationStep /> |
133 | | - </Wizard.Step> |
134 | | - </Wizard> |
135 | | - ); |
136 | | -}; |
137 | | - |
138 | 81 | const ConfigureSSOProtect = ({ children }: { children: React.ReactNode }) => { |
139 | 82 | const { session } = useSession(); |
140 | 83 | const isPersonalWorkspace = !session?.lastActiveOrganizationId; |
@@ -193,44 +136,4 @@ const MissingManageEnterpriseConnectionsPermission = () => ( |
193 | 136 | </> |
194 | 137 | ); |
195 | 138 |
|
196 | | -/** |
197 | | - * Sentinel component rendered inside `<Wizard>` |
198 | | - * |
199 | | - * Clears any card-level error whenever the active step transitions, so a stale failure from one step |
200 | | - * doesn't leak into the next |
201 | | - */ |
202 | | -const ResetCardErrorOnStepChange = (): null => { |
203 | | - const { currentStep } = useWizard(); |
204 | | - const card = useCardState(); |
205 | | - const previousStepIdRef = React.useRef(currentStep?.id); |
206 | | - |
207 | | - React.useEffect(() => { |
208 | | - if (previousStepIdRef.current === currentStep?.id) { |
209 | | - return; |
210 | | - } |
211 | | - |
212 | | - previousStepIdRef.current = currentStep?.id; |
213 | | - card.setError(undefined); |
214 | | - }, [currentStep?.id, card]); |
215 | | - |
216 | | - return null; |
217 | | -}; |
218 | | - |
219 | | -/** |
220 | | - * Fetches a single successful test run for the given connection on mount |
221 | | - */ |
222 | | -const useHasSuccessfulTestRun = ( |
223 | | - enterpriseConnection: EnterpriseConnectionResource | undefined, |
224 | | -): { hasSuccessfulTestRun: boolean; isLoading: boolean } => { |
225 | | - const { data: successfulTestRuns, isLoading } = __internal_useOrganizationEnterpriseConnectionTestRuns({ |
226 | | - enterpriseConnectionId: enterpriseConnection?.id ?? null, |
227 | | - params: { initialPage: 1, pageSize: 1, status: ['success'] }, |
228 | | - }); |
229 | | - |
230 | | - return { |
231 | | - hasSuccessfulTestRun: (successfulTestRuns?.length ?? 0) > 0, |
232 | | - isLoading, |
233 | | - }; |
234 | | -}; |
235 | | - |
236 | 139 | export const ConfigureSSO: React.ComponentType<ConfigureSSOProps> = withCardStateProvider(ConfigureSSOInternal); |
0 commit comments