Fixing Singup sequence FLASHING💥 (#11371)
After investiagting the different options ([see related issue](https://github.com/twentyhq/core-team-issues/issues/660#issuecomment-2766030972)) I decided to add a "Verify Component" and a to build a custom Layout for this route. Reason I cannot use the default one is to have all preloaded once the user changes website and lands on the verify route. Reason I did not modify the DefaultLayout to match our need is that is would require many changes in order to avoid preloading states for our specific usecase. Fixes https://github.com/twentyhq/core-team-issues/issues/660 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -16,8 +16,8 @@ import { PrefetchDataProvider } from '@/prefetch/components/PrefetchDataProvider
|
||||
import { DialogManager } from '@/ui/feedback/dialog-manager/components/DialogManager';
|
||||
import { DialogManagerScope } from '@/ui/feedback/dialog-manager/scopes/DialogManagerScope';
|
||||
import { SnackBarProvider } from '@/ui/feedback/snack-bar-manager/components/SnackBarProvider';
|
||||
import { UserThemeProviderEffect } from '@/ui/theme/components/AppThemeProvider';
|
||||
import { BaseThemeProvider } from '@/ui/theme/components/BaseThemeProvider';
|
||||
import { UserThemeProviderEffect } from '@/ui/theme/components/UserThemeProviderEffect';
|
||||
import { PageFavicon } from '@/ui/utilities/page-favicon/components/PageFavicon';
|
||||
import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
|
||||
import { ServerPreconnect } from '@/ui/utilities/server-preconnect/components/ServerPreconnect';
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
useLocation,
|
||||
useNavigate,
|
||||
useParams,
|
||||
useSearchParams,
|
||||
} from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
@ -13,6 +14,7 @@ import {
|
||||
} from '@/analytics/hooks/useEventTracker';
|
||||
import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken';
|
||||
import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState';
|
||||
import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPath';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
|
||||
@ -21,10 +23,9 @@ import { AppPath } from '@/types/AppPath';
|
||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||
import { usePageChangeEffectNavigateLocation } from '~/hooks/usePageChangeEffectNavigateLocation';
|
||||
import { isCaptchaRequiredForPath } from '@/captcha/utils/isCaptchaRequiredForPath';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
// TODO: break down into smaller functions and / or hooks
|
||||
// - moved usePageChangeEffectNavigateLocation into dedicated hook
|
||||
@ -58,11 +59,16 @@ export const PageChangeEffect = () => {
|
||||
}
|
||||
}, [location, previousLocation]);
|
||||
|
||||
const [searchParams] = useSearchParams();
|
||||
const navigationParams = searchParams.get('animateModal')
|
||||
? `?animateModal=${searchParams.get('animateModal')}`
|
||||
: '';
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(pageChangeEffectNavigateLocation)) {
|
||||
navigate(pageChangeEffectNavigateLocation);
|
||||
navigate(pageChangeEffectNavigateLocation + navigationParams);
|
||||
}
|
||||
}, [navigate, pageChangeEffectNavigateLocation]);
|
||||
}, [navigate, pageChangeEffectNavigateLocation, navigationParams]);
|
||||
|
||||
useEffect(() => {
|
||||
const isLeavingRecordIndexPage = !!matchPath(
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { AppRouterProviders } from '@/app/components/AppRouterProviders';
|
||||
import { SettingsRoutes } from '@/app/components/SettingsRoutes';
|
||||
import { Verify } from '@/auth/components/Verify';
|
||||
|
||||
import { VerifyEffect } from '@/auth/components/VerifyEffect';
|
||||
import { VerifyEmailEffect } from '@/auth/components/VerifyEmailEffect';
|
||||
import indexAppPath from '@/navigation/utils/indexAppPath';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { BlankLayout } from '@/ui/layout/page/components/BlankLayout';
|
||||
import { DefaultLayout } from '@/ui/layout/page/components/DefaultLayout';
|
||||
|
||||
import {
|
||||
createBrowserRouter,
|
||||
createRoutesFromElements,
|
||||
@ -38,7 +39,7 @@ export const useCreateAppRouter = (
|
||||
loader={async () => Promise.resolve(null)}
|
||||
>
|
||||
<Route element={<DefaultLayout />}>
|
||||
<Route path={AppPath.Verify} element={<VerifyEffect />} />
|
||||
<Route path={AppPath.Verify} element={<Verify />} />
|
||||
<Route path={AppPath.VerifyEmail} element={<VerifyEmailEffect />} />
|
||||
<Route path={AppPath.SignInUp} element={<SignInUp />} />
|
||||
<Route path={AppPath.Invite} element={<SignInUp />} />
|
||||
|
||||
@ -8,10 +8,20 @@ const StyledContent = styled(Modal.Content)`
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
type AuthModalProps = { children: React.ReactNode };
|
||||
type AuthModalProps = {
|
||||
children: React.ReactNode;
|
||||
isOpenAnimated?: boolean;
|
||||
};
|
||||
|
||||
export const AuthModal = ({ children }: AuthModalProps) => (
|
||||
<Modal padding={'none'} modalVariant="primary">
|
||||
export const AuthModal = ({
|
||||
children,
|
||||
isOpenAnimated = true,
|
||||
}: AuthModalProps) => (
|
||||
<Modal
|
||||
padding={'none'}
|
||||
modalVariant="primary"
|
||||
isOpenAnimated={isOpenAnimated}
|
||||
>
|
||||
<ScrollWrapper componentInstanceId="scroll-wrapper-modal-content">
|
||||
<StyledContent>{children}</StyledContent>
|
||||
</ScrollWrapper>
|
||||
|
||||
@ -6,10 +6,11 @@ import { useVerifyLogin } from '@/auth/hooks/useVerifyLogin';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
import { SignInUpLoading } from '~/pages/auth/SignInUpLoading';
|
||||
|
||||
export const VerifyEffect = () => {
|
||||
export const Verify = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const loginToken = searchParams.get('loginToken');
|
||||
const errorMessage = searchParams.get('errorMessage');
|
||||
@ -36,5 +37,5 @@ export const VerifyEffect = () => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return <></>;
|
||||
return <SignInUpLoading />;
|
||||
};
|
||||
@ -3,14 +3,14 @@ import { AppPath } from '@/types/AppPath';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
|
||||
import { useVerifyLogin } from '@/auth/hooks/useVerifyLogin';
|
||||
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
import { EmailVerificationSent } from '../sign-in-up/components/EmailVerificationSent';
|
||||
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
|
||||
import { useVerifyLogin } from '@/auth/hooks/useVerifyLogin';
|
||||
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
|
||||
import { EmailVerificationSent } from '../sign-in-up/components/EmailVerificationSent';
|
||||
|
||||
export const VerifyEmailEffect = () => {
|
||||
const { getLoginTokenFromEmailVerificationToken } = useAuth();
|
||||
@ -50,6 +50,7 @@ export const VerifyEmailEffect = () => {
|
||||
if (workspaceUrl.slice(0, -1) !== window.location.origin) {
|
||||
return redirectToWorkspaceDomain(workspaceUrl, AppPath.Verify, {
|
||||
loginToken: loginToken.token,
|
||||
animateModal: false,
|
||||
});
|
||||
}
|
||||
verifyLoginToken(loginToken.token);
|
||||
|
||||
@ -416,6 +416,7 @@ export const useAuth = () => {
|
||||
{
|
||||
...(!isEmailVerificationRequired && {
|
||||
loginToken: signUpResult.data.signUp.loginToken.token,
|
||||
animateModal: false,
|
||||
}),
|
||||
email,
|
||||
},
|
||||
|
||||
@ -2,6 +2,8 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { clientConfigApiStatusState } from '@/client-config/states/clientConfigApiStatusState';
|
||||
import { AppFullScreenErrorFallback } from '@/error-handler/components/AppFullScreenErrorFallback';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||
|
||||
export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
@ -10,8 +12,15 @@ export const ClientConfigProvider: React.FC<React.PropsWithChildren> = ({
|
||||
clientConfigApiStatusState,
|
||||
);
|
||||
|
||||
const { isMatchingLocation } = useIsMatchingLocation();
|
||||
|
||||
// TODO: Implement a better loading strategy
|
||||
if (!isLoaded) return null;
|
||||
if (
|
||||
!isLoaded &&
|
||||
!isMatchingLocation(AppPath.Verify) &&
|
||||
!isMatchingLocation(AppPath.VerifyEmail)
|
||||
)
|
||||
return null;
|
||||
|
||||
return isErrored && error instanceof Error ? (
|
||||
<AppFullScreenErrorFallback
|
||||
|
||||
@ -10,7 +10,6 @@ export const ObjectMetadataItemsProvider = ({
|
||||
children,
|
||||
}: React.PropsWithChildren) => {
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
const shouldDisplayChildren = objectMetadataItems.length > 0;
|
||||
|
||||
return (
|
||||
|
||||
@ -13,7 +13,7 @@ export const useImpersonationRedirect = () => {
|
||||
return redirectToWorkspaceDomain(
|
||||
getWorkspaceUrl(workspaceUrls),
|
||||
AppPath.Verify,
|
||||
{ loginToken },
|
||||
{ loginToken, animateModal: false },
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -56,16 +56,16 @@ const getResult = (isDefaultLayoutAuthModalVisible = true) =>
|
||||
|
||||
// prettier-ignore
|
||||
const testCases = [
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.COMPLETED, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Unpaid, onboardingStatus: OnboardingStatus.COMPLETED, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.PastDue, onboardingStatus: OnboardingStatus.COMPLETED, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: false, subscriptionStatus: undefined, onboardingStatus: undefined, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.WORKSPACE_ACTIVATION, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.PROFILE_CREATION, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.COMPLETED, res: false },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.COMPLETED, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Unpaid, onboardingStatus: OnboardingStatus.COMPLETED, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.PastDue, onboardingStatus: OnboardingStatus.COMPLETED, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: false, subscriptionStatus: undefined, onboardingStatus: undefined, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.WORKSPACE_ACTIVATION, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.PROFILE_CREATION, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: true },
|
||||
{ loc: AppPath.Verify, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.COMPLETED, res: true },
|
||||
|
||||
{ loc: AppPath.VerifyEmail, isLogged: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: true },
|
||||
{ loc: AppPath.VerifyEmail, isLogged: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.COMPLETED, res: true },
|
||||
|
||||
@ -6,9 +6,9 @@ import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { isDefaultLayoutAuthModalVisibleState } from '@/ui/layout/states/isDefaultLayoutAuthModalVisibleState';
|
||||
import { useSubscriptionStatus } from '@/workspace/hooks/useSubscriptionStatus';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { OnboardingStatus, SubscriptionStatus } from '~/generated/graphql';
|
||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useShowAuthModal = () => {
|
||||
const { isMatchingLocation } = useIsMatchingLocation();
|
||||
@ -21,8 +21,11 @@ export const useShowAuthModal = () => {
|
||||
);
|
||||
|
||||
return useMemo(() => {
|
||||
if (isMatchingLocation(AppPath.Verify)) {
|
||||
return false;
|
||||
if (
|
||||
isMatchingLocation(AppPath.Verify) ||
|
||||
isMatchingLocation(AppPath.VerifyEmail)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
useListenClickOutside,
|
||||
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
@ -148,6 +149,7 @@ export type ModalProps = React.PropsWithChildren & {
|
||||
className?: string;
|
||||
hotkeyScope?: ModalHotkeyScope;
|
||||
onEnter?: () => void;
|
||||
isOpenAnimated?: boolean;
|
||||
modalVariant?: ModalVariants;
|
||||
} & (
|
||||
| { isClosable: true; onClose: () => void }
|
||||
@ -170,6 +172,7 @@ export const Modal = ({
|
||||
isClosable = false,
|
||||
onClose,
|
||||
modalVariant = 'primary',
|
||||
isOpenAnimated = true,
|
||||
}: ModalProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
@ -223,6 +226,8 @@ export const Modal = ({
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<StyledBackDrop
|
||||
className="modal-backdrop"
|
||||
@ -233,12 +238,13 @@ export const Modal = ({
|
||||
ref={modalRef}
|
||||
size={size}
|
||||
padding={padding}
|
||||
initial="hidden"
|
||||
initial={isOpenAnimated ? 'hidden' : 'visible'}
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
layout
|
||||
modalVariant={modalVariant}
|
||||
variants={modalAnimation}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
className={className}
|
||||
isMobile={isMobile}
|
||||
>
|
||||
|
||||
@ -17,7 +17,7 @@ import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { Global, css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { AnimatePresence, LayoutGroup, motion } from 'framer-motion';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { Outlet, useSearchParams } from 'react-router-dom';
|
||||
import { useScreenSize } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledLayout = styled.div`
|
||||
@ -63,6 +63,8 @@ export const DefaultLayout = () => {
|
||||
const windowsWidth = useScreenSize().width;
|
||||
const showAuthModal = useShowAuthModal();
|
||||
const useShowFullScreen = useShowFullscreen();
|
||||
const [searchParams] = useSearchParams();
|
||||
const animateModal = searchParams.get('animateModal') !== 'false';
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -86,7 +88,9 @@ export const DefaultLayout = () => {
|
||||
2
|
||||
: 0,
|
||||
}}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
transition={{
|
||||
duration: theme.animation.duration.normal,
|
||||
}}
|
||||
>
|
||||
{!showAuthModal && (
|
||||
<>
|
||||
@ -104,7 +108,7 @@ export const DefaultLayout = () => {
|
||||
<SignInBackgroundMockPage />
|
||||
<AnimatePresence mode="wait">
|
||||
<LayoutGroup>
|
||||
<AuthModal>
|
||||
<AuthModal isOpenAnimated={animateModal}>
|
||||
<Outlet />
|
||||
</AuthModal>
|
||||
</LayoutGroup>
|
||||
|
||||
@ -1,30 +1,27 @@
|
||||
import { DEFAULT_WORKSPACE_LOGO } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceLogo';
|
||||
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { Workspaces, workspacesState } from '@/auth/states/workspaces';
|
||||
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useBuildWorkspaceUrl } from '@/domain-manager/hooks/useBuildWorkspaceUrl';
|
||||
import { multiWorkspaceDropdownState } from '@/ui/navigation/navigation-drawer/states/multiWorkspaceDropdownState';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MultiWorkspaceDropdownId';
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { Workspaces, workspacesState } from '@/auth/states/workspaces';
|
||||
import { useBuildWorkspaceUrl } from '@/domain-manager/hooks/useBuildWorkspaceUrl';
|
||||
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { useSignUpInNewWorkspaceMutation } from '~/generated/graphql';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { SelectHotkeyScope } from '@/ui/input/types/SelectHotkeyScope';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MultiWorkspaceDropdownId';
|
||||
import { multiWorkspaceDropdownState } from '@/ui/navigation/navigation-drawer/states/multiWorkspaceDropdownState';
|
||||
import { useColorScheme } from '@/ui/theme/hooks/useColorScheme';
|
||||
import styled from '@emotion/styled';
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import {
|
||||
Avatar,
|
||||
IconDotsVertical,
|
||||
@ -39,6 +36,9 @@ import {
|
||||
MenuItemSelectAvatar,
|
||||
UndecoratedLink,
|
||||
} from 'twenty-ui/navigation';
|
||||
import { useSignUpInNewWorkspaceMutation } from '~/generated/graphql';
|
||||
import { getWorkspaceUrl } from '~/utils/getWorkspaceUrl';
|
||||
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
|
||||
|
||||
const StyledDescription = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
@ -79,6 +79,7 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
|
||||
AppPath.Verify,
|
||||
{
|
||||
loginToken: data.signUpInNewWorkspace.loginToken.token,
|
||||
animateModal: false,
|
||||
},
|
||||
'_blank',
|
||||
);
|
||||
|
||||
@ -15,6 +15,8 @@ export const UserProvider = ({ children }: React.PropsWithChildren) => {
|
||||
const dateTimeFormat = useRecoilValue(dateTimeFormatState);
|
||||
|
||||
return !isCurrentUserLoaded &&
|
||||
!isMatchingLocation(AppPath.Verify) &&
|
||||
!isMatchingLocation(AppPath.VerifyEmail) &&
|
||||
!isMatchingLocation(AppPath.CreateWorkspace) ? (
|
||||
<UserOrMetadataLoader />
|
||||
) : (
|
||||
|
||||
@ -3,8 +3,8 @@ import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadingState';
|
||||
import { workspacesState } from '@/auth/states/workspaces';
|
||||
@ -16,15 +16,18 @@ import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';
|
||||
import { detectTimeZone } from '@/localization/utils/detectTimeZone';
|
||||
import { getDateFormatFromWorkspaceDateFormat } from '@/localization/utils/getDateFormatFromWorkspaceDateFormat';
|
||||
import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTimeFormatFromWorkspaceTimeFormat';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
||||
import { WorkspaceMember } from '~/generated-metadata/graphql';
|
||||
import { useGetCurrentUserQuery } from '~/generated/graphql';
|
||||
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
|
||||
import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WorkspaceMember } from '~/generated-metadata/graphql';
|
||||
import { useGetCurrentUserQuery } from '~/generated/graphql';
|
||||
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||
import { dynamicActivate } from '~/utils/i18n/dynamicActivate';
|
||||
|
||||
export const UserProviderEffect = () => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const { isMatchingLocation } = useIsMatchingLocation();
|
||||
|
||||
const [isCurrentUserLoaded, setIsCurrentUserLoaded] = useRecoilState(
|
||||
isCurrentUserLoadedState,
|
||||
@ -44,7 +47,10 @@ export const UserProviderEffect = () => {
|
||||
);
|
||||
|
||||
const { loading: queryLoading, data: queryData } = useGetCurrentUserQuery({
|
||||
skip: isCurrentUserLoaded,
|
||||
skip:
|
||||
isCurrentUserLoaded ||
|
||||
isMatchingLocation(AppPath.Verify) ||
|
||||
isMatchingLocation(AppPath.VerifyEmail),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
Reference in New Issue
Block a user