Skip to content

Commit

Permalink
WIP: Add an onboarding resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
martmull committed Jun 10, 2024
1 parent 99910f3 commit a92f9c2
Show file tree
Hide file tree
Showing 31 changed files with 195 additions and 275 deletions.
31 changes: 12 additions & 19 deletions packages/twenty-front/src/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,12 @@ export type ObjectFieldsConnection = {
pageInfo: PageInfo;
};

/** Onboarding step */
export enum OnboardingStep {
InviteTeam = 'INVITE_TEAM',
SyncEmail = 'SYNC_EMAIL'
}

export type PageInfo = {
__typename?: 'PageInfo';
/** The cursor of the last returned record. */
Expand Down Expand Up @@ -799,12 +805,12 @@ export type User = {
firstName: Scalars['String'];
id: Scalars['UUID'];
lastName: Scalars['String'];
onboardingStep?: Maybe<OnboardingStep>;
passwordHash?: Maybe<Scalars['String']>;
/** @deprecated field migrated into the AppTokens Table ref: https://github.com/twentyhq/twenty/issues/5021 */
passwordResetToken?: Maybe<Scalars['String']>;
/** @deprecated field migrated into the AppTokens Table ref: https://github.com/twentyhq/twenty/issues/5021 */
passwordResetTokenExpiresAt?: Maybe<Scalars['DateTime']>;
state: UserState;
supportUserHash?: Maybe<Scalars['String']>;
updatedAt: Scalars['DateTime'];
workspaceMember?: Maybe<WorkspaceMember>;
Expand All @@ -829,17 +835,6 @@ export type UserMappingOptionsUser = {
user?: Maybe<Scalars['String']>;
};

export type UserState = {
__typename?: 'UserState';
onboardingStep?: Maybe<UserStateOnboardingStepValues>;
};

/** User state onboarding step */
export enum UserStateOnboardingStepValues {
InviteTeam = 'INVITE_TEAM',
SyncEmail = 'SYNC_EMAIL'
}

export type UserStateResult = {
__typename?: 'UserStateResult';
/** Boolean that confirms query was dispatched */
Expand Down Expand Up @@ -1147,7 +1142,7 @@ export type ImpersonateMutationVariables = Exact<{
}>;


export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, state: { __typename?: 'UserState', onboardingStep?: UserStateOnboardingStepValues | null }, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStep?: OnboardingStep | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };

export type RenewTokenMutationVariables = Exact<{
appToken: Scalars['String'];
Expand Down Expand Up @@ -1179,7 +1174,7 @@ export type VerifyMutationVariables = Exact<{
}>;


export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, state: { __typename?: 'UserState', onboardingStep?: UserStateOnboardingStepValues | null }, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStep?: OnboardingStep | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };

export type CheckUserExistsQueryVariables = Exact<{
email: Scalars['String'];
Expand Down Expand Up @@ -1233,7 +1228,7 @@ export type SkipSyncEmailOnboardingStepMutationVariables = Exact<{ [key: string]

export type SkipSyncEmailOnboardingStepMutation = { __typename?: 'Mutation', skipSyncEmailOnboardingStep: { __typename?: 'UserStateResult', success: boolean } };

export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, state: { __typename?: 'UserState', onboardingStep?: UserStateOnboardingStepValues | null }, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> };
export type UserQueryFragmentFragment = { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStep?: OnboardingStep | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> };

export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;

Expand All @@ -1250,7 +1245,7 @@ export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProf
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;


export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, state: { __typename?: 'UserState', onboardingStep?: UserStateOnboardingStepValues | null }, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } };
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: any, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, onboardingStep?: OnboardingStep | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: any, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: any, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, activationStatus: string, currentCacheVersion?: string | null, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: any, key: string, value: boolean, workspaceId: string }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: any, status: string, interval?: string | null } | null }, workspaces: Array<{ __typename?: 'UserWorkspace', workspace?: { __typename?: 'Workspace', id: any, logo?: string | null, displayName?: string | null, domainName?: string | null } | null }> } };

export type AddUserToWorkspaceMutationVariables = Exact<{
inviteHash: Scalars['String'];
Expand Down Expand Up @@ -1401,9 +1396,7 @@ export const UserQueryFragmentFragmentDoc = gql`
email
canImpersonate
supportUserHash
state {
onboardingStep
}
onboardingStep
workspaceMember {
id
name {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { isVerifyPendingState } from '@/auth/states/isVerifyPendingState';
import { tokenPairState } from '@/auth/states/tokenPairState';
import { billingState } from '@/client-config/states/billingState';
import { OnboardingStep } from '~/generated/graphql';

const tokenPair = {
accessToken: { token: 'accessToken', expiresAt: 'expiresAt' },
Expand All @@ -26,7 +27,7 @@ const currentUser = {
email: 'test@test',
supportUserHash: '1',
canImpersonate: false,
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser;
const currentWorkspace = {
activationStatus: 'active',
Expand Down Expand Up @@ -196,7 +197,7 @@ describe('useOnboardingStatus', () => {
setBilling(billing);
setCurrentUser({
...currentUser,
state: { skipSyncEmailOnboardingStep: false },
onboardingStep: OnboardingStep.SyncEmail,
});
setCurrentWorkspace({
...currentWorkspace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { User } from '~/generated/graphql';

export type CurrentUser = Pick<
User,
'id' | 'email' | 'supportUserHash' | 'canImpersonate' | 'state'
'id' | 'email' | 'supportUserHash' | 'canImpersonate' | 'onboardingStep'
>;

export const currentUserState = createState<CurrentUser | null>({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CurrentUser } from '@/auth/states/currentUserState';
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import { OnboardingStep } from '~/generated/graphql';

import { getOnboardingStatus } from '../getOnboardingStatus';

Expand All @@ -22,7 +23,7 @@ describe('getOnboardingStatus', () => {
activationStatus: 'inactive',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser,
isBillingEnabled: false,
});
Expand All @@ -38,7 +39,7 @@ describe('getOnboardingStatus', () => {
activationStatus: 'active',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser,
isBillingEnabled: false,
});
Expand All @@ -57,7 +58,7 @@ describe('getOnboardingStatus', () => {
activationStatus: 'active',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: false },
onboardingStep: OnboardingStep.SyncEmail,
} as CurrentUser,
isBillingEnabled: false,
});
Expand All @@ -76,7 +77,7 @@ describe('getOnboardingStatus', () => {
activationStatus: 'active',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser,
isBillingEnabled: false,
});
Expand All @@ -96,7 +97,7 @@ describe('getOnboardingStatus', () => {
subscriptionStatus: 'incomplete',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser,
isBillingEnabled: true,
});
Expand All @@ -116,7 +117,7 @@ describe('getOnboardingStatus', () => {
subscriptionStatus: 'incomplete',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser,
isBillingEnabled: false,
});
Expand All @@ -136,7 +137,7 @@ describe('getOnboardingStatus', () => {
subscriptionStatus: 'canceled',
} as CurrentWorkspace,
currentUser: {
state: { skipSyncEmailOnboardingStep: true },
onboardingStep: null,
} as CurrentUser,
isBillingEnabled: true,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CurrentUser } from '@/auth/states/currentUserState';
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
import { UserStateOnboardingStepValues } from '~/generated/graphql';
import { OnboardingStep } from '~/generated/graphql';

export enum OnboardingStatus {
Incomplete = 'incomplete',
Expand Down Expand Up @@ -61,16 +61,11 @@ export const getOnboardingStatus = ({
return OnboardingStatus.OngoingProfileCreation;
}

if (
currentUser.state.onboardingStep === UserStateOnboardingStepValues.SyncEmail
) {
if (currentUser.onboardingStep === OnboardingStep.SyncEmail) {
return OnboardingStatus.OngoingSyncEmail;
}

if (
currentUser.state.onboardingStep ===
UserStateOnboardingStepValues.InviteTeam
) {
if (currentUser.onboardingStep === OnboardingStep.InviteTeam) {
return OnboardingStatus.OngoingInviteTeam;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { useRecoilCallback, useSetRecoilState } from 'recoil';

import { currentUserState } from '@/auth/states/currentUserState';
import { UserStateOnboardingStepValues } from '~/generated/graphql';
import { OnboardingStep } from '~/generated/graphql';

export const useSetOnboardingStep = () => {
const setCurrentUser = useSetRecoilState(currentUserState);
return useRecoilCallback(
() => (onboardingStep: UserStateOnboardingStepValues | null) => {
() => (onboardingStep: OnboardingStep | null) => {
setCurrentUser(
(current) =>
({
...current,
state: { onboardingStep: onboardingStep },
onboardingStep,
}) as any,
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ export const USER_QUERY_FRAGMENT = gql`
email
canImpersonate
supportUserHash
state {
onboardingStep
}
onboardingStep
workspaceMember {
id
name {
Expand Down
4 changes: 2 additions & 2 deletions packages/twenty-front/src/pages/onboarding/SyncEmails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ActionLink } from '@/ui/navigation/link/components/ActionLink';
import {
CalendarChannelVisibility,
MessageChannelVisibility,
UserStateOnboardingStepValues,
OnboardingStep,
useSkipSyncEmailOnboardingStepMutation,
} from '~/generated/graphql';

Expand Down Expand Up @@ -57,7 +57,7 @@ export const SyncEmails = () => {

const continueWithoutSync = async () => {
await skipSyncEmailOnboardingStepMutation();
setOnboardingStep(UserStateOnboardingStepValues.InviteTeam);
setOnboardingStep(OnboardingStep.InviteTeam);
};

return (
Expand Down
Loading

0 comments on commit a92f9c2

Please sign in to comment.