Prefill workspace invitation email (#7174) (#8826)

Prefill workspace invitation email, fixes #7174

---------

Co-authored-by: ad-elias <elias@autodiligence.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Antoine Moreaux <moreaux.antoine@gmail.com>
This commit is contained in:
eliasylonen
2024-12-02 14:22:53 +01:00
committed by GitHub
parent 2b0f67191a
commit b6701a81e1
8 changed files with 39 additions and 30 deletions

View File

@ -10,7 +10,7 @@ import { useAuth } from '@/auth/hooks/useAuth';
import { authProvidersState } from '@/client-config/states/authProvidersState';
import { billingState } from '@/client-config/states/billingState';
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
import { supportChatState } from '@/client-config/states/supportChatState';
import { email, mocks, password, results, token } from '../__mocks__/useAuth';
@ -78,7 +78,9 @@ describe('useAuth', () => {
const icons = useRecoilValue(iconsState);
const authProviders = useRecoilValue(authProvidersState);
const billing = useRecoilValue(billingState);
const isSignInPrefilled = useRecoilValue(isSignInPrefilledState);
const isDeveloperDefaultSignInPrefilled = useRecoilValue(
isDeveloperDefaultSignInPrefilledState,
);
const supportChat = useRecoilValue(supportChatState);
const isDebugMode = useRecoilValue(isDebugModeState);
return {
@ -88,7 +90,7 @@ describe('useAuth', () => {
icons,
authProviders,
billing,
isSignInPrefilled,
isDeveloperDefaultSignInPrefilled,
supportChat,
isDebugMode,
},
@ -119,7 +121,7 @@ describe('useAuth', () => {
sso: false,
});
expect(state.billing).toBeNull();
expect(state.isSignInPrefilled).toBe(false);
expect(state.isDeveloperDefaultSignInPrefilled).toBe(false);
expect(state.supportChat).toEqual({
supportDriver: 'none',
supportFrontChatId: null,

View File

@ -19,7 +19,6 @@ import { billingState } from '@/client-config/states/billingState';
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
import { clientConfigApiStatusState } from '@/client-config/states/clientConfigApiStatusState';
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
import { supportChatState } from '@/client-config/states/supportChatState';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
@ -32,6 +31,7 @@ import {
import { isDefined } from '~/utils/isDefined';
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersStates';
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
import { DateFormat } from '@/localization/constants/DateFormat';
import { TimeFormat } from '@/localization/constants/TimeFormat';
import { dateTimeFormatState } from '@/localization/states/dateTimeFormatState';
@ -78,8 +78,8 @@ export const useAuth = () => {
.getLoadable(authProvidersState)
.getValue();
const billing = snapshot.getLoadable(billingState).getValue();
const isSignInPrefilled = snapshot
.getLoadable(isSignInPrefilledState)
const isDeveloperDefaultSignInPrefilled = snapshot
.getLoadable(isDeveloperDefaultSignInPrefilledState)
.getValue();
const supportChat = snapshot.getLoadable(supportChatState).getValue();
const isDebugMode = snapshot.getLoadable(isDebugModeState).getValue();
@ -96,7 +96,10 @@ export const useAuth = () => {
set(iconsState, iconsValue);
set(authProvidersState, authProvidersValue);
set(billingState, billing);
set(isSignInPrefilledState, isSignInPrefilled);
set(
isDeveloperDefaultSignInPrefilledState,
isDeveloperDefaultSignInPrefilled,
);
set(supportChatState, supportChat);
set(isDebugModeState, isDebugMode);
set(captchaProviderState, captchaProvider);

View File

@ -5,7 +5,9 @@ import { useRecoilValue } from 'recoil';
import { z } from 'zod';
import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex';
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
import { useSearchParams } from 'react-router-dom';
import { isDefined } from '~/utils/isDefined';
export const validationSchema = z
.object({
@ -20,7 +22,12 @@ export const validationSchema = z
export type Form = z.infer<typeof validationSchema>;
export const useSignInUpForm = () => {
const isSignInPrefilled = useRecoilValue(isSignInPrefilledState);
const isDeveloperDefaultSignInPrefilled = useRecoilValue(
isDeveloperDefaultSignInPrefilledState,
);
const [searchParams] = useSearchParams();
const invitationPrefilledEmail = searchParams.get('email');
const form = useForm<Form>({
mode: 'onChange',
defaultValues: {
@ -33,10 +40,12 @@ export const useSignInUpForm = () => {
});
useEffect(() => {
if (isSignInPrefilled === true) {
if (isDefined(invitationPrefilledEmail)) {
form.setValue('email', invitationPrefilledEmail);
} else if (isDeveloperDefaultSignInPrefilled === true) {
form.setValue('email', 'tim@apple.dev');
form.setValue('password', 'Applecar2025');
}
}, [form, isSignInPrefilled]);
}, [form, isDeveloperDefaultSignInPrefilled, invitationPrefilledEmail]);
return { form: form };
};

View File

@ -6,7 +6,7 @@ import { chromeExtensionIdState } from '@/client-config/states/chromeExtensionId
import { clientConfigApiStatusState } from '@/client-config/states/clientConfigApiStatusState';
import { isAnalyticsEnabledState } from '@/client-config/states/isAnalyticsEnabledState';
import { isDebugModeState } from '@/client-config/states/isDebugModeState';
import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState';
import { isDeveloperDefaultSignInPrefilledState } from '@/client-config/states/isDeveloperDefaultSignInPrefilledState';
import { isSignUpDisabledState } from '@/client-config/states/isSignUpDisabledState';
import { sentryConfigState } from '@/client-config/states/sentryConfigState';
import { supportChatState } from '@/client-config/states/supportChatState';
@ -20,7 +20,9 @@ export const ClientConfigProviderEffect = () => {
const setIsDebugMode = useSetRecoilState(isDebugModeState);
const setIsAnalyticsEnabled = useSetRecoilState(isAnalyticsEnabledState);
const setIsSignInPrefilled = useSetRecoilState(isSignInPrefilledState);
const setIsDeveloperDefaultSignInPrefilled = useSetRecoilState(
isDeveloperDefaultSignInPrefilledState,
);
const setIsSignUpDisabled = useSetRecoilState(isSignUpDisabledState);
const setBilling = useSetRecoilState(billingState);
@ -76,7 +78,7 @@ export const ClientConfigProviderEffect = () => {
});
setIsDebugMode(data?.clientConfig.debugMode);
setIsAnalyticsEnabled(data?.clientConfig.analyticsEnabled);
setIsSignInPrefilled(data?.clientConfig.signInPrefilled);
setIsDeveloperDefaultSignInPrefilled(data?.clientConfig.signInPrefilled);
setIsSignUpDisabled(data?.clientConfig.signUpDisabled);
setBilling(data?.clientConfig.billing);
@ -99,7 +101,7 @@ export const ClientConfigProviderEffect = () => {
data,
setAuthProviders,
setIsDebugMode,
setIsSignInPrefilled,
setIsDeveloperDefaultSignInPrefilled,
setIsSignUpDisabled,
setSupportChat,
setBilling,

View File

@ -0,0 +1,6 @@
import { createState } from 'twenty-ui';
export const isDeveloperDefaultSignInPrefilledState = createState<boolean>({
key: 'isDeveloperDefaultSignInPrefilledState',
defaultValue: false,
});

View File

@ -1,6 +0,0 @@
import { createState } from 'twenty-ui';
export const isSignInPrefilledState = createState<boolean>({
key: 'isSignInPrefilledState',
defaultValue: false,
});

View File

@ -2,7 +2,6 @@ import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { Key } from 'ts-key-enum';
import { Button, IconSend } from 'twenty-ui';
import { z } from 'zod';
@ -105,12 +104,6 @@ export const WorkspaceInviteTeam = () => {
}
});
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === Key.Enter) {
submit();
}
};
const { isSubmitSuccessful, errors } = formState;
useEffect(() => {
@ -133,7 +126,6 @@ export const WorkspaceInviteTeam = () => {
value={value}
onChange={onChange}
error={error?.message}
onKeyDown={handleKeyDown}
fullWidth
/>
);

View File

@ -229,6 +229,7 @@ export class WorkspaceInvitationService {
if (invitation.value.isPersonalInvitation) {
link.searchParams.set('inviteToken', invitation.value.appToken.value);
link.searchParams.set('email', invitation.value.email);
}
const emailData = {
link: link.toString(),