From 9f14088e8f43434a0878c73819978057cff2f1ed Mon Sep 17 00:00:00 2001 From: vikrantgupta25 Date: Thu, 5 Dec 2024 16:57:17 +0530 Subject: [PATCH] feat: syncronize the approutes file --- frontend/src/AppRoutes/index.tsx | 122 ++++++++++++++--------- frontend/src/hooks/useGetFeatureFlag.tsx | 15 +-- frontend/src/providers/App/App.tsx | 21 +++- frontend/src/providers/App/types.ts | 4 +- 4 files changed, 97 insertions(+), 65 deletions(-) diff --git a/frontend/src/AppRoutes/index.tsx b/frontend/src/AppRoutes/index.tsx index 46b7e0288f..2e31d2f440 100644 --- a/frontend/src/AppRoutes/index.tsx +++ b/frontend/src/AppRoutes/index.tsx @@ -10,7 +10,6 @@ import AppLayout from 'container/AppLayout'; import useAnalytics from 'hooks/analytics/useAnalytics'; import { KeyboardHotkeysProvider } from 'hooks/hotkeys/useKeyboardHotkeys'; import { useThemeConfig } from 'hooks/useDarkMode'; -import useFeatureFlags from 'hooks/useFeatureFlag'; import { LICENSE_PLAN_KEY } from 'hooks/useLicense'; import { NotificationProvider } from 'hooks/useNotifications'; import { ResourceProvider } from 'hooks/useResourceAttribute'; @@ -44,7 +43,9 @@ function App(): JSX.Element { isFetchingFeatureFlags, userFetchError, licensesFetchError, + featureFlagsFetchError, isLoggedIn: isLoggedInState, + featureFlags, org, } = useAppContext(); const [routes, setRoutes] = useState(defaultRoutes); @@ -55,18 +56,6 @@ function App(): JSX.Element { const isCloudUserVal = isCloudUser(); - const isChatSupportEnabled = - useFeatureFlags(FeatureKeys.CHAT_SUPPORT)?.active || false; - - const isPremiumSupportEnabled = - useFeatureFlags(FeatureKeys.PREMIUM_SUPPORT)?.active || false; - - const isOnBasicPlan = - licenses?.licenses?.some( - (license) => - license.isCurrent && license.planKey === LICENSE_PLAN_KEY.BASIC_PLAN, - ) || licenses?.licenses === null; - const enableAnalytics = (user: IUser): void => { const orgName = org && Array.isArray(org) && org.length > 0 ? org[0].name : ''; @@ -120,34 +109,49 @@ function App(): JSX.Element { }); }; + // eslint-disable-next-line sonarjs/cognitive-complexity useEffect(() => { - const isIdentifiedUser = getLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER); - - if (isLoggedInState && user && user.id && user.email && !isIdentifiedUser) { - setLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER, 'true'); - } - - if ( - isOnBasicPlan || - (isLoggedInState && user.role && user.role !== 'ADMIN') || - !(isCloudUserVal || isEECloudUser()) - ) { - const newRoutes = routes.filter((route) => route?.path !== ROUTES.BILLING); - setRoutes(newRoutes); - } - - if (isCloudUserVal || isEECloudUser()) { - const newRoutes = [...routes, SUPPORT_ROUTE]; - - setRoutes(newRoutes); - } else { - const newRoutes = [...routes, LIST_LICENSES]; - - setRoutes(newRoutes); + if (licenses && !!user.email) { + const isOnBasicPlan = + licenses.licenses?.some( + (license) => + license.isCurrent && license.planKey === LICENSE_PLAN_KEY.BASIC_PLAN, + ) || licenses.licenses === null; + + const isIdentifiedUser = getLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER); + + if (isLoggedInState && user && user.id && user.email && !isIdentifiedUser) { + setLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER, 'true'); + } + + // if the user is a cloud user + if (isCloudUserVal || isEECloudUser()) { + let updatedRoutes = routes; + // if the user is on basic plan or is not an admin then remove billing + if ( + isOnBasicPlan || + (isLoggedInState && user.role && user.role !== 'ADMIN') + ) { + updatedRoutes = updatedRoutes.filter( + (route) => route?.path !== ROUTES.BILLING, + ); + } + // always add support route for cloud users + updatedRoutes = [...updatedRoutes, SUPPORT_ROUTE]; + setRoutes(updatedRoutes); + } else { + // if not a cloud user then remove billing and add list licenses route + let updatedRoutes = routes; + updatedRoutes = updatedRoutes.filter( + (route) => route?.path !== ROUTES.BILLING, + ); + updatedRoutes = [...updatedRoutes, LIST_LICENSES]; + setRoutes(updatedRoutes); + } } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoggedInState, isOnBasicPlan, user]); + }, [isLoggedInState, user, licenses]); useEffect(() => { if (pathname === ROUTES.ONBOARDING) { @@ -165,23 +169,45 @@ function App(): JSX.Element { }, [pathname]); useEffect(() => { - const showAddCreditCardModal = - !isPremiumSupportEnabled && !licenses?.trialConvertedToSubscription; - - if (isLoggedInState && isChatSupportEnabled && !showAddCreditCardModal) { - window.Intercom('boot', { - app_id: process.env.INTERCOM_APP_ID, - email: user?.email || '', - name: user?.name || '', - }); + // feature flag shouldn't be loading and featureFlags or fetchError any one of this should be true indicating that req is complete + // licenses should also be present. there is no check for licenses for loading and error as that is mandatory if not present then routing + // to something went wrong which would ideally need a reload. + if ( + !isFetchingFeatureFlags && + (featureFlags || featureFlagsFetchError) && + licenses + ) { + let isChatSupportEnabled = false; + let isPremiumSupportEnabled = false; + if (featureFlags && featureFlags.length > 0) { + isChatSupportEnabled = + featureFlags.find((flag) => flag.name === FeatureKeys.CHAT_SUPPORT) + ?.active || false; + + isPremiumSupportEnabled = + featureFlags.find((flag) => flag.name === FeatureKeys.PREMIUM_SUPPORT) + ?.active || false; + } + const showAddCreditCardModal = + !isPremiumSupportEnabled && !licenses.trialConvertedToSubscription; + + if (isLoggedInState && isChatSupportEnabled && !showAddCreditCardModal) { + window.Intercom('boot', { + app_id: process.env.INTERCOM_APP_ID, + email: user?.email || '', + name: user?.name || '', + }); + } } }, [ isLoggedInState, - isChatSupportEnabled, user, - isPremiumSupportEnabled, pathname, licenses?.trialConvertedToSubscription, + featureFlags, + isFetchingFeatureFlags, + featureFlagsFetchError, + licenses, ]); useEffect(() => { diff --git a/frontend/src/hooks/useGetFeatureFlag.tsx b/frontend/src/hooks/useGetFeatureFlag.tsx index e13893d056..4c9d3b0bd7 100644 --- a/frontend/src/hooks/useGetFeatureFlag.tsx +++ b/frontend/src/hooks/useGetFeatureFlag.tsx @@ -1,23 +1,18 @@ import getFeaturesFlags from 'api/features/getFeatureFlags'; import { REACT_QUERY_KEY } from 'constants/reactQueryKeys'; import { useQuery, UseQueryResult } from 'react-query'; -import { useSelector } from 'react-redux'; -import { AppState } from 'store/reducers'; import { FeatureFlagProps } from 'types/api/features/getFeaturesFlags'; const useGetFeatureFlag = ( onSuccessHandler: (routes: FeatureFlagProps[]) => void, -): UseQueryResult => { - const userId: string = useSelector( - (state) => state.app.user?.userId || '', - ); - - return useQuery({ + userEmail: string, +): UseQueryResult => + useQuery({ queryFn: getFeaturesFlags, - queryKey: [REACT_QUERY_KEY.GET_FEATURES_FLAGS, userId], + queryKey: [REACT_QUERY_KEY.GET_FEATURES_FLAGS, userEmail], onSuccess: onSuccessHandler, retryOnMount: false, + enabled: !!userEmail, }); -}; export default useGetFeatureFlag; diff --git a/frontend/src/providers/App/App.tsx b/frontend/src/providers/App/App.tsx index 46e13ba5a7..5631345a57 100644 --- a/frontend/src/providers/App/App.tsx +++ b/frontend/src/providers/App/App.tsx @@ -36,9 +36,11 @@ export function AppProvider({ children }: PropsWithChildren): JSX.Element { setActiveLicenseV3, ] = useState(null); const [featureFlags, setFeatureFlags] = useState(null); - const [orgPreferences, setOrgPreferences] = useState([]); + const [orgPreferences, setOrgPreferences] = useState( + null, + ); const [isLoggedIn, setIsLoggedIn] = useState(false); - const [org, setOrg] = useState([]); + const [org, setOrg] = useState(null); // fetcher for user const { @@ -55,6 +57,17 @@ export function AppProvider({ children }: PropsWithChildren): JSX.Element { setLocalStorageApi(LOCALSTORAGE.IS_LOGGED_IN, 'true'); setIsLoggedIn(true); setOrg((prev) => { + if (!prev) { + return [ + { + createdAt: 0, + hasOptedUpdates: false, + id: userData.payload.orgId, + isAnonymous: false, + name: userData.payload.organization, + }, + ]; + } const orgIndex = prev.findIndex((e) => e.id === userData.payload.orgId); const updatedOrg: Organization[] = [ @@ -110,7 +123,7 @@ export function AppProvider({ children }: PropsWithChildren): JSX.Element { error: featureFlagsFetchError, } = useGetFeatureFlag((allFlags: FeatureFlags[]) => { setFeatureFlags(allFlags); - }); + }, user.email); const { data: orgPreferencesData, @@ -140,8 +153,6 @@ export function AppProvider({ children }: PropsWithChildren): JSX.Element { } }); - console.log(user, licenseData, activeLicenseV3, featureFlags); - // return value for the context const value: IAppContext = useMemo( () => ({ diff --git a/frontend/src/providers/App/types.ts b/frontend/src/providers/App/types.ts index bc1c7e56c3..3c075ce26f 100644 --- a/frontend/src/providers/App/types.ts +++ b/frontend/src/providers/App/types.ts @@ -10,9 +10,9 @@ export interface IAppContext { licenses: LicensesResModel | null; activeLicenseV3: LicenseV3ResModel | null; featureFlags: FeatureFlags[] | null; - orgPreferences: OrgPreference[]; + orgPreferences: OrgPreference[] | null; isLoggedIn: boolean; - org: Organization[]; + org: Organization[] | null; isFetchingUser: boolean; isFetchingLicenses: boolean; isFetchingActiveLicenseV3: boolean;