4689 multi workspace i should be able to accept an invite if im already logged in (#5454)
- split signInUp to separate Invitation from signInUp - update redirection logic - add a resolver for userWorkspace - add a mutation to add a user to a workspace - authorize /invite/hash while loggedIn - add a button to join a workspace ### Base functionnality https://github.com/twentyhq/twenty/assets/29927851/a1075a4e-a2af-4184-aa3e-e163711277a1 ### Error handling https://github.com/twentyhq/twenty/assets/29927851/1bdd78ce-933a-4860-a87a-3f1f7bda389e
This commit is contained in:
@ -6,11 +6,17 @@ import { motion } from 'framer-motion';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { IconGoogle, IconMicrosoft } from 'twenty-ui';
|
||||
|
||||
import { FooterNote } from '@/auth/sign-in-up/components/FooterNote';
|
||||
import { HorizontalSeparator } from '@/auth/sign-in-up/components/HorizontalSeparator';
|
||||
import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword';
|
||||
import {
|
||||
SignInUpMode,
|
||||
SignInUpStep,
|
||||
useSignInUp,
|
||||
} from '@/auth/sign-in-up/hooks/useSignInUp';
|
||||
import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
||||
import { useSignInWithGoogle } from '@/auth/sign-in-up/hooks/useSignInWithGoogle';
|
||||
import { useSignInWithMicrosoft } from '@/auth/sign-in-up/hooks/useSignInWithMicrosoft';
|
||||
import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash';
|
||||
import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState';
|
||||
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
|
||||
@ -18,16 +24,8 @@ import { Loader } from '@/ui/feedback/loader/components/Loader';
|
||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { ActionLink } from '@/ui/navigation/link/components/ActionLink';
|
||||
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { Logo } from '../../components/Logo';
|
||||
import { Title } from '../../components/Title';
|
||||
import { SignInUpMode, SignInUpStep, useSignInUp } from '../hooks/useSignInUp';
|
||||
|
||||
import { FooterNote } from './FooterNote';
|
||||
import { HorizontalSeparator } from './HorizontalSeparator';
|
||||
|
||||
const StyledContentContainer = styled.div`
|
||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||
margin-top: ${({ theme }) => theme.spacing(4)};
|
||||
@ -55,14 +53,12 @@ export const SignInUpForm = () => {
|
||||
);
|
||||
const [authProviders] = useRecoilState(authProvidersState);
|
||||
const [showErrors, setShowErrors] = useState(false);
|
||||
const { handleResetPassword } = useHandleResetPassword();
|
||||
const workspace = useWorkspaceFromInviteHash();
|
||||
const { signInWithGoogle } = useSignInWithGoogle();
|
||||
const { signInWithMicrosoft } = useSignInWithMicrosoft();
|
||||
const { form } = useSignInUpForm();
|
||||
const { handleResetPassword } = useHandleResetPassword();
|
||||
|
||||
const {
|
||||
isInviteMode,
|
||||
signInUpStep,
|
||||
signInUpMode,
|
||||
continueWithCredentials,
|
||||
@ -101,23 +97,6 @@ export const SignInUpForm = () => {
|
||||
return signInUpMode === SignInUpMode.SignIn ? 'Sign in' : 'Sign up';
|
||||
}, [signInUpMode, signInUpStep]);
|
||||
|
||||
const title = useMemo(() => {
|
||||
if (isInviteMode) {
|
||||
return `Join ${workspace?.displayName ?? ''} team`;
|
||||
}
|
||||
|
||||
if (
|
||||
signInUpStep === SignInUpStep.Init ||
|
||||
signInUpStep === SignInUpStep.Email
|
||||
) {
|
||||
return 'Welcome to Twenty';
|
||||
}
|
||||
|
||||
return signInUpMode === SignInUpMode.SignIn
|
||||
? 'Sign in to Twenty'
|
||||
: 'Sign up to Twenty';
|
||||
}, [signInUpMode, workspace?.displayName, isInviteMode, signInUpStep]);
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const shouldWaitForCaptchaToken =
|
||||
@ -143,10 +122,6 @@ export const SignInUpForm = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<AnimatedEaseIn>
|
||||
<Logo workspaceLogo={workspace?.logo} />
|
||||
</AnimatedEaseIn>
|
||||
<Title animate>{title}</Title>
|
||||
<StyledContentContainer>
|
||||
{authProviders.google && (
|
||||
<>
|
||||
|
||||
@ -4,8 +4,13 @@ import { useGetWorkspaceFromInviteHashQuery } from '~/generated/graphql';
|
||||
|
||||
export const useWorkspaceFromInviteHash = () => {
|
||||
const workspaceInviteHash = useParams().workspaceInviteHash;
|
||||
const { data: workspaceFromInviteHash } = useGetWorkspaceFromInviteHashQuery({
|
||||
variables: { inviteHash: workspaceInviteHash || '' },
|
||||
});
|
||||
return workspaceFromInviteHash?.findWorkspaceFromInviteHash;
|
||||
const { data: workspaceFromInviteHash, loading } =
|
||||
useGetWorkspaceFromInviteHashQuery({
|
||||
variables: { inviteHash: workspaceInviteHash || '' },
|
||||
});
|
||||
return {
|
||||
workspace: workspaceFromInviteHash?.findWorkspaceFromInviteHash,
|
||||
workspaceInviteHash,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
|
||||
@ -80,6 +80,7 @@ export const DefaultLayout = () => {
|
||||
OnboardingStatus.OngoingWorkspaceActivation,
|
||||
].includes(onboardingStatus)) ||
|
||||
isMatchingLocation(AppPath.ResetPassword) ||
|
||||
isMatchingLocation(AppPath.Invite) ||
|
||||
(isMatchingLocation(AppPath.PlanRequired) &&
|
||||
(OnboardingStatus.CompletedWithoutSubscription ||
|
||||
OnboardingStatus.Canceled))
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { tokenPairState } from '@/auth/states/tokenPairState';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { useGenerateJwtMutation } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useWorkspaceSwitching = () => {
|
||||
const navigate = useNavigate();
|
||||
const setTokenPair = useSetRecoilState(tokenPairState);
|
||||
const [generateJWT] = useGenerateJwtMutation();
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
@ -30,8 +29,7 @@ export const useWorkspaceSwitching = () => {
|
||||
|
||||
const { tokens } = jwt.data.generateJWT;
|
||||
setTokenPair(tokens);
|
||||
navigate(`/objects/companies`);
|
||||
window.location.reload();
|
||||
window.location.href = AppPath.Index;
|
||||
};
|
||||
|
||||
return { switchWorkspace };
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const ADD_USER_TO_WORKSPACE = gql`
|
||||
mutation AddUserToWorkspace($inviteHash: String!) {
|
||||
addUserToWorkspace(inviteHash: $inviteHash) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
Reference in New Issue
Block a user