From 7282f64dcfe5a23a0471159982a2c27acbe17a4e Mon Sep 17 00:00:00 2001 From: Jacques Ikot Date: Thu, 10 Jul 2025 21:42:42 +0100 Subject: [PATCH] feat: skip license page for cloud billing users (#41102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This PR enhances the signup success flow to automatically skip the license page when cloud billing is enabled, providing a smoother onboarding experience for cloud users. ## Key Changes ### 🚀 New Features - Added cloud billing detection using `useIsCloudBillingEnabled()` hook - Implemented automatic license page skipping for cloud billing users - Enhanced redirect logic with proper async/await handling ### 🔧 Improvements - Added redirect state management to prevent race conditions - Improved error handling in redirect flow with try-catch blocks - Extracted redirect conditions into `shouldAutoRedirect` variable for better readability - Added redirect protection to prevent multiple simultaneous redirects ### 🛠️ Technical Details - Added `isMultiOrgEnabled` flag to signup redirect parameters - Made `redirectUsingQueryParam` and `onGetStarted` functions async - Implemented `isRedirecting` state to track redirect status - Added proper dependency management in useEffect and useCallback hooks ## Impact - **Cloud billing users** will now bypass the license page automatically - **Improved UX** with more robust redirect handling and loading states - **Better performance** by preventing unnecessary redirect attempts - **Enhanced reliability** with proper error handling and state management ## Automation /ok-to-test tags="@tag.Sanity, @tag.Authentication, @tag.LicenseAndBilling" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: ab4247c9e01d23159f07451f3014f76fa313134e > Cypress dashboard. > Tags: `@tag.Sanity, @tag.Authentication, @tag.LicenseAndBilling` > Spec: >
Wed, 09 Jul 2025 12:00:44 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No ## Summary by CodeRabbit * **New Features** * Improved signup success experience with smarter automatic redirection based on user status and organization settings. * Added a loading spinner during redirection for better user feedback. * **Bug Fixes** * Prevented multiple redirects from occurring at the same time. --- app/client/src/pages/setup/SignupSuccess.tsx | 93 ++++++++++++-------- 1 file changed, 57 insertions(+), 36 deletions(-) diff --git a/app/client/src/pages/setup/SignupSuccess.tsx b/app/client/src/pages/setup/SignupSuccess.tsx index af8ee38754..2cf3e9e9db 100644 --- a/app/client/src/pages/setup/SignupSuccess.tsx +++ b/app/client/src/pages/setup/SignupSuccess.tsx @@ -1,7 +1,7 @@ import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import { requiresAuth } from "pages/UserAuth/requiresAuthHOC"; import React from "react"; -import { useCallback } from "react"; +import { useCallback, useState } from "react"; import { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { getCurrentUser } from "selectors/usersSelectors"; @@ -16,6 +16,7 @@ import { redirectUserAfterSignup } from "ee/utils/signupHelpers"; import { setUserSignedUpFlag } from "utils/storage"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { getIsAiAgentInstanceEnabled } from "ee/selectors/aiAgentSelectors"; +import { useIsCloudBillingEnabled } from "hooks/useIsCloudBillingEnabled"; export function SignupSuccess() { const dispatch = useDispatch(); @@ -25,50 +26,78 @@ export function SignupSuccess() { "enableFirstTimeUserExperience", ); const isAiAgentInstanceEnabled = useSelector(getIsAiAgentInstanceEnabled); + const isMultiOrgEnabled = useIsCloudBillingEnabled(); const validLicense = useSelector(isValidLicense); const user = useSelector(getCurrentUser); const isOnLoginPage = !useSelector(isWithinAnOrganization); + const [isRedirecting, setIsRedirecting] = useState(false); + useEffect(() => { user?.email && setUserSignedUpFlag(user?.email); }, []); const isNonInvitedUser = shouldEnableFirstTimeUserOnboarding === "true"; - const redirectUsingQueryParam = useCallback( - () => - redirectUserAfterSignup({ + const redirectUsingQueryParam = useCallback(async () => { + if (isRedirecting) return; + + setIsRedirecting(true); + + try { + await redirectUserAfterSignup({ redirectUrl, shouldEnableFirstTimeUserOnboarding, validLicense, dispatch, isAiAgentInstanceEnabled, + isMultiOrgEnabled, isOnLoginPage, - }), - [ - dispatch, - isNonInvitedUser, - isOnLoginPage, - redirectUrl, - shouldEnableFirstTimeUserOnboarding, - validLicense, - ], + }); + } catch (err) { + setIsRedirecting(false); + } + }, [ + dispatch, + isNonInvitedUser, + isOnLoginPage, + redirectUrl, + shouldEnableFirstTimeUserOnboarding, + validLicense, + isAiAgentInstanceEnabled, + isMultiOrgEnabled, + ]); + + const onGetStarted = useCallback( + async (proficiency?: string, useCase?: string) => { + dispatch({ + type: ReduxActionTypes.UPDATE_USER_DETAILS_INIT, + payload: { + proficiency, + useCase, + }, + }); + AnalyticsUtil.logEvent("GET_STARTED_CLICKED", { + proficiency, + goal: useCase, + }); + await redirectUsingQueryParam(); + }, + [redirectUsingQueryParam], ); - const onGetStarted = useCallback((proficiency?: string, useCase?: string) => { - dispatch({ - type: ReduxActionTypes.UPDATE_USER_DETAILS_INIT, - payload: { - proficiency, - useCase, - }, - }); - AnalyticsUtil.logEvent("GET_STARTED_CLICKED", { - proficiency, - goal: useCase, - }); - redirectUsingQueryParam(); - }, []); + const shouldAutoRedirect = + user?.isSuperUser || + ((user?.role || user?.proficiency) && user?.useCase) || + shouldEnableFirstTimeUserOnboarding !== "true" || + isAiAgentInstanceEnabled || + isMultiOrgEnabled; + + useEffect(() => { + if (shouldAutoRedirect && !isRedirecting) { + redirectUsingQueryParam(); + } + }, [shouldAutoRedirect, redirectUsingQueryParam, isRedirecting]); /* * Proceed with redirection, @@ -78,15 +107,7 @@ export function SignupSuccess() { * We identify an invited user based on `enableFirstTimeUserExperience` flag in url. */ //TODO(Balaji): Factor in case, where user had closed the tab, while filling the form.And logs back in again. - if ( - user?.isSuperUser || - ((user?.role || user?.proficiency) && user?.useCase) || - shouldEnableFirstTimeUserOnboarding !== "true" || - isAiAgentInstanceEnabled - ) { - redirectUsingQueryParam(); - - // Showing a loader until the redirect + if (shouldAutoRedirect) { return (