Path: blob/main/components/dashboard/src/dedicated-setup/DedicatedSetup.tsx
2506 views
/**1* Copyright (c) 2023 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { FC, useCallback, useContext, useMemo, useState } from "react";7import { GettingStartedStep } from "./GettingStartedStep";8import { OrgNamingStep } from "./OrgNamingStep";9import { SSOSetupStep } from "./SSOSetupStep";10import { useConfetti } from "../contexts/ConfettiContext";11import { SetupCompleteStep } from "./SetupCompleteStep";12import { useOIDCClientsQuery } from "../data/oidc-clients/oidc-clients-query";13import { useCurrentOrg } from "../data/organizations/orgs-query";14import { SpinnerLoader } from "../components/Loader";15import { getGitpodService } from "../service/service";16import { UserContext } from "../user-context";17import { OIDCClientConfig } from "@gitpod/public-api/lib/gitpod/experimental/v1/oidc_pb";18import { useQueryParams } from "../hooks/use-query-params";19import { useDocumentTitle } from "../hooks/use-document-title";20import { forceDedicatedSetupParam } from "./use-show-dedicated-setup";21import { Organization } from "@gitpod/public-api/lib/gitpod/v1/organization_pb";22import { Delayed } from "@podkit/loading/Delayed";23import { userClient } from "../service/public-api";2425type Props = {26onComplete: () => void;27};28const DedicatedSetup: FC<Props> = ({ onComplete }) => {29useDocumentTitle("Welcome");30const currentOrg = useCurrentOrg();31const oidcClients = useOIDCClientsQuery();3233// if a config already exists, select first active, or first config34const ssoConfig = useMemo(() => {35if (!oidcClients.data) {36return;37}3839const activeConfig = (oidcClients.data || []).find((c) => c.active);40if (activeConfig) {41return activeConfig;42}4344return oidcClients.data?.[0];45}, [oidcClients.data]);4647// let current org load along with oidc clients once we have an org48if (currentOrg.isLoading || (currentOrg.data && oidcClients.isLoading)) {49return (50<Delayed>51<SpinnerLoader />52</Delayed>53);54}5556// Delay rendering until we have data so we can default to the correct step57return <DedicatedSetupSteps org={currentOrg.data} ssoConfig={ssoConfig} onComplete={onComplete} />;58};5960export default DedicatedSetup;6162const STEPS = {63GETTING_STARTED: "getting-started",64ORG_NAMING: "org-naming",65SSO_SETUP: "sso-setup",66COMPLETE: "complete",67} as const;68type StepsValue = typeof STEPS[keyof typeof STEPS];6970type DedicatedSetupStepsProps = {71org?: Organization;72ssoConfig?: OIDCClientConfig;73onComplete: () => void;74};75const DedicatedSetupSteps: FC<DedicatedSetupStepsProps> = ({ org, ssoConfig, onComplete }) => {76const { setUser } = useContext(UserContext);77const params = useQueryParams();7879// If we have an org w/ a name, we can skip the first step and go to sso setup80let initialStep: StepsValue = org && org.name ? STEPS.SSO_SETUP : STEPS.GETTING_STARTED;81// If there's already an active sso config, advance to the complete step82if (ssoConfig?.active) {83initialStep = STEPS.COMPLETE;84}8586// If setup forced via params, just start at beginning87const forceSetup = forceDedicatedSetupParam(params);88const [step, setStep] = useState<StepsValue>(forceSetup ? STEPS.GETTING_STARTED : initialStep);89const { dropConfetti } = useConfetti();9091const handleSetupComplete = useCallback(() => {92// celebrate 🎉93dropConfetti();94// Transition to completed view95setStep(STEPS.COMPLETE);96}, [dropConfetti]);9798const updateUser = useCallback(async () => {99// TODO(at) this is still required if the FE shim is used per FF100await getGitpodService().reconnect();101102const response = await userClient.getAuthenticatedUser({});103if (response.user) {104setUser(response.user);105}106}, [setUser]);107108const handleEndSetup = useCallback(async () => {109await updateUser();110onComplete();111}, [onComplete, updateUser]);112113return (114<>115{step === STEPS.GETTING_STARTED && (116<GettingStartedStep117progressCurrent={0}118progressTotal={2}119onComplete={() => setStep(STEPS.ORG_NAMING)}120/>121)}122{step === STEPS.ORG_NAMING && (123<OrgNamingStep progressCurrent={1} progressTotal={2} onComplete={() => setStep(STEPS.SSO_SETUP)} />124)}125{step === STEPS.SSO_SETUP && (126<SSOSetupStep127progressCurrent={2}128progressTotal={2}129config={ssoConfig}130onComplete={handleSetupComplete}131/>132)}133{step === STEPS.COMPLETE && <SetupCompleteStep onComplete={handleEndSetup} />}134</>135);136};137138139