5509 remove flash on intermediate verify step when sign in with sso (#5526)
- remove flash on /verify - remove flash on signInUp - remove useless redirections and hooks - Remove DefaultHomePage component - Move redirections to /objects/companies in PageChangeEffect - add useShowAuthModal hooks and tests - add usePageChangeEffectNaviteLocation hooks and tests - fix refresh token expired produces blank screen
This commit is contained in:
@ -1,9 +0,0 @@
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
import { useDefaultHomePagePath } from '~/hooks/useDefaultHomePagePath';
|
||||
|
||||
export const DefaultHomePage = () => {
|
||||
const { defaultHomePagePath } = useDefaultHomePagePath();
|
||||
|
||||
return <Navigate to={defaultHomePagePath} />;
|
||||
};
|
||||
@ -5,7 +5,7 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { SubTitle } from '@/auth/components/SubTitle';
|
||||
import { Title } from '@/auth/components/Title';
|
||||
import { useSignOutAndRedirect } from '@/auth/hooks/useSignOutAndRedirect';
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { SubscriptionBenefit } from '@/billing/components/SubscriptionBenefit';
|
||||
import { SubscriptionCard } from '@/billing/components/SubscriptionCard';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
@ -95,7 +95,7 @@ export const ChooseYourPlan = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const handleLogout = useSignOutAndRedirect();
|
||||
const { signOut } = useAuth();
|
||||
|
||||
const computeInfo = (
|
||||
price: ProductPriceEntity,
|
||||
@ -175,7 +175,7 @@ export const ChooseYourPlan = () => {
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
<StyledLinkGroup>
|
||||
<ActionLink onClick={handleLogout}>Log out</ActionLink>
|
||||
<ActionLink onClick={signOut}>Log out</ActionLink>
|
||||
<span />
|
||||
<ActionLink href={CAL_LINK} target="_blank" rel="noreferrer">
|
||||
Book a Call
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useMemo } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
@ -10,10 +9,7 @@ import { SignInUpForm } from '@/auth/sign-in-up/components/SignInUpForm';
|
||||
import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
||||
import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { Loader } from '@/ui/feedback/loader/components/Loader';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||
import { useWorkspaceSwitching } from '@/ui/navigation/navigation-drawer/hooks/useWorkspaceSwitching';
|
||||
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
|
||||
@ -26,13 +22,8 @@ const StyledContentContainer = styled.div`
|
||||
`;
|
||||
|
||||
export const Invite = () => {
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
workspace: workspaceFromInviteHash,
|
||||
loading: workspaceFromInviteHashLoading,
|
||||
workspaceInviteHash,
|
||||
} = useWorkspaceFromInviteHash();
|
||||
const { workspace: workspaceFromInviteHash, workspaceInviteHash } =
|
||||
useWorkspaceFromInviteHash();
|
||||
const { form } = useSignInUpForm();
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const [addUserToWorkspace] = useAddUserToWorkspaceMutation();
|
||||
@ -56,68 +47,41 @@ export const Invite = () => {
|
||||
await switchWorkspace(workspaceFromInviteHash.id);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
!isDefined(workspaceFromInviteHash) &&
|
||||
!workspaceFromInviteHashLoading
|
||||
) {
|
||||
enqueueSnackBar('workspace does not exist', {
|
||||
variant: SnackBarVariant.Error,
|
||||
});
|
||||
if (isDefined(currentWorkspace)) {
|
||||
navigate(AppPath.Index);
|
||||
} else {
|
||||
navigate(AppPath.SignInUp);
|
||||
}
|
||||
}
|
||||
if (
|
||||
if (
|
||||
!isDefined(workspaceFromInviteHash) ||
|
||||
(isDefined(workspaceFromInviteHash) &&
|
||||
isDefined(currentWorkspace) &&
|
||||
currentWorkspace.id === workspaceFromInviteHash?.id
|
||||
) {
|
||||
enqueueSnackBar(
|
||||
`You already belong to ${workspaceFromInviteHash?.displayName} workspace`,
|
||||
{
|
||||
variant: SnackBarVariant.Info,
|
||||
},
|
||||
);
|
||||
navigate(AppPath.Index);
|
||||
}
|
||||
}, [
|
||||
navigate,
|
||||
enqueueSnackBar,
|
||||
currentWorkspace,
|
||||
workspaceFromInviteHash,
|
||||
workspaceFromInviteHashLoading,
|
||||
]);
|
||||
workspaceFromInviteHash.id === currentWorkspace.id)
|
||||
) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
!workspaceFromInviteHashLoading && (
|
||||
<>
|
||||
<AnimatedEaseIn>
|
||||
<Logo workspaceLogo={workspaceFromInviteHash?.logo} />
|
||||
</AnimatedEaseIn>
|
||||
<Title animate>{title}</Title>
|
||||
{isDefined(currentWorkspace) && workspaceFromInviteHash ? (
|
||||
<>
|
||||
<StyledContentContainer>
|
||||
<MainButton
|
||||
variant="secondary"
|
||||
title="Continue"
|
||||
type="submit"
|
||||
onClick={handleUserJoinWorkspace}
|
||||
Icon={() => form.formState.isSubmitting && <Loader />}
|
||||
fullWidth
|
||||
/>
|
||||
</StyledContentContainer>
|
||||
<FooterNote>
|
||||
By using Twenty, you agree to the Terms of Service and Privacy
|
||||
Policy.
|
||||
</FooterNote>
|
||||
</>
|
||||
) : (
|
||||
<SignInUpForm />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
<>
|
||||
<AnimatedEaseIn>
|
||||
<Logo workspaceLogo={workspaceFromInviteHash?.logo} />
|
||||
</AnimatedEaseIn>
|
||||
<Title animate>{title}</Title>
|
||||
{isDefined(currentWorkspace) ? (
|
||||
<>
|
||||
<StyledContentContainer>
|
||||
<MainButton
|
||||
variant="secondary"
|
||||
title="Continue"
|
||||
type="submit"
|
||||
onClick={handleUserJoinWorkspace}
|
||||
Icon={() => form.formState.isSubmitting && <Loader />}
|
||||
fullWidth
|
||||
/>
|
||||
</StyledContentContainer>
|
||||
<FooterNote>
|
||||
By using Twenty, you agree to the Terms of Service and Privacy
|
||||
Policy.
|
||||
</FooterNote>
|
||||
</>
|
||||
) : (
|
||||
<SignInUpForm />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -7,19 +7,20 @@ import styled from '@emotion/styled';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { Logo } from '@/auth/components/Logo';
|
||||
import { Title } from '@/auth/components/Title';
|
||||
import { useAuth } from '@/auth/hooks/useAuth';
|
||||
import { useIsLogged } from '@/auth/hooks/useIsLogged';
|
||||
import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp';
|
||||
import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex';
|
||||
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 { MainButton } from '@/ui/input/button/components/MainButton';
|
||||
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
|
||||
import { isDefaultLayoutAuthModalVisibleState } from '@/ui/layout/states/isDefaultLayoutAuthModalVisibleState';
|
||||
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
|
||||
import {
|
||||
useUpdatePasswordViaResetTokenMutation,
|
||||
@ -73,6 +74,7 @@ export const PasswordReset = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [email, setEmail] = useState('');
|
||||
const [isTokenValid, setIsTokenValid] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
@ -80,6 +82,9 @@ export const PasswordReset = () => {
|
||||
|
||||
const isLoggedIn = useIsLogged();
|
||||
|
||||
const setIsDefaultLayoutAuthModalVisibleState = useSetRecoilState(
|
||||
isDefaultLayoutAuthModalVisibleState,
|
||||
);
|
||||
const { control, handleSubmit } = useForm<Form>({
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
@ -89,7 +94,7 @@ export const PasswordReset = () => {
|
||||
resolver: zodResolver(validationSchema),
|
||||
});
|
||||
|
||||
const { loading: isValidatingToken } = useValidatePasswordResetTokenQuery({
|
||||
useValidatePasswordResetTokenQuery({
|
||||
variables: {
|
||||
token: passwordResetToken ?? '',
|
||||
},
|
||||
@ -98,13 +103,11 @@ export const PasswordReset = () => {
|
||||
enqueueSnackBar(error?.message ?? 'Token Invalid', {
|
||||
variant: SnackBarVariant.Error,
|
||||
});
|
||||
if (!isLoggedIn) {
|
||||
navigate(AppPath.SignInUp);
|
||||
} else {
|
||||
navigate(AppPath.Index);
|
||||
}
|
||||
navigate(AppPath.Index);
|
||||
},
|
||||
onCompleted: (data) => {
|
||||
setIsTokenValid(true);
|
||||
setIsDefaultLayoutAuthModalVisibleState(true);
|
||||
if (isNonEmptyString(data?.validatePasswordResetToken?.email)) {
|
||||
setEmail(data.validatePasswordResetToken.email);
|
||||
}
|
||||
@ -116,8 +119,6 @@ export const PasswordReset = () => {
|
||||
|
||||
const { signInWithCredentials } = useAuth();
|
||||
|
||||
const { navigateAfterSignInUp } = useNavigateAfterSignInUp();
|
||||
|
||||
const onSubmit = async (formData: Form) => {
|
||||
try {
|
||||
const { data } = await updatePasswordViaToken({
|
||||
@ -142,12 +143,7 @@ export const PasswordReset = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
workspace: currentWorkspace,
|
||||
workspaceMember: currentWorkspaceMember,
|
||||
} = await signInWithCredentials(email || '', formData.newPassword);
|
||||
|
||||
navigateAfterSignInUp(currentWorkspace, currentWorkspaceMember);
|
||||
await signInWithCredentials(email || '', formData.newPassword);
|
||||
} catch (err) {
|
||||
logError(err);
|
||||
enqueueSnackBar(
|
||||
@ -160,89 +156,90 @@ export const PasswordReset = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledMainContainer>
|
||||
<AnimatedEaseIn>
|
||||
<Logo />
|
||||
</AnimatedEaseIn>
|
||||
<Title animate>Reset Password</Title>
|
||||
<StyledContentContainer>
|
||||
{isValidatingToken && (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.quaternary}
|
||||
highlightColor={theme.background.secondary}
|
||||
>
|
||||
<Skeleton
|
||||
height={32}
|
||||
count={2}
|
||||
style={{
|
||||
marginBottom: theme.spacing(2),
|
||||
}}
|
||||
/>
|
||||
</SkeletonTheme>
|
||||
)}
|
||||
{email && (
|
||||
<StyledForm onSubmit={handleSubmit(onSubmit)}>
|
||||
<StyledFullWidthMotionDiv
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
transition={{
|
||||
type: 'spring',
|
||||
stiffness: 800,
|
||||
damping: 35,
|
||||
}}
|
||||
isTokenValid && (
|
||||
<StyledMainContainer>
|
||||
<AnimatedEaseIn>
|
||||
<Logo />
|
||||
</AnimatedEaseIn>
|
||||
<Title animate>Reset Password</Title>
|
||||
<StyledContentContainer>
|
||||
{!email ? (
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.quaternary}
|
||||
highlightColor={theme.background.secondary}
|
||||
>
|
||||
<StyledInputContainer>
|
||||
<TextInputV2
|
||||
autoFocus
|
||||
value={email}
|
||||
placeholder="Email"
|
||||
fullWidth
|
||||
disabled
|
||||
/>
|
||||
</StyledInputContainer>
|
||||
</StyledFullWidthMotionDiv>
|
||||
<StyledFullWidthMotionDiv
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
transition={{
|
||||
type: 'spring',
|
||||
stiffness: 800,
|
||||
damping: 35,
|
||||
}}
|
||||
>
|
||||
<Controller
|
||||
name="newPassword"
|
||||
control={control}
|
||||
render={({
|
||||
field: { onChange, onBlur, value },
|
||||
fieldState: { error },
|
||||
}) => (
|
||||
<StyledInputContainer>
|
||||
<TextInputV2
|
||||
autoFocus
|
||||
value={value}
|
||||
type="password"
|
||||
placeholder="New Password"
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
error={error?.message}
|
||||
fullWidth
|
||||
/>
|
||||
</StyledInputContainer>
|
||||
)}
|
||||
<Skeleton
|
||||
height={32}
|
||||
count={2}
|
||||
style={{
|
||||
marginBottom: theme.spacing(2),
|
||||
}}
|
||||
/>
|
||||
</StyledFullWidthMotionDiv>
|
||||
</SkeletonTheme>
|
||||
) : (
|
||||
<StyledForm onSubmit={handleSubmit(onSubmit)}>
|
||||
<StyledFullWidthMotionDiv
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
transition={{
|
||||
type: 'spring',
|
||||
stiffness: 800,
|
||||
damping: 35,
|
||||
}}
|
||||
>
|
||||
<StyledInputContainer>
|
||||
<TextInputV2
|
||||
autoFocus
|
||||
value={email}
|
||||
placeholder="Email"
|
||||
fullWidth
|
||||
disabled
|
||||
/>
|
||||
</StyledInputContainer>
|
||||
</StyledFullWidthMotionDiv>
|
||||
<StyledFullWidthMotionDiv
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
transition={{
|
||||
type: 'spring',
|
||||
stiffness: 800,
|
||||
damping: 35,
|
||||
}}
|
||||
>
|
||||
<Controller
|
||||
name="newPassword"
|
||||
control={control}
|
||||
render={({
|
||||
field: { onChange, onBlur, value },
|
||||
fieldState: { error },
|
||||
}) => (
|
||||
<StyledInputContainer>
|
||||
<TextInputV2
|
||||
autoFocus
|
||||
value={value}
|
||||
type="password"
|
||||
placeholder="New Password"
|
||||
onBlur={onBlur}
|
||||
onChange={onChange}
|
||||
error={error?.message}
|
||||
fullWidth
|
||||
/>
|
||||
</StyledInputContainer>
|
||||
)}
|
||||
/>
|
||||
</StyledFullWidthMotionDiv>
|
||||
|
||||
<MainButton
|
||||
variant="secondary"
|
||||
title="Change Password"
|
||||
type="submit"
|
||||
fullWidth
|
||||
disabled={isUpdatingPassword}
|
||||
/>
|
||||
</StyledForm>
|
||||
)}
|
||||
</StyledContentContainer>
|
||||
</StyledMainContainer>
|
||||
<MainButton
|
||||
variant="secondary"
|
||||
title="Change Password"
|
||||
type="submit"
|
||||
fullWidth
|
||||
disabled={isUpdatingPassword}
|
||||
/>
|
||||
</StyledForm>
|
||||
)}
|
||||
</StyledContentContainer>
|
||||
</StyledMainContainer>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user