Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/dashboard/src/dedicated-setup/DedicatedSetup.tsx
2506 views
1
/**
2
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { FC, useCallback, useContext, useMemo, useState } from "react";
8
import { GettingStartedStep } from "./GettingStartedStep";
9
import { OrgNamingStep } from "./OrgNamingStep";
10
import { SSOSetupStep } from "./SSOSetupStep";
11
import { useConfetti } from "../contexts/ConfettiContext";
12
import { SetupCompleteStep } from "./SetupCompleteStep";
13
import { useOIDCClientsQuery } from "../data/oidc-clients/oidc-clients-query";
14
import { useCurrentOrg } from "../data/organizations/orgs-query";
15
import { SpinnerLoader } from "../components/Loader";
16
import { getGitpodService } from "../service/service";
17
import { UserContext } from "../user-context";
18
import { OIDCClientConfig } from "@gitpod/public-api/lib/gitpod/experimental/v1/oidc_pb";
19
import { useQueryParams } from "../hooks/use-query-params";
20
import { useDocumentTitle } from "../hooks/use-document-title";
21
import { forceDedicatedSetupParam } from "./use-show-dedicated-setup";
22
import { Organization } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";
23
import { Delayed } from "@podkit/loading/Delayed";
24
import { userClient } from "../service/public-api";
25
26
type Props = {
27
onComplete: () => void;
28
};
29
const DedicatedSetup: FC<Props> = ({ onComplete }) => {
30
useDocumentTitle("Welcome");
31
const currentOrg = useCurrentOrg();
32
const oidcClients = useOIDCClientsQuery();
33
34
// if a config already exists, select first active, or first config
35
const ssoConfig = useMemo(() => {
36
if (!oidcClients.data) {
37
return;
38
}
39
40
const activeConfig = (oidcClients.data || []).find((c) => c.active);
41
if (activeConfig) {
42
return activeConfig;
43
}
44
45
return oidcClients.data?.[0];
46
}, [oidcClients.data]);
47
48
// let current org load along with oidc clients once we have an org
49
if (currentOrg.isLoading || (currentOrg.data && oidcClients.isLoading)) {
50
return (
51
<Delayed>
52
<SpinnerLoader />
53
</Delayed>
54
);
55
}
56
57
// Delay rendering until we have data so we can default to the correct step
58
return <DedicatedSetupSteps org={currentOrg.data} ssoConfig={ssoConfig} onComplete={onComplete} />;
59
};
60
61
export default DedicatedSetup;
62
63
const STEPS = {
64
GETTING_STARTED: "getting-started",
65
ORG_NAMING: "org-naming",
66
SSO_SETUP: "sso-setup",
67
COMPLETE: "complete",
68
} as const;
69
type StepsValue = typeof STEPS[keyof typeof STEPS];
70
71
type DedicatedSetupStepsProps = {
72
org?: Organization;
73
ssoConfig?: OIDCClientConfig;
74
onComplete: () => void;
75
};
76
const DedicatedSetupSteps: FC<DedicatedSetupStepsProps> = ({ org, ssoConfig, onComplete }) => {
77
const { setUser } = useContext(UserContext);
78
const params = useQueryParams();
79
80
// If we have an org w/ a name, we can skip the first step and go to sso setup
81
let initialStep: StepsValue = org && org.name ? STEPS.SSO_SETUP : STEPS.GETTING_STARTED;
82
// If there's already an active sso config, advance to the complete step
83
if (ssoConfig?.active) {
84
initialStep = STEPS.COMPLETE;
85
}
86
87
// If setup forced via params, just start at beginning
88
const forceSetup = forceDedicatedSetupParam(params);
89
const [step, setStep] = useState<StepsValue>(forceSetup ? STEPS.GETTING_STARTED : initialStep);
90
const { dropConfetti } = useConfetti();
91
92
const handleSetupComplete = useCallback(() => {
93
// celebrate 🎉
94
dropConfetti();
95
// Transition to completed view
96
setStep(STEPS.COMPLETE);
97
}, [dropConfetti]);
98
99
const updateUser = useCallback(async () => {
100
// TODO(at) this is still required if the FE shim is used per FF
101
await getGitpodService().reconnect();
102
103
const response = await userClient.getAuthenticatedUser({});
104
if (response.user) {
105
setUser(response.user);
106
}
107
}, [setUser]);
108
109
const handleEndSetup = useCallback(async () => {
110
await updateUser();
111
onComplete();
112
}, [onComplete, updateUser]);
113
114
return (
115
<>
116
{step === STEPS.GETTING_STARTED && (
117
<GettingStartedStep
118
progressCurrent={0}
119
progressTotal={2}
120
onComplete={() => setStep(STEPS.ORG_NAMING)}
121
/>
122
)}
123
{step === STEPS.ORG_NAMING && (
124
<OrgNamingStep progressCurrent={1} progressTotal={2} onComplete={() => setStep(STEPS.SSO_SETUP)} />
125
)}
126
{step === STEPS.SSO_SETUP && (
127
<SSOSetupStep
128
progressCurrent={2}
129
progressTotal={2}
130
config={ssoConfig}
131
onComplete={handleSetupComplete}
132
/>
133
)}
134
{step === STEPS.COMPLETE && <SetupCompleteStep onComplete={handleEndSetup} />}
135
</>
136
);
137
};
138
139