diff --git a/apps/web/core/components/onboarding/header.tsx b/apps/web/core/components/onboarding/header.tsx index 4ebf6a9c156..224fca5f09f 100644 --- a/apps/web/core/components/onboarding/header.tsx +++ b/apps/web/core/components/onboarding/header.tsx @@ -12,6 +12,7 @@ import type { TOnboardingStep } from "@plane/types"; import { EOnboardingSteps } from "@plane/types"; import { cn } from "@plane/utils"; // hooks +import { useInstance } from "@/hooks/store/use-instance"; import { useUser } from "@/hooks/store/user"; // local imports import { SwitchAccountDropdown } from "./switch-account-dropdown"; @@ -26,6 +27,8 @@ export const OnboardingHeader = observer(function OnboardingHeader(props: Onboar const { currentStep, updateCurrentStep, hasInvitations } = props; // store hooks const { data: user } = useUser(); + const { config: instanceConfig } = useInstance(); + const isSelfManaged = instanceConfig?.is_self_managed; // handle step back const handleStepBack = () => { @@ -37,7 +40,7 @@ export const OnboardingHeader = observer(function OnboardingHeader(props: Onboar updateCurrentStep(EOnboardingSteps.ROLE_SETUP); break; case EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN: - updateCurrentStep(EOnboardingSteps.USE_CASE_SETUP); + updateCurrentStep(isSelfManaged ? EOnboardingSteps.PROFILE_SETUP : EOnboardingSteps.USE_CASE_SETUP); break; } }; @@ -45,22 +48,18 @@ export const OnboardingHeader = observer(function OnboardingHeader(props: Onboar // can go back const canGoBack = ![EOnboardingSteps.PROFILE_SETUP, EOnboardingSteps.INVITE_MEMBERS].includes(currentStep); - // Get current step number for progress tracking - const getCurrentStepNumber = (): number => { - const stepOrder: TOnboardingStep[] = [ - EOnboardingSteps.PROFILE_SETUP, - EOnboardingSteps.ROLE_SETUP, - EOnboardingSteps.USE_CASE_SETUP, - ...(hasInvitations - ? [EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN] - : [EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN, EOnboardingSteps.INVITE_MEMBERS]), - ]; - return stepOrder.indexOf(currentStep) + 1; - }; + // step order for progress tracking — include INVITE_MEMBERS if user is currently on it + const showInviteStep = !hasInvitations || currentStep === EOnboardingSteps.INVITE_MEMBERS; + const stepOrder: TOnboardingStep[] = [ + EOnboardingSteps.PROFILE_SETUP, + ...(isSelfManaged ? [] : [EOnboardingSteps.ROLE_SETUP, EOnboardingSteps.USE_CASE_SETUP]), + EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN, + ...(showInviteStep ? [EOnboardingSteps.INVITE_MEMBERS] : []), + ]; // derived values - const currentStepNumber = getCurrentStepNumber(); - const totalSteps = hasInvitations ? 4 : 5; // 4 if invites available, 5 if not + const currentStepNumber = stepOrder.indexOf(currentStep) + 1; + const totalSteps = stepOrder.length; const userName = user?.display_name ? user?.display_name : user?.first_name diff --git a/apps/web/core/components/onboarding/root.tsx b/apps/web/core/components/onboarding/root.tsx index cc8e7cfe41f..395e19b0957 100644 --- a/apps/web/core/components/onboarding/root.tsx +++ b/apps/web/core/components/onboarding/root.tsx @@ -11,6 +11,7 @@ import { TOAST_TYPE, setToast } from "@plane/propel/toast"; import type { IWorkspaceMemberInvitation, TOnboardingStep, TOnboardingSteps, TUserProfile } from "@plane/types"; import { EOnboardingSteps } from "@plane/types"; // hooks +import { useInstance } from "@/hooks/store/use-instance"; import { useWorkspace } from "@/hooks/store/use-workspace"; import { useUser, useUserProfile } from "@/hooks/store/user"; // local components @@ -27,8 +28,10 @@ export const OnboardingRoot = observer(function OnboardingRoot({ invitations = [ const { data: user } = useUser(); const { data: userProfile, updateUserProfile, finishUserOnboarding } = useUserProfile(); const { workspaces } = useWorkspace(); + const { config: instanceConfig } = useInstance(); const workspacesList = Object.values(workspaces ?? {}); + const isSelfManaged = instanceConfig?.is_self_managed; // Calculate total steps based on whether invitations are available const hasInvitations = invitations.length > 0; @@ -68,7 +71,14 @@ export const OnboardingRoot = observer(function OnboardingRoot({ invitations = [ (step: EOnboardingSteps, skipInvites?: boolean) => { switch (step) { case EOnboardingSteps.PROFILE_SETUP: - setCurrentStep(EOnboardingSteps.ROLE_SETUP); + if (isSelfManaged) { + // Skip role & use case steps for self-hosted + stepChange({ profile_complete: true }); + if (workspacesList.length > 0) finishOnboarding(); + else setCurrentStep(EOnboardingSteps.WORKSPACE_CREATE_OR_JOIN); + } else { + setCurrentStep(EOnboardingSteps.ROLE_SETUP); + } break; case EOnboardingSteps.ROLE_SETUP: setCurrentStep(EOnboardingSteps.USE_CASE_SETUP); @@ -91,7 +101,7 @@ export const OnboardingRoot = observer(function OnboardingRoot({ invitations = [ break; } }, - [stepChange, finishOnboarding, workspacesList] + [stepChange, finishOnboarding, workspacesList, isSelfManaged] ); const updateCurrentStep = (step: EOnboardingSteps) => setCurrentStep(step);