Remove book a call step from onboarding (#22597)

The book a call screen was shown as a dedicated onboarding step after
sending team invites. It is no longer part of the flow: the
`BOOK_ONBOARDING` status, its pending user var, the
`skipBookOnboardingStep` mutation and the `BookCallDecision` screen are
removed, and onboarding completes right after the plan step.

The `/book-call` Cal.com page remains, reachable only from the "Book a
Call" link on the upgrade screen, with a back link to `/plan-required`.

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22597?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Raphaël Bosi
2026-07-07 10:34:20 +02:00
committed by GitHub
parent ee28ae363f
commit d3b79320b1
21 changed files with 10 additions and 348 deletions
@@ -995,7 +995,6 @@ enum OnboardingStatus {
SYNC_EMAIL
APPS_INSTALLATION
INVITE_TEAM
BOOK_ONBOARDING
COMPLETED
}
@@ -3344,7 +3343,6 @@ type Mutation {
revokeApiKey(input: RevokeApiKeyInput!): ApiKey
assignRoleToApiKey(apiKeyId: UUID!, roleId: UUID!): Boolean!
skipSyncEmailOnboardingStep: OnboardingStepSuccess!
skipBookOnboardingStep: OnboardingStepSuccess!
triggerInstallAppsOnboardingStep(universalIdentifiers: [String!]!): OnboardingStepSuccess!
updateOneApplicationVariable(key: String!, value: String!, applicationId: UUID!): Boolean!
checkoutSession(recurringInterval: SubscriptionInterval!, plan: BillingPlanKey! = PRO, requirePaymentMethod: Boolean! = true, successUrlPath: String): BillingSession!
@@ -708,7 +708,7 @@ export interface User {
/** Onboarding status */
export type OnboardingStatus = 'PLAN_REQUIRED' | 'WORKSPACE_ACTIVATION' | 'PROFILE_CREATION' | 'SYNC_EMAIL' | 'APPS_INSTALLATION' | 'INVITE_TEAM' | 'BOOK_ONBOARDING' | 'COMPLETED'
export type OnboardingStatus = 'PLAN_REQUIRED' | 'WORKSPACE_ACTIVATION' | 'PROFILE_CREATION' | 'SYNC_EMAIL' | 'APPS_INSTALLATION' | 'INVITE_TEAM' | 'COMPLETED'
export interface RatioAggregateConfig {
fieldMetadataId: Scalars['UUID']
@@ -2876,7 +2876,6 @@ export interface Mutation {
revokeApiKey?: ApiKey
assignRoleToApiKey: Scalars['Boolean']
skipSyncEmailOnboardingStep: OnboardingStepSuccess
skipBookOnboardingStep: OnboardingStepSuccess
triggerInstallAppsOnboardingStep: OnboardingStepSuccess
updateOneApplicationVariable: Scalars['Boolean']
checkoutSession: BillingSession
@@ -6123,7 +6122,6 @@ export interface MutationGenqlSelection{
revokeApiKey?: (ApiKeyGenqlSelection & { __args: {input: RevokeApiKeyInput} })
assignRoleToApiKey?: { __args: {apiKeyId: Scalars['UUID'], roleId: Scalars['UUID']} }
skipSyncEmailOnboardingStep?: OnboardingStepSuccessGenqlSelection
skipBookOnboardingStep?: OnboardingStepSuccessGenqlSelection
triggerInstallAppsOnboardingStep?: (OnboardingStepSuccessGenqlSelection & { __args: {universalIdentifiers: Scalars['String'][]} })
updateOneApplicationVariable?: { __args: {key: Scalars['String'], value: Scalars['String'], applicationId: Scalars['UUID']} }
checkoutSession?: (BillingSessionGenqlSelection & { __args: {recurringInterval: SubscriptionInterval, plan: BillingPlanKey, requirePaymentMethod: Scalars['Boolean'], successUrlPath?: (Scalars['String'] | null)} })
@@ -9059,7 +9057,6 @@ export const enumOnboardingStatus = {
SYNC_EMAIL: 'SYNC_EMAIL' as const,
APPS_INSTALLATION: 'APPS_INSTALLATION' as const,
INVITE_TEAM: 'INVITE_TEAM' as const,
BOOK_ONBOARDING: 'BOOK_ONBOARDING' as const,
COMPLETED: 'COMPLETED' as const
}
@@ -7535,9 +7535,6 @@ export default {
"skipSyncEmailOnboardingStep": [
154
],
"skipBookOnboardingStep": [
154
],
"triggerInstallAppsOnboardingStep": [
154,
{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 627 KiB

File diff suppressed because one or more lines are too long
@@ -82,7 +82,6 @@ jest.mock('@/ui/utilities/state/jotai/hooks/useAtomStateValue');
const setupMockState = (
objectNamePlural?: string,
verifyEmailRedirectPath?: string,
calendarBookingPageId?: string | null,
returnToPath?: string,
currentWorkspace: object | null = { id: 'mock-workspace-id' },
isBillingEnabled: boolean = true,
@@ -91,7 +90,6 @@ const setupMockState = (
jest
.mocked(useAtomStateValue)
.mockReturnValueOnce(currentWorkspace)
.mockReturnValueOnce(calendarBookingPageId ?? 'mock-calendar-id')
.mockReturnValueOnce({ isBillingEnabled })
.mockReturnValueOnce([{ namePlural: objectNamePlural ?? '' }])
.mockReturnValueOnce(isMinimalMetadataReady)
@@ -124,7 +122,6 @@ const testCases: {
{ loc: AppPath.Verify, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.Verify, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.Verify, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.Verify, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.Verify, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.SignInUp, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -135,7 +132,6 @@ const testCases: {
{ loc: AppPath.SignInUp, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.SignInUp, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.SignInUp, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.SignInUp, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.SignInUp, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.Invite, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: '/plan-required' },
@@ -146,7 +142,6 @@ const testCases: {
{ loc: AppPath.Invite, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: '/sync/emails' },
{ loc: AppPath.Invite, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.Invite, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: '/invite-team' },
{ loc: AppPath.Invite, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.Invite, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.ResetPassword, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: '/plan-required' },
@@ -157,7 +152,6 @@ const testCases: {
{ loc: AppPath.ResetPassword, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: '/sync/emails' },
{ loc: AppPath.ResetPassword, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.ResetPassword, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: '/invite-team' },
{ loc: AppPath.ResetPassword, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.ResetPassword, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.VerifyEmail, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -170,7 +164,6 @@ const testCases: {
{ loc: AppPath.VerifyEmail, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.VerifyEmail, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.VerifyEmail, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.VerifyEmail, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.VerifyEmail, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.WorkspaceActivation, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -181,7 +174,6 @@ const testCases: {
{ loc: AppPath.WorkspaceActivation, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.WorkspaceActivation, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.WorkspaceActivation, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.WorkspaceActivation, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.WorkspaceActivation, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.CreateProfile, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -192,7 +184,6 @@ const testCases: {
{ loc: AppPath.CreateProfile, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.CreateProfile, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.CreateProfile, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.CreateProfile, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.CreateProfile, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.SyncEmails, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -203,7 +194,6 @@ const testCases: {
{ loc: AppPath.SyncEmails, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: undefined },
{ loc: AppPath.SyncEmails, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.SyncEmails, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.SyncEmails, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.SyncEmails, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.InstallApps, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -214,7 +204,6 @@ const testCases: {
{ loc: AppPath.InstallApps, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.InstallApps, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: undefined },
{ loc: AppPath.InstallApps, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.InstallApps, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.InstallApps, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -225,29 +214,16 @@ const testCases: {
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: undefined },
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.PlanRequired },
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: AppPath.PlanRequired },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: undefined },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: true, onboardingStatus: OnboardingStatus.COMPLETED, res: getSettingsPath(SettingsPath.Billing) },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: false, isWorkspaceSuspended: false, onboardingStatus: undefined, res: AppPath.SignInUp },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.WORKSPACE_ACTIVATION, res: undefined },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PROFILE_CREATION, res: AppPath.CreateProfile },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: undefined },
{ loc: AppPath.BookCallDecision, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: undefined },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: true, onboardingStatus: OnboardingStatus.COMPLETED, res: getSettingsPath(SettingsPath.Billing) },
{ loc: AppPath.BookCall, hasAccessTokenPair: false, isWorkspaceSuspended: false, onboardingStatus: undefined, res: AppPath.SignInUp },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.WORKSPACE_ACTIVATION, res: undefined },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.WORKSPACE_ACTIVATION, res: AppPath.WorkspaceActivation },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PROFILE_CREATION, res: AppPath.CreateProfile },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: undefined },
{ loc: AppPath.BookCall, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: undefined },
@@ -258,7 +234,6 @@ const testCases: {
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: undefined },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.PlanRequiredSuccess, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: undefined },
@@ -269,7 +244,6 @@ const testCases: {
{ loc: AppPath.PlanRequiredSuccess, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.PlanRequiredSuccess, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.PlanRequiredSuccess, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.PlanRequiredSuccess, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.PlanRequiredSuccess, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.Index, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -280,7 +254,6 @@ const testCases: {
{ loc: AppPath.Index, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.Index, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.Index, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.Index, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.Index, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: defaultHomePagePath },
{ loc: AppPath.TasksPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -291,7 +264,6 @@ const testCases: {
{ loc: AppPath.TasksPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.TasksPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.TasksPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.TasksPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.TasksPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.OpportunitiesPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -302,7 +274,6 @@ const testCases: {
{ loc: AppPath.OpportunitiesPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.OpportunitiesPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.OpportunitiesPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.OpportunitiesPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.OpportunitiesPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -313,7 +284,6 @@ const testCases: {
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined, objectNamePluralFromParams: 'existing-object', objectNamePluralFromMetadata: 'existing-object' },
{ loc: AppPath.RecordIndexPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: AppPath.NotFound, objectNamePluralFromParams: 'non-existing-object', objectNamePluralFromMetadata: 'existing-object' },
@@ -327,7 +297,6 @@ const testCases: {
{ loc: AppPath.RecordShowPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.RecordShowPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.RecordShowPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.RecordShowPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.RecordShowPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -338,7 +307,6 @@ const testCases: {
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined, pageLayoutId: 'valid-id', useQueryResult: { loading: true } },
{ loc: AppPath.PageLayoutPage, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: AppPath.NotFound, pageLayoutId: 'non-existent-id', useQueryResult: { data: { getPageLayout: null }, loading: false } },
@@ -353,7 +321,6 @@ const testCases: {
{ loc: AppPath.SettingsCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.SettingsCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.SettingsCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.SettingsCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.SettingsCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.DevelopersCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -364,7 +331,6 @@ const testCases: {
{ loc: AppPath.DevelopersCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.DevelopersCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.DevelopersCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.DevelopersCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.DevelopersCatchAll, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.Authorize, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -375,7 +341,6 @@ const testCases: {
{ loc: AppPath.Authorize, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.Authorize, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.Authorize, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.Authorize, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.Authorize, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.NotFoundWildcard, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -386,7 +351,6 @@ const testCases: {
{ loc: AppPath.NotFoundWildcard, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.NotFoundWildcard, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.NotFoundWildcard, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.NotFoundWildcard, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.NotFoundWildcard, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
{ loc: AppPath.NotFound, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.PLAN_REQUIRED, res: AppPath.PlanRequired },
@@ -397,14 +361,11 @@ const testCases: {
{ loc: AppPath.NotFound, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.SYNC_EMAIL, res: AppPath.SyncEmails },
{ loc: AppPath.NotFound, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.APPS_INSTALLATION, res: AppPath.InstallApps },
{ loc: AppPath.NotFound, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.INVITE_TEAM, res: AppPath.InviteTeam },
{ loc: AppPath.NotFound, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, res: AppPath.BookCallDecision },
{ loc: AppPath.NotFound, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, res: undefined },
// isBillingEnabled:false — no post-invite-team upgrade interception on billing-disabled instances
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, isBillingEnabled: false, res: defaultHomePagePath },
{ loc: AppPath.InviteTeam, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, isBillingEnabled: false, res: AppPath.BookCallDecision },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, isBillingEnabled: false, res: defaultHomePagePath },
{ loc: AppPath.PlanRequired, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.BOOK_ONBOARDING, isBillingEnabled: false, res: AppPath.BookCallDecision },
// returnToPath: should redirect to saved path instead of defaultHomePagePath
{ loc: AppPath.Verify, hasAccessTokenPair: true, isWorkspaceSuspended: false, onboardingStatus: OnboardingStatus.COMPLETED, returnToPath: '/authorize?clientId=abc', res: '/authorize?clientId=abc' },
@@ -445,7 +406,6 @@ describe('usePageChangeEffectNavigateLocation', () => {
setupMockState(
objectNamePluralFromMetadata,
verifyEmailRedirectPath,
undefined,
returnToPath,
undefined,
isBillingEnabled ?? true,
@@ -478,9 +438,7 @@ describe('usePageChangeEffectNavigateLocation', () => {
['notOnWorkspace:verify', 'notOnWorkspace:signInUp'].length +
[
'billingDisabled:inviteTeamCompleted',
'billingDisabled:inviteTeamBookOnboarding',
'billingDisabled:planRequiredCompleted',
'billingDisabled:planRequiredBookOnboarding',
].length,
);
});
@@ -498,7 +456,7 @@ describe('usePageChangeEffectNavigateLocation — authenticated with no current
setupMockIsOnAWorkspace(true);
setupMockUseQuery();
setupMockUseParams();
setupMockState(undefined, undefined, undefined, undefined, null);
setupMockState(undefined, undefined, undefined, null);
expect(usePageChangeEffectNavigateLocation()).toEqual(AppPath.SignInUp);
},
@@ -5,7 +5,6 @@ import { useHasAccessTokenPair } from '@/auth/hooks/useHasAccessTokenPair';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { returnToPathState } from '@/auth/states/returnToPathState';
import { billingState } from '@/client-config/states/billingState';
import { calendarBookingPageIdState } from '@/client-config/states/calendarBookingPageIdState';
import { useIsCurrentLocationOnAWorkspace } from '@/domain-manager/hooks/useIsCurrentLocationOnAWorkspace';
import { isMinimalMetadataReadyState } from '@/metadata-store/states/isMinimalMetadataReadyState';
import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath';
@@ -43,7 +42,6 @@ export const usePageChangeEffectNavigateLocation = () => {
);
const { defaultHomePagePath } = useDefaultHomePagePath();
const location = useLocation();
const calendarBookingPageId = useAtomStateValue(calendarBookingPageIdState);
const billing = useAtomStateValue(billingState);
const isBillingEnabled = billing?.isBillingEnabled ?? false;
@@ -97,7 +95,6 @@ export const usePageChangeEffectNavigateLocation = () => {
AppPath.PlanRequired,
AppPath.PlanRequiredSuccess,
AppPath.BookCall,
AppPath.BookCallDecision,
])
) {
if (
@@ -121,11 +118,7 @@ export const usePageChangeEffectNavigateLocation = () => {
if (
onboardingStatus === OnboardingStatus.WORKSPACE_ACTIVATION &&
!someMatchingLocationOf([
AppPath.WorkspaceActivation,
AppPath.BookCallDecision,
AppPath.BookCall,
])
!isMatchingLocation(location, AppPath.WorkspaceActivation)
) {
return AppPath.WorkspaceActivation;
}
@@ -158,11 +151,7 @@ export const usePageChangeEffectNavigateLocation = () => {
return AppPath.InviteTeam;
}
if (
isBillingEnabled &&
(onboardingStatus === OnboardingStatus.BOOK_ONBOARDING ||
onboardingStatus === OnboardingStatus.COMPLETED)
) {
if (isBillingEnabled && onboardingStatus === OnboardingStatus.COMPLETED) {
if (isMatchingLocation(location, AppPath.InviteTeam)) {
return AppPath.PlanRequired;
}
@@ -171,16 +160,6 @@ export const usePageChangeEffectNavigateLocation = () => {
}
}
if (
onboardingStatus === OnboardingStatus.BOOK_ONBOARDING &&
!someMatchingLocationOf([AppPath.BookCallDecision, AppPath.BookCall])
) {
if (!isDefined(calendarBookingPageId)) {
return defaultHomePagePath;
}
return AppPath.BookCallDecision;
}
if (
onboardingStatus === OnboardingStatus.COMPLETED &&
someMatchingLocationOf([
@@ -99,12 +99,6 @@ const PaymentSuccess = lazy(() =>
})),
);
const BookCallDecision = lazy(() =>
import('~/pages/onboarding/BookCallDecision').then((module) => ({
default: module.BookCallDecision,
})),
);
const BookCall = lazy(() =>
import('~/pages/onboarding/BookCall').then((module) => ({
default: module.BookCall,
@@ -219,14 +213,6 @@ const createWorkspaceAppRouter = (
</LazyRoute>
}
/>
<Route
path={AppPath.BookCallDecision}
element={
<LazyRoute fallback={null}>
<BookCallDecision />
</LazyRoute>
}
/>
<Route
path={AppPath.BookCall}
element={
@@ -8,6 +8,5 @@ export const ONBOARDING_PATHS = [
AppPath.InviteTeam,
AppPath.PlanRequired,
AppPath.PlanRequiredSuccess,
AppPath.BookCallDecision,
AppPath.BookCall,
];
@@ -1 +0,0 @@
export const BOOK_CALL_MODAL_ID = 'book-call-modal';
@@ -1,9 +0,0 @@
import { gql } from '@apollo/client';
export const SKIP_BOOK_ONBOARDING_STEP = gql`
mutation SkipBookOnboardingStep {
skipBookOnboardingStep {
success
}
}
`;
@@ -152,20 +152,4 @@ describe('useSetNextOnboardingStatus', () => {
});
expect(nextOnboardingStatus).toEqual(OnboardingStatus.PLAN_REQUIRED);
});
it('should complete after booking onboarding when the workspace already has a subscription', () => {
const nextOnboardingStatus = renderHooks(OnboardingStatus.BOOK_ONBOARDING, {
isBillingEnabled: true,
withSubscription: true,
});
expect(nextOnboardingStatus).toEqual(OnboardingStatus.COMPLETED);
});
it('should require a plan after booking onboarding when billing is enabled and the workspace has no subscription', () => {
const nextOnboardingStatus = renderHooks(OnboardingStatus.BOOK_ONBOARDING, {
isBillingEnabled: true,
withSubscription: false,
});
expect(nextOnboardingStatus).toEqual(OnboardingStatus.PLAN_REQUIRED);
});
});
@@ -9,7 +9,6 @@ import {
currentWorkspaceState,
} from '@/auth/states/currentWorkspaceState';
import { billingState } from '@/client-config/states/billingState';
import { calendarBookingPageIdState } from '@/client-config/states/calendarBookingPageIdState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useCallback } from 'react';
@@ -19,14 +18,12 @@ import { useStore } from 'jotai';
type GetNextOnboardingStatusArgs = {
currentUser: CurrentUser | null;
currentWorkspace: CurrentWorkspace | null;
calendarBookingPageId: string | null;
isBillingEnabled: boolean;
};
const getNextOnboardingStatus = ({
currentUser,
currentWorkspace,
calendarBookingPageId,
isBillingEnabled,
}: GetNextOnboardingStatusArgs) => {
const isPlanRequired =
@@ -54,14 +51,6 @@ const getNextOnboardingStatus = ({
: OnboardingStatus.COMPLETED;
}
if (currentUser?.onboardingStatus === OnboardingStatus.INVITE_TEAM) {
if (isPlanRequired) {
return OnboardingStatus.PLAN_REQUIRED;
}
return isDefined(calendarBookingPageId)
? OnboardingStatus.BOOK_ONBOARDING
: OnboardingStatus.COMPLETED;
}
if (currentUser?.onboardingStatus === OnboardingStatus.BOOK_ONBOARDING) {
return isPlanRequired
? OnboardingStatus.PLAN_REQUIRED
: OnboardingStatus.COMPLETED;
@@ -73,7 +62,6 @@ export const useSetNextOnboardingStatus = () => {
const store = useStore();
const currentUser = useAtomStateValue(currentUserState);
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
const calendarBookingPageId = useAtomStateValue(calendarBookingPageIdState);
const billing = useAtomStateValue(billingState);
const isBillingEnabled = billing?.isBillingEnabled ?? false;
@@ -81,7 +69,6 @@ export const useSetNextOnboardingStatus = () => {
const nextOnboardingStatus = getNextOnboardingStatus({
currentUser,
currentWorkspace,
calendarBookingPageId,
isBillingEnabled,
});
store.set(currentUserState.atom, (current) => {
@@ -93,11 +80,5 @@ export const useSetNextOnboardingStatus = () => {
}
return current;
});
}, [
currentUser,
currentWorkspace,
calendarBookingPageId,
isBillingEnabled,
store,
]);
}, [currentUser, currentWorkspace, isBillingEnabled, store]);
};
@@ -4,21 +4,15 @@ import { Link } from 'react-router-dom';
import { currentUserState } from '@/auth/states/currentUserState';
import { calendarBookingPageIdState } from '@/client-config/states/calendarBookingPageIdState';
import { useSetNextOnboardingStatus } from '@/onboarding/hooks/useSetNextOnboardingStatus';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { AppPath } from 'twenty-shared/types';
import { IconChevronLeft, IconChevronRightPipe } from 'twenty-ui/icon';
import { IconChevronLeft } from 'twenty-ui/icon';
import { LightButton } from 'twenty-ui/input';
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
import { useIsMobile } from 'twenty-ui/utilities';
import { useMutation } from '@apollo/client/react';
import {
OnboardingStatus,
SkipBookOnboardingStepDocument,
} from '~/generated-metadata/graphql';
const StyledPage = styled.div`
display: flex;
@@ -51,20 +45,9 @@ export const BookCall = () => {
const { t } = useLingui();
const calendarBookingPageId = useAtomStateValue(calendarBookingPageIdState);
const setNextOnboardingStatus = useSetNextOnboardingStatus();
const currentUser = useAtomStateValue(currentUserState);
const [skipBookOnboardingStepMutation] = useMutation(
SkipBookOnboardingStepDocument,
);
const isMobile = useIsMobile();
const isPlanRequired =
currentUser?.onboardingStatus === OnboardingStatus.PLAN_REQUIRED;
const handleCompleteOnboarding = async () => {
await skipBookOnboardingStepMutation();
setNextOnboardingStatus();
};
return (
<StyledPage>
@@ -85,17 +68,9 @@ export const BookCall = () => {
</ScrollWrapper>
</StyledContent>
<StyledFooter>
{isPlanRequired ? (
<Link to={AppPath.PlanRequired}>
<LightButton Icon={IconChevronLeft} title={t`Back`} />
</Link>
) : (
<LightButton
Icon={IconChevronRightPipe}
title={t`Skip`}
onClick={handleCompleteOnboarding}
/>
)}
<Link to={AppPath.PlanRequired}>
<LightButton Icon={IconChevronLeft} title={t`Back`} />
</Link>
</StyledFooter>
</StyledPage>
);
@@ -1,89 +0,0 @@
import { SubTitle } from '@/auth/components/SubTitle';
import { Title } from '@/auth/components/Title';
import { useSetNextOnboardingStatus } from '@/onboarding/hooks/useSetNextOnboardingStatus';
import { styled } from '@linaria/react';
import { Trans, useLingui } from '@lingui/react/macro';
import { Link } from 'react-router-dom';
import { AppPath } from 'twenty-shared/types';
import { LightButton, MainButton } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { useMutation } from '@apollo/client/react';
import { SkipBookOnboardingStepDocument } from '~/generated-metadata/graphql';
const StyledPage = styled.div`
align-items: center;
display: flex;
flex: 1;
flex-direction: column;
gap: ${themeCssVariables.spacing[8]};
justify-content: center;
min-height: 0;
width: 100%;
`;
const StyledCoverImage = styled.img`
border-radius: ${themeCssVariables.border.radius.sm};
height: 204px;
max-width: 100%;
object-fit: cover;
width: 320px;
`;
const StyledTitleContainer = styled.div`
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
`;
const StyledButtonContainer = styled.div`
align-items: center;
display: flex;
flex-direction: column;
gap: ${themeCssVariables.spacing[4]};
width: 100%;
`;
const StyledLinkContainer = styled.div`
> a {
text-decoration: none;
}
`;
export const BookCallDecision = () => {
const { t } = useLingui();
const setNextOnboardingStatus = useSetNextOnboardingStatus();
const [skipBookOnboardingStepMutation] = useMutation(
SkipBookOnboardingStepDocument,
);
const handleFinish = async () => {
await skipBookOnboardingStepMutation();
setNextOnboardingStatus();
};
return (
<StyledPage>
<StyledTitleContainer>
<Title noMarginTop>
<Trans>Book your onboarding</Trans>
</Title>
<SubTitle>
<Trans>
Our team can help you set up your workspace to match your specific
needs and workflows.
</Trans>
</SubTitle>
</StyledTitleContainer>
<StyledCoverImage src="/images/placeholders/onboarding-covers/onboarding-book-call-decision-cover.png" />
<StyledButtonContainer>
<StyledLinkContainer>
<Link to={AppPath.BookCall}>
<MainButton title={t`Book onboarding`} width={198} />
</Link>
</StyledLinkContainer>
<LightButton title={t`Finish`} onClick={handleFinish} />
</StyledButtonContainer>
</StyledPage>
);
};
@@ -5,6 +5,5 @@ export enum OnboardingStatus {
SYNC_EMAIL = 'SYNC_EMAIL',
APPS_INSTALLATION = 'APPS_INSTALLATION',
INVITE_TEAM = 'INVITE_TEAM',
BOOK_ONBOARDING = 'BOOK_ONBOARDING',
COMPLETED = 'COMPLETED',
}
@@ -56,19 +56,6 @@ export class OnboardingResolver {
return { success: true };
}
@Mutation(() => OnboardingStepSuccessDTO)
@UseGuards(NoPermissionGuard)
async skipBookOnboardingStep(
@AuthWorkspace() workspace: WorkspaceEntity,
): Promise<OnboardingStepSuccessDTO> {
await this.onboardingService.setOnboardingBookOnboardingPending({
workspaceId: workspace.id,
value: false,
});
return { success: true };
}
@Mutation(() => OnboardingStepSuccessDTO)
@UseGuards(NoPermissionGuard)
async triggerInstallAppsOnboardingStep(
@@ -1,7 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { type QueryRunner, Repository } from 'typeorm';
@@ -26,7 +25,6 @@ export enum OnboardingStepKeys {
ONBOARDING_CONNECT_ACCOUNT_PENDING = 'ONBOARDING_CONNECT_ACCOUNT_PENDING',
ONBOARDING_INVITE_TEAM_PENDING = 'ONBOARDING_INVITE_TEAM_PENDING',
ONBOARDING_CREATE_PROFILE_PENDING = 'ONBOARDING_CREATE_PROFILE_PENDING',
ONBOARDING_BOOK_ONBOARDING_PENDING = 'ONBOARDING_BOOK_ONBOARDING_PENDING',
ONBOARDING_INSTALL_APPS_PENDING = 'ONBOARDING_INSTALL_APPS_PENDING',
}
@@ -34,7 +32,6 @@ export type OnboardingKeyValueTypeMap = {
[OnboardingStepKeys.ONBOARDING_CONNECT_ACCOUNT_PENDING]: boolean;
[OnboardingStepKeys.ONBOARDING_INVITE_TEAM_PENDING]: boolean;
[OnboardingStepKeys.ONBOARDING_CREATE_PROFILE_PENDING]: boolean;
[OnboardingStepKeys.ONBOARDING_BOOK_ONBOARDING_PENDING]: boolean;
[OnboardingStepKeys.ONBOARDING_INSTALL_APPS_PENDING]: boolean;
};
@@ -103,10 +100,6 @@ export class OnboardingService {
const isInviteTeamPending =
userVars.get(OnboardingStepKeys.ONBOARDING_INVITE_TEAM_PENDING) === true;
const isBookOnboardingPending =
userVars.get(OnboardingStepKeys.ONBOARDING_BOOK_ONBOARDING_PENDING) ===
true;
if (isConnectAccountPending) {
return OnboardingStatus.SYNC_EMAIL;
}
@@ -131,26 +124,6 @@ export class OnboardingService {
return OnboardingStatus.PLAN_REQUIRED;
}
if (isBookOnboardingPending) {
const calendarBookingPageId = this.twentyConfigService.get(
'CALENDAR_BOOKING_PAGE_ID',
);
const isBookingConfigured =
isDefined(calendarBookingPageId) &&
isNonEmptyString(calendarBookingPageId);
if (!isBookingConfigured) {
await this.userVarsService.delete({
workspaceId: workspace.id,
key: OnboardingStepKeys.ONBOARDING_BOOK_ONBOARDING_PENDING,
});
return OnboardingStatus.COMPLETED;
}
return OnboardingStatus.BOOK_ONBOARDING;
}
return OnboardingStatus.COMPLETED;
}
@@ -462,35 +435,4 @@ export class OnboardingService {
value: false,
});
}
async setOnboardingBookOnboardingPending({
workspaceId,
value,
}: {
workspaceId: string;
value: boolean;
}) {
const calendarBookingPageId = this.twentyConfigService.get(
'CALENDAR_BOOKING_PAGE_ID',
);
const isBookingConfigured =
isDefined(calendarBookingPageId) &&
isNonEmptyString(calendarBookingPageId);
if (!value || !isBookingConfigured) {
await this.userVarsService.delete({
workspaceId,
key: OnboardingStepKeys.ONBOARDING_BOOK_ONBOARDING_PENDING,
});
return;
}
await this.userVarsService.set({
workspaceId,
key: OnboardingStepKeys.ONBOARDING_BOOK_ONBOARDING_PENDING,
value: true,
});
}
}
@@ -91,7 +91,6 @@ describe('WorkspaceInvitationService', () => {
provide: OnboardingService,
useValue: {
setOnboardingInviteTeamPending: jest.fn(),
setOnboardingBookOnboardingPending: jest.fn(),
isOnboardingInviteTeamPending: jest.fn().mockResolvedValue(false),
},
},
@@ -227,12 +226,6 @@ describe('WorkspaceInvitationService', () => {
workspaceId: workspace.id,
value: false,
});
expect(
onboardingService.setOnboardingBookOnboardingPending,
).toHaveBeenCalledWith({
workspaceId: workspace.id,
value: true,
});
});
it('should mint reward-eligible tokens when the invite-team step is pending', async () => {
@@ -385,11 +385,6 @@ export class WorkspaceInvitationService {
value: false,
});
await this.onboardingService.setOnboardingBookOnboardingPending({
workspaceId: workspace.id,
value: true,
});
const i18n = this.i18nService.getI18nInstance(sender.locale);
const result = invitationResults.reduce<{
@@ -14,7 +14,6 @@ export enum AppPath {
InviteTeam = '/invite-team',
PlanRequired = '/plan-required',
PlanRequiredSuccess = '/plan-required/payment-success',
BookCallDecision = '/book-call-decision',
BookCall = '/book-call',
// Onboarded