feat: skip license page for cloud billing users (#41102)
## 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" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/16167808138> > Commit: ab4247c9e01d23159f07451f3014f76fa313134e > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=16167808138&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity, @tag.Authentication, @tag.LicenseAndBilling` > Spec: > <hr>Wed, 09 Jul 2025 12:00:44 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## 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. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
3981590006
commit
7282f64dcf
|
|
@ -1,7 +1,7 @@
|
||||||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||||
import { requiresAuth } from "pages/UserAuth/requiresAuthHOC";
|
import { requiresAuth } from "pages/UserAuth/requiresAuthHOC";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useCallback } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { getCurrentUser } from "selectors/usersSelectors";
|
import { getCurrentUser } from "selectors/usersSelectors";
|
||||||
|
|
@ -16,6 +16,7 @@ import { redirectUserAfterSignup } from "ee/utils/signupHelpers";
|
||||||
import { setUserSignedUpFlag } from "utils/storage";
|
import { setUserSignedUpFlag } from "utils/storage";
|
||||||
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
|
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
|
||||||
import { getIsAiAgentInstanceEnabled } from "ee/selectors/aiAgentSelectors";
|
import { getIsAiAgentInstanceEnabled } from "ee/selectors/aiAgentSelectors";
|
||||||
|
import { useIsCloudBillingEnabled } from "hooks/useIsCloudBillingEnabled";
|
||||||
|
|
||||||
export function SignupSuccess() {
|
export function SignupSuccess() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
@ -25,37 +26,50 @@ export function SignupSuccess() {
|
||||||
"enableFirstTimeUserExperience",
|
"enableFirstTimeUserExperience",
|
||||||
);
|
);
|
||||||
const isAiAgentInstanceEnabled = useSelector(getIsAiAgentInstanceEnabled);
|
const isAiAgentInstanceEnabled = useSelector(getIsAiAgentInstanceEnabled);
|
||||||
|
const isMultiOrgEnabled = useIsCloudBillingEnabled();
|
||||||
const validLicense = useSelector(isValidLicense);
|
const validLicense = useSelector(isValidLicense);
|
||||||
const user = useSelector(getCurrentUser);
|
const user = useSelector(getCurrentUser);
|
||||||
const isOnLoginPage = !useSelector(isWithinAnOrganization);
|
const isOnLoginPage = !useSelector(isWithinAnOrganization);
|
||||||
|
|
||||||
|
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
user?.email && setUserSignedUpFlag(user?.email);
|
user?.email && setUserSignedUpFlag(user?.email);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const isNonInvitedUser = shouldEnableFirstTimeUserOnboarding === "true";
|
const isNonInvitedUser = shouldEnableFirstTimeUserOnboarding === "true";
|
||||||
|
|
||||||
const redirectUsingQueryParam = useCallback(
|
const redirectUsingQueryParam = useCallback(async () => {
|
||||||
() =>
|
if (isRedirecting) return;
|
||||||
redirectUserAfterSignup({
|
|
||||||
|
setIsRedirecting(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await redirectUserAfterSignup({
|
||||||
redirectUrl,
|
redirectUrl,
|
||||||
shouldEnableFirstTimeUserOnboarding,
|
shouldEnableFirstTimeUserOnboarding,
|
||||||
validLicense,
|
validLicense,
|
||||||
dispatch,
|
dispatch,
|
||||||
isAiAgentInstanceEnabled,
|
isAiAgentInstanceEnabled,
|
||||||
|
isMultiOrgEnabled,
|
||||||
isOnLoginPage,
|
isOnLoginPage,
|
||||||
}),
|
});
|
||||||
[
|
} catch (err) {
|
||||||
|
setIsRedirecting(false);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
dispatch,
|
dispatch,
|
||||||
isNonInvitedUser,
|
isNonInvitedUser,
|
||||||
isOnLoginPage,
|
isOnLoginPage,
|
||||||
redirectUrl,
|
redirectUrl,
|
||||||
shouldEnableFirstTimeUserOnboarding,
|
shouldEnableFirstTimeUserOnboarding,
|
||||||
validLicense,
|
validLicense,
|
||||||
],
|
isAiAgentInstanceEnabled,
|
||||||
);
|
isMultiOrgEnabled,
|
||||||
|
]);
|
||||||
|
|
||||||
const onGetStarted = useCallback((proficiency?: string, useCase?: string) => {
|
const onGetStarted = useCallback(
|
||||||
|
async (proficiency?: string, useCase?: string) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ReduxActionTypes.UPDATE_USER_DETAILS_INIT,
|
type: ReduxActionTypes.UPDATE_USER_DETAILS_INIT,
|
||||||
payload: {
|
payload: {
|
||||||
|
|
@ -67,8 +81,23 @@ export function SignupSuccess() {
|
||||||
proficiency,
|
proficiency,
|
||||||
goal: useCase,
|
goal: useCase,
|
||||||
});
|
});
|
||||||
|
await redirectUsingQueryParam();
|
||||||
|
},
|
||||||
|
[redirectUsingQueryParam],
|
||||||
|
);
|
||||||
|
|
||||||
|
const shouldAutoRedirect =
|
||||||
|
user?.isSuperUser ||
|
||||||
|
((user?.role || user?.proficiency) && user?.useCase) ||
|
||||||
|
shouldEnableFirstTimeUserOnboarding !== "true" ||
|
||||||
|
isAiAgentInstanceEnabled ||
|
||||||
|
isMultiOrgEnabled;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (shouldAutoRedirect && !isRedirecting) {
|
||||||
redirectUsingQueryParam();
|
redirectUsingQueryParam();
|
||||||
}, []);
|
}
|
||||||
|
}, [shouldAutoRedirect, redirectUsingQueryParam, isRedirecting]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Proceed with redirection,
|
* Proceed with redirection,
|
||||||
|
|
@ -78,15 +107,7 @@ export function SignupSuccess() {
|
||||||
* We identify an invited user based on `enableFirstTimeUserExperience` flag in url.
|
* 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.
|
//TODO(Balaji): Factor in case, where user had closed the tab, while filling the form.And logs back in again.
|
||||||
if (
|
if (shouldAutoRedirect) {
|
||||||
user?.isSuperUser ||
|
|
||||||
((user?.role || user?.proficiency) && user?.useCase) ||
|
|
||||||
shouldEnableFirstTimeUserOnboarding !== "true" ||
|
|
||||||
isAiAgentInstanceEnabled
|
|
||||||
) {
|
|
||||||
redirectUsingQueryParam();
|
|
||||||
|
|
||||||
// Showing a loader until the redirect
|
|
||||||
return (
|
return (
|
||||||
<Center>
|
<Center>
|
||||||
<Spinner size="lg" />
|
<Spinner size="lg" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user