5622 add a syncemail onboarding step (#5689)
- add sync email onboarding step - refactor calendar and email visibility enums - add a new table `keyValuePair` in `core` schema - add a new resolved boolean field `skipSyncEmail` in current user https://github.com/twentyhq/twenty/assets/29927851/de791475-5bfe-47f9-8e90-76c349fba56f
This commit is contained in:
@ -1,7 +1,4 @@
|
||||
export enum CalendarChannelVisibility {
|
||||
Everything = 'SHARE_EVERYTHING',
|
||||
Metadata = 'METADATA',
|
||||
}
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
export type CalendarChannel = {
|
||||
id: string;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { InboxSettingsVisibilityValue } from '@/settings/accounts/components/SettingsAccountsInboxVisibilitySettingsCard';
|
||||
import { MessageChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
export type MessageChannel = {
|
||||
id: string;
|
||||
handle: string;
|
||||
isContactAutoCreationEnabled?: boolean;
|
||||
isSyncEnabled: boolean;
|
||||
visibility: InboxSettingsVisibilityValue;
|
||||
visibility: MessageChannelVisibility;
|
||||
syncStatus: string;
|
||||
__typename: 'MessageChannel';
|
||||
};
|
||||
|
||||
@ -14,6 +14,7 @@ import { hasCalendarEventEnded } from '@/activities/calendar/utils/hasCalendarEv
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
import { TimelineCalendarEvent } from '~/generated-metadata/graphql';
|
||||
import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -118,7 +119,8 @@ export const CalendarEventRow = ({
|
||||
const isCurrentWorkspaceMemberAttending = calendarEvent.participants?.some(
|
||||
({ workspaceMemberId }) => workspaceMemberId === currentWorkspaceMember?.id,
|
||||
);
|
||||
const showTitle = calendarEvent.visibility === 'SHARE_EVERYTHING';
|
||||
const showTitle =
|
||||
calendarEvent.visibility === CalendarChannelVisibility.ShareEverything;
|
||||
|
||||
return (
|
||||
<StyledContainer
|
||||
|
||||
@ -2,6 +2,7 @@ import { act, renderHook } from '@testing-library/react';
|
||||
|
||||
import { useCalendarEvents } from '@/activities/calendar/hooks/useCalendarEvents';
|
||||
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
const calendarEvents: CalendarEvent[] = [
|
||||
{
|
||||
@ -9,7 +10,7 @@ const calendarEvents: CalendarEvent[] = [
|
||||
externalCreatedAt: '2024-02-17T20:45:43.854Z',
|
||||
isFullDay: false,
|
||||
startsAt: '2024-02-17T21:45:27.822Z',
|
||||
visibility: 'METADATA',
|
||||
visibility: CalendarChannelVisibility.Metadata,
|
||||
__typename: 'CalendarEvent',
|
||||
},
|
||||
{
|
||||
@ -17,7 +18,7 @@ const calendarEvents: CalendarEvent[] = [
|
||||
externalCreatedAt: '2024-02-18T19:43:37.854Z',
|
||||
isFullDay: false,
|
||||
startsAt: '2024-02-18T21:43:27.754Z',
|
||||
visibility: 'SHARE_EVERYTHING',
|
||||
visibility: CalendarChannelVisibility.ShareEverything,
|
||||
__typename: 'CalendarEvent',
|
||||
},
|
||||
{
|
||||
@ -25,7 +26,7 @@ const calendarEvents: CalendarEvent[] = [
|
||||
externalCreatedAt: '2024-02-19T20:45:20.854Z',
|
||||
isFullDay: true,
|
||||
startsAt: '2024-02-19T22:05:27.653Z',
|
||||
visibility: 'METADATA',
|
||||
visibility: CalendarChannelVisibility.Metadata,
|
||||
__typename: 'CalendarEvent',
|
||||
},
|
||||
{
|
||||
@ -33,7 +34,7 @@ const calendarEvents: CalendarEvent[] = [
|
||||
externalCreatedAt: '2024-02-20T20:45:12.854Z',
|
||||
isFullDay: true,
|
||||
startsAt: '2024-02-20T23:15:23.150Z',
|
||||
visibility: 'SHARE_EVERYTHING',
|
||||
visibility: CalendarChannelVisibility.ShareEverything,
|
||||
__typename: 'CalendarEvent',
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { CalendarEventParticipant } from '@/activities/calendar/types/CalendarEventParticipant';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
// TODO: use backend CalendarEvent type when ready
|
||||
export type CalendarEvent = {
|
||||
@ -15,7 +16,7 @@ export type CalendarEvent = {
|
||||
location?: string;
|
||||
startsAt: string;
|
||||
title?: string;
|
||||
visibility: 'METADATA' | 'SHARE_EVERYTHING';
|
||||
visibility: CalendarChannelVisibility;
|
||||
calendarEventParticipants?: CalendarEventParticipant[];
|
||||
__typename: 'CalendarEvent';
|
||||
};
|
||||
|
||||
@ -8,18 +8,22 @@ import { useEmailThread } from '@/activities/emails/hooks/useEmailThread';
|
||||
import { emailThreadIdWhenEmailThreadWasClosedState } from '@/activities/emails/states/lastViewableEmailThreadIdState';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||
import { TimelineThread } from '~/generated/graphql';
|
||||
import { MessageChannelVisibility, TimelineThread } from '~/generated/graphql';
|
||||
import { formatToHumanReadableDate } from '~/utils';
|
||||
import { getImageAbsoluteURIOrBase64 } from '~/utils/image/getImageAbsoluteURIOrBase64';
|
||||
|
||||
const StyledCardContent = styled(CardContent)<{ visibility: string }>`
|
||||
const StyledCardContent = styled(CardContent)<{
|
||||
visibility: MessageChannelVisibility;
|
||||
}>`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
height: ${({ theme }) => theme.spacing(12)};
|
||||
padding: ${({ theme }) => theme.spacing(0, 4)};
|
||||
cursor: ${({ visibility }) =>
|
||||
visibility === 'share_everything' ? 'pointer' : 'default'};
|
||||
visibility === MessageChannelVisibility.ShareEverything
|
||||
? 'pointer'
|
||||
: 'default'};
|
||||
`;
|
||||
|
||||
const StyledHeading = styled.div<{ unread: boolean }>`
|
||||
@ -78,8 +82,6 @@ const StyledReceivedAt = styled.div`
|
||||
padding: ${({ theme }) => theme.spacing(0, 1)};
|
||||
`;
|
||||
|
||||
export type EmailThreadVisibility = 'metadata' | 'subject' | 'share_everything';
|
||||
|
||||
type EmailThreadPreviewProps = {
|
||||
divider?: boolean;
|
||||
thread: TimelineThread;
|
||||
@ -93,7 +95,7 @@ export const EmailThreadPreview = ({
|
||||
|
||||
const { openEmailThread } = useEmailThread();
|
||||
|
||||
const visibility = thread.visibility as EmailThreadVisibility;
|
||||
const visibility = thread.visibility;
|
||||
|
||||
const senderNames =
|
||||
thread.firstParticipant.displayName +
|
||||
@ -126,7 +128,7 @@ export const EmailThreadPreview = ({
|
||||
.getValue();
|
||||
|
||||
const canOpen =
|
||||
thread.visibility === 'share_everything' &&
|
||||
thread.visibility === MessageChannelVisibility.ShareEverything &&
|
||||
(!clickJustTriggeredEmailDrawerClose ||
|
||||
emailThreadIdWhenEmailThreadWasClosed !== thread.id);
|
||||
|
||||
@ -183,13 +185,15 @@ export const EmailThreadPreview = ({
|
||||
</StyledHeading>
|
||||
|
||||
<StyledSubjectAndBody>
|
||||
{visibility !== 'metadata' && (
|
||||
{visibility !== MessageChannelVisibility.Metadata && (
|
||||
<StyledSubject>{thread.subject}</StyledSubject>
|
||||
)}
|
||||
{visibility === 'share_everything' && (
|
||||
{visibility === MessageChannelVisibility.ShareEverything && (
|
||||
<StyledBody>{thread.lastMessageBody}</StyledBody>
|
||||
)}
|
||||
{visibility !== 'share_everything' && <EmailThreadNotShared />}
|
||||
{visibility !== MessageChannelVisibility.ShareEverything && (
|
||||
<EmailThreadNotShared />
|
||||
)}
|
||||
</StyledSubjectAndBody>
|
||||
<StyledReceivedAt>
|
||||
{formatToHumanReadableDate(thread.lastMessageReceivedAt)}
|
||||
|
||||
@ -3,6 +3,7 @@ import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus';
|
||||
import { CurrentUser, currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import {
|
||||
CurrentWorkspace,
|
||||
@ -20,6 +21,13 @@ const billing = {
|
||||
billingUrl: 'testing.com',
|
||||
isBillingEnabled: true,
|
||||
};
|
||||
const currentUser = {
|
||||
id: '1',
|
||||
email: 'test@test',
|
||||
supportUserHash: '1',
|
||||
canImpersonate: false,
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser;
|
||||
const currentWorkspace = {
|
||||
activationStatus: 'active',
|
||||
id: '1',
|
||||
@ -27,7 +35,7 @@ const currentWorkspace = {
|
||||
currentBillingSubscription: {
|
||||
status: 'trialing',
|
||||
},
|
||||
};
|
||||
} as CurrentWorkspace;
|
||||
const currentWorkspaceMember = {
|
||||
id: '1',
|
||||
locale: '',
|
||||
@ -46,12 +54,14 @@ const renderHooks = () => {
|
||||
const setCurrentWorkspaceMember = useSetRecoilState(
|
||||
currentWorkspaceMemberState,
|
||||
);
|
||||
const setCurrentUser = useSetRecoilState(currentUserState);
|
||||
const setTokenPair = useSetRecoilState(tokenPairState);
|
||||
const setVerifyPending = useSetRecoilState(isVerifyPendingState);
|
||||
|
||||
return {
|
||||
onboardingStatus,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
setTokenPair,
|
||||
@ -77,6 +87,7 @@ describe('useOnboardingStatus', () => {
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -84,10 +95,11 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'incomplete',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
setCurrentWorkspaceMember(currentWorkspaceMember);
|
||||
});
|
||||
|
||||
@ -99,6 +111,7 @@ describe('useOnboardingStatus', () => {
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -106,10 +119,11 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'canceled',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
setCurrentWorkspaceMember({
|
||||
...currentWorkspaceMember,
|
||||
name: {
|
||||
@ -124,16 +138,18 @@ describe('useOnboardingStatus', () => {
|
||||
|
||||
it('should return "ongoing_workspace_activation"', async () => {
|
||||
const { result } = renderHooks();
|
||||
const { setTokenPair, setBilling, setCurrentWorkspace } = result.current;
|
||||
const { setTokenPair, setBilling, setCurrentUser, setCurrentWorkspace } =
|
||||
result.current;
|
||||
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
activationStatus: 'inactive',
|
||||
subscriptionStatus: 'active',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.onboardingStatus).toBe(
|
||||
@ -146,6 +162,7 @@ describe('useOnboardingStatus', () => {
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -153,21 +170,56 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'active',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
setCurrentWorkspaceMember(currentWorkspaceMember);
|
||||
});
|
||||
|
||||
expect(result.current.onboardingStatus).toBe('ongoing_profile_creation');
|
||||
});
|
||||
|
||||
it('should return "ongoing_sync_email"', async () => {
|
||||
const { result } = renderHooks();
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser({
|
||||
...currentUser,
|
||||
state: { skipSyncEmailOnboardingStep: false },
|
||||
});
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'active',
|
||||
});
|
||||
setCurrentWorkspaceMember({
|
||||
...currentWorkspaceMember,
|
||||
name: {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.onboardingStatus).toBe('ongoing_sync_email');
|
||||
});
|
||||
|
||||
it('should return "completed"', async () => {
|
||||
const { result } = renderHooks();
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -175,10 +227,11 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'active',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
setCurrentWorkspaceMember({
|
||||
...currentWorkspaceMember,
|
||||
name: {
|
||||
@ -196,6 +249,7 @@ describe('useOnboardingStatus', () => {
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -203,10 +257,11 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'past_due',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
setCurrentWorkspaceMember({
|
||||
...currentWorkspaceMember,
|
||||
name: {
|
||||
@ -224,6 +279,7 @@ describe('useOnboardingStatus', () => {
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -231,10 +287,11 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'unpaid',
|
||||
} as CurrentWorkspace);
|
||||
});
|
||||
setCurrentWorkspaceMember({
|
||||
...currentWorkspaceMember,
|
||||
name: {
|
||||
@ -252,6 +309,7 @@ describe('useOnboardingStatus', () => {
|
||||
const {
|
||||
setTokenPair,
|
||||
setBilling,
|
||||
setCurrentUser,
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
} = result.current;
|
||||
@ -259,6 +317,7 @@ describe('useOnboardingStatus', () => {
|
||||
act(() => {
|
||||
setTokenPair(tokenPair);
|
||||
setBilling(billing);
|
||||
setCurrentUser(currentUser);
|
||||
setCurrentWorkspace({
|
||||
...currentWorkspace,
|
||||
subscriptionStatus: 'trialing',
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
@ -14,12 +15,14 @@ export const useOnboardingStatus = (): OnboardingStatus | undefined => {
|
||||
const billing = useRecoilValue(billingState);
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
const isLoggedIn = useIsLogged();
|
||||
|
||||
return getOnboardingStatus({
|
||||
isLoggedIn,
|
||||
currentWorkspaceMember,
|
||||
currentWorkspace,
|
||||
currentUser,
|
||||
isBillingEnabled: billing?.isBillingEnabled || false,
|
||||
});
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@ import { User } from '~/generated/graphql';
|
||||
|
||||
export type CurrentUser = Pick<
|
||||
User,
|
||||
'id' | 'email' | 'supportUserHash' | 'canImpersonate'
|
||||
'id' | 'email' | 'supportUserHash' | 'canImpersonate' | 'state'
|
||||
>;
|
||||
|
||||
export const currentUserState = createState<CurrentUser | null>({
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { CurrentUser } from '@/auth/states/currentUserState';
|
||||
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
|
||||
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||
|
||||
@ -9,6 +10,7 @@ describe('getOnboardingStatus', () => {
|
||||
isLoggedIn: false,
|
||||
currentWorkspaceMember: null,
|
||||
currentWorkspace: null,
|
||||
currentUser: null,
|
||||
isBillingEnabled: false,
|
||||
});
|
||||
|
||||
@ -19,6 +21,9 @@ describe('getOnboardingStatus', () => {
|
||||
id: '1',
|
||||
activationStatus: 'inactive',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: false,
|
||||
});
|
||||
|
||||
@ -32,6 +37,28 @@ describe('getOnboardingStatus', () => {
|
||||
id: '1',
|
||||
activationStatus: 'active',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: false,
|
||||
});
|
||||
|
||||
const ongoingSyncEmail = getOnboardingStatus({
|
||||
isLoggedIn: true,
|
||||
currentWorkspaceMember: {
|
||||
id: '1',
|
||||
name: {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
},
|
||||
} as WorkspaceMember,
|
||||
currentWorkspace: {
|
||||
id: '1',
|
||||
activationStatus: 'active',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: false },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: false,
|
||||
});
|
||||
|
||||
@ -48,6 +75,9 @@ describe('getOnboardingStatus', () => {
|
||||
id: '1',
|
||||
activationStatus: 'active',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: false,
|
||||
});
|
||||
|
||||
@ -65,6 +95,9 @@ describe('getOnboardingStatus', () => {
|
||||
activationStatus: 'active',
|
||||
subscriptionStatus: 'incomplete',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: true,
|
||||
});
|
||||
|
||||
@ -82,6 +115,9 @@ describe('getOnboardingStatus', () => {
|
||||
activationStatus: 'active',
|
||||
subscriptionStatus: 'incomplete',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: false,
|
||||
});
|
||||
|
||||
@ -99,12 +135,16 @@ describe('getOnboardingStatus', () => {
|
||||
activationStatus: 'active',
|
||||
subscriptionStatus: 'canceled',
|
||||
} as CurrentWorkspace,
|
||||
currentUser: {
|
||||
state: { skipSyncEmailOnboardingStep: true },
|
||||
} as CurrentUser,
|
||||
isBillingEnabled: true,
|
||||
});
|
||||
|
||||
expect(ongoingUserCreation).toBe('ongoing_user_creation');
|
||||
expect(ongoingWorkspaceActivation).toBe('ongoing_workspace_activation');
|
||||
expect(ongoingProfileCreation).toBe('ongoing_profile_creation');
|
||||
expect(ongoingSyncEmail).toBe('ongoing_sync_email');
|
||||
expect(completed).toBe('completed');
|
||||
expect(incomplete).toBe('incomplete');
|
||||
expect(canceled).toBe('canceled');
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { CurrentUser } from '@/auth/states/currentUserState';
|
||||
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
|
||||
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||
|
||||
@ -9,6 +10,7 @@ export enum OnboardingStatus {
|
||||
OngoingUserCreation = 'ongoing_user_creation',
|
||||
OngoingWorkspaceActivation = 'ongoing_workspace_activation',
|
||||
OngoingProfileCreation = 'ongoing_profile_creation',
|
||||
OngoingSyncEmail = 'ongoing_sync_email',
|
||||
Completed = 'completed',
|
||||
CompletedWithoutSubscription = 'completed_without_subscription',
|
||||
}
|
||||
@ -17,6 +19,7 @@ export const getOnboardingStatus = ({
|
||||
isLoggedIn,
|
||||
currentWorkspaceMember,
|
||||
currentWorkspace,
|
||||
currentUser,
|
||||
isBillingEnabled,
|
||||
}: {
|
||||
isLoggedIn: boolean;
|
||||
@ -25,6 +28,7 @@ export const getOnboardingStatus = ({
|
||||
'createdAt' | 'updatedAt' | 'userId' | 'userEmail' | '__typename'
|
||||
> | null;
|
||||
currentWorkspace: CurrentWorkspace | null;
|
||||
currentUser: CurrentUser | null;
|
||||
isBillingEnabled: boolean;
|
||||
}) => {
|
||||
if (!isLoggedIn) {
|
||||
@ -33,7 +37,7 @@ export const getOnboardingStatus = ({
|
||||
|
||||
// After SignInUp, the user should have a current workspace assigned.
|
||||
// If not, it indicates that the data is still being requested.
|
||||
if (!currentWorkspace) {
|
||||
if (!currentWorkspace || !currentUser) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -55,6 +59,10 @@ export const getOnboardingStatus = ({
|
||||
return OnboardingStatus.OngoingProfileCreation;
|
||||
}
|
||||
|
||||
if (!currentUser.state.skipSyncEmailOnboardingStep) {
|
||||
return OnboardingStatus.OngoingSyncEmail;
|
||||
}
|
||||
|
||||
if (isBillingEnabled && currentWorkspace.subscriptionStatus === 'canceled') {
|
||||
return OnboardingStatus.Canceled;
|
||||
}
|
||||
|
||||
@ -292,6 +292,66 @@ export const getObjectMetadataItemsMock = () => {
|
||||
updatedAt: '2023-11-30T11:13:15.206Z',
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
__typename: 'object',
|
||||
id: '3aac4582-f677-4d7d-acd5-3e33a039acdd',
|
||||
dataSourceId: '20202020-7f63-47a9-b1b3-6c7290ca9fb1',
|
||||
nameSingular: 'connectedAccount',
|
||||
namePlural: 'connectedAccounts',
|
||||
labelSingular: 'Connected Account',
|
||||
labelPlural: 'Connected Accounts',
|
||||
description: 'A connected account',
|
||||
icon: 'IconAt',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
createdAt: '2024-06-01T14:55:04.039Z',
|
||||
updatedAt: '2024-06-01T14:55:04.039Z',
|
||||
labelIdentifierFieldMetadataId: null,
|
||||
imageIdentifierFieldMetadataId: null,
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
__typename: 'object',
|
||||
id: '3aac4582-f677-4d7d-acd5-3e33a039acde',
|
||||
dataSourceId: '20202020-7f63-47a9-b1b3-6c7290ca9fb1',
|
||||
nameSingular: 'messageChannel',
|
||||
namePlural: 'messageChannels',
|
||||
labelSingular: 'Message Channel',
|
||||
labelPlural: 'Message Channels',
|
||||
description: 'A message channel',
|
||||
icon: 'IconAt',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
createdAt: '2024-06-01T14:55:04.039Z',
|
||||
updatedAt: '2024-06-01T14:55:04.039Z',
|
||||
labelIdentifierFieldMetadataId: null,
|
||||
imageIdentifierFieldMetadataId: null,
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
__typename: 'object',
|
||||
id: '3aac4582-f677-4d7d-acd5-3e33a039acdf',
|
||||
dataSourceId: '20202020-7f63-47a9-b1b3-6c7290ca9fb1',
|
||||
nameSingular: 'calendarChannel',
|
||||
namePlural: 'calendarChannels',
|
||||
labelSingular: 'Calendar Channel',
|
||||
labelPlural: 'Calendar Channels',
|
||||
description: 'A calendar channel',
|
||||
icon: 'IconAt',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
createdAt: '2024-06-01T14:55:04.039Z',
|
||||
updatedAt: '2024-06-01T14:55:04.039Z',
|
||||
labelIdentifierFieldMetadataId: null,
|
||||
imageIdentifierFieldMetadataId: null,
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
__typename: 'object',
|
||||
id: '20202020-cae9-4ff4-9579-f7d9fe44c937',
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
import { onboardingSyncEmailsOptions } from '@/onboarding/components/onboardingSyncEmailsOptions';
|
||||
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
|
||||
import { MessageChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
type OnboardingSyncEmailsSettingsCardProps = {
|
||||
onChange: (nextValue: MessageChannelVisibility) => void;
|
||||
value?: MessageChannelVisibility;
|
||||
};
|
||||
|
||||
export const OnboardingSyncEmailsSettingsCard = ({
|
||||
onChange,
|
||||
value = MessageChannelVisibility.ShareEverything,
|
||||
}: OnboardingSyncEmailsSettingsCardProps) => (
|
||||
<SettingsAccountsRadioSettingsCard
|
||||
options={onboardingSyncEmailsOptions}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
@ -0,0 +1,38 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { SettingsAccountsVisibilitySettingCardMedia } from '@/settings/accounts/components/SettingsAccountsVisibilitySettingCardMedia';
|
||||
import { MessageChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
const StyledCardMedia = styled(SettingsAccountsVisibilitySettingCardMedia)`
|
||||
width: ${({ theme }) => theme.spacing(10)};
|
||||
`;
|
||||
|
||||
export const onboardingSyncEmailsOptions = [
|
||||
{
|
||||
title: 'Everything',
|
||||
description:
|
||||
'Your emails and events content will be shared with your team.',
|
||||
value: MessageChannelVisibility.ShareEverything,
|
||||
cardMedia: (
|
||||
<StyledCardMedia metadata="active" subject="active" body="active" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Subject and metadata',
|
||||
description:
|
||||
'Your email subjects and meeting titles will be shared with your team.',
|
||||
value: MessageChannelVisibility.Subject,
|
||||
cardMedia: (
|
||||
<StyledCardMedia metadata="active" subject="active" body="inactive" />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Metadata',
|
||||
description:
|
||||
'Only the timestamp & participants will be shared with your team.',
|
||||
value: MessageChannelVisibility.Metadata,
|
||||
cardMedia: (
|
||||
<StyledCardMedia metadata="active" subject="inactive" body="inactive" />
|
||||
),
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,9 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const SKIP_SYNC_EMAIL_ONBOARDING_STEP = gql`
|
||||
mutation SkipSyncEmailOnboardingStep {
|
||||
skipSyncEmailOnboardingStep {
|
||||
success
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -1,8 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { CalendarChannelVisibility } from '@/accounts/types/CalendarChannel';
|
||||
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
|
||||
import { SettingsAccountsVisibilitySettingCardMedia } from '@/settings/accounts/components/SettingsAccountsVisibilitySettingCardMedia';
|
||||
import { CalendarChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
type SettingsAccountsEventVisibilitySettingsCardProps = {
|
||||
onChange: (nextValue: CalendarChannelVisibility) => void;
|
||||
@ -17,7 +17,7 @@ const eventSettingsVisibilityOptions = [
|
||||
{
|
||||
title: 'Everything',
|
||||
description: 'The whole event details will be shared with your team.',
|
||||
value: CalendarChannelVisibility.Everything,
|
||||
value: CalendarChannelVisibility.ShareEverything,
|
||||
cardMedia: <StyledCardMedia subject="active" body="active" />,
|
||||
},
|
||||
{
|
||||
@ -30,7 +30,7 @@ const eventSettingsVisibilityOptions = [
|
||||
|
||||
export const SettingsAccountsEventVisibilitySettingsCard = ({
|
||||
onChange,
|
||||
value = CalendarChannelVisibility.Everything,
|
||||
value = CalendarChannelVisibility.ShareEverything,
|
||||
}: SettingsAccountsEventVisibilitySettingsCardProps) => (
|
||||
<SettingsAccountsRadioSettingsCard
|
||||
options={eventSettingsVisibilityOptions}
|
||||
|
||||
@ -1,22 +1,17 @@
|
||||
import { SettingsAccountsRadioSettingsCard } from '@/settings/accounts/components/SettingsAccountsRadioSettingsCard';
|
||||
import { SettingsAccountsVisibilitySettingCardMedia } from '@/settings/accounts/components/SettingsAccountsVisibilitySettingCardMedia';
|
||||
|
||||
export enum InboxSettingsVisibilityValue {
|
||||
Everything = 'share_everything',
|
||||
SubjectMetadata = 'subject',
|
||||
Metadata = 'metadata',
|
||||
}
|
||||
import { MessageChannelVisibility } from '~/generated/graphql';
|
||||
|
||||
type SettingsAccountsInboxVisibilitySettingsCardProps = {
|
||||
onChange: (nextValue: InboxSettingsVisibilityValue) => void;
|
||||
value?: InboxSettingsVisibilityValue;
|
||||
onChange: (nextValue: MessageChannelVisibility) => void;
|
||||
value?: MessageChannelVisibility;
|
||||
};
|
||||
|
||||
const inboxSettingsVisibilityOptions = [
|
||||
{
|
||||
title: 'Everything',
|
||||
description: 'Subject, body and attachments will be shared with your team.',
|
||||
value: InboxSettingsVisibilityValue.Everything,
|
||||
value: MessageChannelVisibility.ShareEverything,
|
||||
cardMedia: (
|
||||
<SettingsAccountsVisibilitySettingCardMedia
|
||||
metadata="active"
|
||||
@ -28,7 +23,7 @@ const inboxSettingsVisibilityOptions = [
|
||||
{
|
||||
title: 'Subject and metadata',
|
||||
description: 'Subject and metadata will be shared with your team.',
|
||||
value: InboxSettingsVisibilityValue.SubjectMetadata,
|
||||
value: MessageChannelVisibility.Subject,
|
||||
cardMedia: (
|
||||
<SettingsAccountsVisibilitySettingCardMedia
|
||||
metadata="active"
|
||||
@ -40,7 +35,7 @@ const inboxSettingsVisibilityOptions = [
|
||||
{
|
||||
title: 'Metadata',
|
||||
description: 'Timestamp and participants will be shared with your team.',
|
||||
value: InboxSettingsVisibilityValue.Metadata,
|
||||
value: MessageChannelVisibility.Metadata,
|
||||
cardMedia: (
|
||||
<SettingsAccountsVisibilitySettingCardMedia
|
||||
metadata="active"
|
||||
@ -53,7 +48,7 @@ const inboxSettingsVisibilityOptions = [
|
||||
|
||||
export const SettingsAccountsInboxVisibilitySettingsCard = ({
|
||||
onChange,
|
||||
value = InboxSettingsVisibilityValue.Everything,
|
||||
value = MessageChannelVisibility.ShareEverything,
|
||||
}: SettingsAccountsInboxVisibilitySettingsCardProps) => (
|
||||
<SettingsAccountsRadioSettingsCard
|
||||
options={inboxSettingsVisibilityOptions}
|
||||
|
||||
@ -27,6 +27,10 @@ export const SettingsAccountsListEmptyStateCard = ({
|
||||
}: SettingsAccountsListEmptyStateCardProps) => {
|
||||
const { triggerGoogleApisOAuth } = useTriggerGoogleApisOAuth();
|
||||
|
||||
const handleOnClick = async () => {
|
||||
await triggerGoogleApisOAuth();
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<StyledHeader>{label || 'No connected account'}</StyledHeader>
|
||||
@ -35,7 +39,7 @@ export const SettingsAccountsListEmptyStateCard = ({
|
||||
Icon={IconGoogle}
|
||||
title="Connect with Google"
|
||||
variant="secondary"
|
||||
onClick={triggerGoogleApisOAuth}
|
||||
onClick={handleOnClick}
|
||||
/>
|
||||
</StyledBody>
|
||||
</Card>
|
||||
|
||||
@ -50,7 +50,7 @@ export const SettingsAccountsRadioSettingsCard = <
|
||||
options,
|
||||
value,
|
||||
}: SettingsAccountsRadioSettingsCardProps<Option>) => (
|
||||
<Card>
|
||||
<Card rounded>
|
||||
{options.map((option, index) => (
|
||||
<StyledCardContent
|
||||
key={option.value}
|
||||
|
||||
@ -36,7 +36,7 @@ export const SettingsAccountsToggleSettingCard = ({
|
||||
onToggle,
|
||||
title,
|
||||
}: SettingsAccountsToggleSettingCardProps) => (
|
||||
<Card>
|
||||
<Card rounded>
|
||||
<StyledCardContent onClick={() => onToggle(!value)}>
|
||||
{cardMedia}
|
||||
<StyledTitle>{title}</StyledTitle>
|
||||
|
||||
@ -1,21 +1,47 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||
import { useGenerateTransientTokenMutation } from '~/generated/graphql';
|
||||
import {
|
||||
CalendarChannelVisibility,
|
||||
MessageChannelVisibility,
|
||||
useGenerateTransientTokenMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const useTriggerGoogleApisOAuth = () => {
|
||||
const [generateTransientToken] = useGenerateTransientTokenMutation();
|
||||
|
||||
const triggerGoogleApisOAuth = useCallback(async () => {
|
||||
const authServerUrl = REACT_APP_SERVER_BASE_URL;
|
||||
const triggerGoogleApisOAuth = useCallback(
|
||||
async (
|
||||
redirectLocation?: AppPath,
|
||||
messageVisibility?: MessageChannelVisibility,
|
||||
calendarVisibility?: CalendarChannelVisibility,
|
||||
) => {
|
||||
const authServerUrl = REACT_APP_SERVER_BASE_URL;
|
||||
|
||||
const transientToken = await generateTransientToken();
|
||||
const transientToken = await generateTransientToken();
|
||||
|
||||
const token =
|
||||
transientToken.data?.generateTransientToken.transientToken.token;
|
||||
const token =
|
||||
transientToken.data?.generateTransientToken.transientToken.token;
|
||||
|
||||
window.location.href = `${authServerUrl}/auth/google-apis?transientToken=${token}`;
|
||||
}, [generateTransientToken]);
|
||||
let params = `transientToken=${token}`;
|
||||
|
||||
params += redirectLocation
|
||||
? `&redirectLocation=${encodeURIComponent(redirectLocation)}`
|
||||
: '';
|
||||
|
||||
params += calendarVisibility
|
||||
? `&calendarVisibility=${calendarVisibility}`
|
||||
: '';
|
||||
|
||||
params += messageVisibility
|
||||
? `&messageVisibility=${messageVisibility}`
|
||||
: '';
|
||||
|
||||
window.location.href = `${authServerUrl}/auth/google-apis?${params}`;
|
||||
},
|
||||
[generateTransientToken],
|
||||
);
|
||||
|
||||
return { triggerGoogleApisOAuth };
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ export enum AppPath {
|
||||
// Onboarding
|
||||
CreateWorkspace = '/create/workspace',
|
||||
CreateProfile = '/create/profile',
|
||||
SyncEmails = '/sync/emails',
|
||||
PlanRequired = '/plan-required',
|
||||
PlanRequiredSuccess = '/plan-required/payment-success',
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledCard = styled.div<{ fullWidth?: boolean }>`
|
||||
const StyledCard = styled.div<{ fullWidth?: boolean; rounded?: boolean }>`
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
border-radius: ${({ theme, rounded }) =>
|
||||
rounded ? theme.border.radius.md : theme.border.radius.sm};
|
||||
color: ${({ theme }) => theme.font.color.secondary};
|
||||
overflow: hidden;
|
||||
width: ${({ fullWidth }) => (fullWidth ? '100%' : 'auto')};
|
||||
|
||||
@ -46,6 +46,7 @@ const testCases = [
|
||||
{ loc: AppPath.Verify, status: OnboardingStatus.OngoingUserCreation, res: false },
|
||||
{ loc: AppPath.Verify, status: OnboardingStatus.OngoingWorkspaceActivation, res: false },
|
||||
{ loc: AppPath.Verify, status: OnboardingStatus.OngoingProfileCreation, res: false },
|
||||
{ loc: AppPath.Verify, status: OnboardingStatus.OngoingSyncEmail, res: false },
|
||||
{ loc: AppPath.Verify, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.Verify, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -56,6 +57,7 @@ const testCases = [
|
||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.SignInUp, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -66,6 +68,7 @@ const testCases = [
|
||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.Invite, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.Invite, status: OnboardingStatus.Completed, res: true },
|
||||
{ loc: AppPath.Invite, status: OnboardingStatus.CompletedWithoutSubscription, res: true },
|
||||
|
||||
@ -76,6 +79,7 @@ const testCases = [
|
||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Completed, res: true },
|
||||
{ loc: AppPath.ResetPassword, status: OnboardingStatus.CompletedWithoutSubscription, res: true },
|
||||
|
||||
@ -86,6 +90,7 @@ const testCases = [
|
||||
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -96,9 +101,21 @@ const testCases = [
|
||||
{ loc: AppPath.CreateProfile, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.CreateProfile, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.CreateProfile, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.CreateProfile, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.CreateProfile, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.CreateProfile, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.Incomplete, res: true },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.Canceled, res: false },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.Unpaid, res: false },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.PastDue, res: false },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.SyncEmails, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.Incomplete, res: true },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.Canceled, res: true },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.Unpaid, res: false },
|
||||
@ -106,6 +123,7 @@ const testCases = [
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.PlanRequired, status: OnboardingStatus.CompletedWithoutSubscription, res: true },
|
||||
|
||||
@ -116,6 +134,7 @@ const testCases = [
|
||||
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -126,6 +145,7 @@ const testCases = [
|
||||
{ loc: AppPath.Index, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.Index, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.Index, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.Index, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.Index, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.Index, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -136,6 +156,7 @@ const testCases = [
|
||||
{ loc: AppPath.TasksPage, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.TasksPage, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.TasksPage, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.TasksPage, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.TasksPage, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.TasksPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -146,6 +167,7 @@ const testCases = [
|
||||
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -156,6 +178,7 @@ const testCases = [
|
||||
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -166,6 +189,7 @@ const testCases = [
|
||||
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -176,6 +200,7 @@ const testCases = [
|
||||
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -186,6 +211,7 @@ const testCases = [
|
||||
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -196,6 +222,7 @@ const testCases = [
|
||||
{ loc: AppPath.Impersonate, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.Impersonate, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.Impersonate, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.Impersonate, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.Impersonate, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.Impersonate, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -206,6 +233,7 @@ const testCases = [
|
||||
{ loc: AppPath.Authorize, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.Authorize, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.Authorize, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.Authorize, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.Authorize, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.Authorize, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -216,6 +244,7 @@ const testCases = [
|
||||
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
|
||||
@ -226,6 +255,7 @@ const testCases = [
|
||||
{ loc: AppPath.NotFound, status: OnboardingStatus.OngoingUserCreation, res: true },
|
||||
{ loc: AppPath.NotFound, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
|
||||
{ loc: AppPath.NotFound, status: OnboardingStatus.OngoingProfileCreation, res: true },
|
||||
{ loc: AppPath.NotFound, status: OnboardingStatus.OngoingSyncEmail, res: true },
|
||||
{ loc: AppPath.NotFound, status: OnboardingStatus.Completed, res: false },
|
||||
{ loc: AppPath.NotFound, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
|
||||
];
|
||||
|
||||
@ -27,7 +27,8 @@ export const useShowAuthModal = () => {
|
||||
OnboardingStatus.Incomplete === onboardingStatus ||
|
||||
OnboardingStatus.OngoingUserCreation === onboardingStatus ||
|
||||
OnboardingStatus.OngoingProfileCreation === onboardingStatus ||
|
||||
OnboardingStatus.OngoingWorkspaceActivation === onboardingStatus
|
||||
OnboardingStatus.OngoingWorkspaceActivation === onboardingStatus ||
|
||||
OnboardingStatus.OngoingSyncEmail === onboardingStatus
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
@ -7,9 +6,8 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMembe
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadingState';
|
||||
import { workspacesState } from '@/auth/states/workspaces';
|
||||
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
|
||||
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
||||
import { User } from '~/generated/graphql';
|
||||
import { useGetCurrentUserQuery } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const UserProviderEffect = () => {
|
||||
@ -26,9 +24,7 @@ export const UserProviderEffect = () => {
|
||||
currentWorkspaceMemberState,
|
||||
);
|
||||
|
||||
const { loading: queryLoading, data: queryData } = useQuery<{
|
||||
currentUser: User;
|
||||
}>(GET_CURRENT_USER, {
|
||||
const { loading: queryLoading, data: queryData } = useGetCurrentUserQuery({
|
||||
skip: isCurrentUserLoaded,
|
||||
});
|
||||
|
||||
|
||||
@ -8,6 +8,9 @@ export const USER_QUERY_FRAGMENT = gql`
|
||||
email
|
||||
canImpersonate
|
||||
supportUserHash
|
||||
state {
|
||||
skipSyncEmailOnboardingStep
|
||||
}
|
||||
workspaceMember {
|
||||
id
|
||||
name {
|
||||
|
||||
@ -4,52 +4,7 @@ import { gql } from '@apollo/client';
|
||||
export const GET_CURRENT_USER = gql`
|
||||
query GetCurrentUser {
|
||||
currentUser {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
email
|
||||
canImpersonate
|
||||
supportUserHash
|
||||
workspaceMember {
|
||||
id
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
colorScheme
|
||||
avatarUrl
|
||||
locale
|
||||
}
|
||||
defaultWorkspace {
|
||||
id
|
||||
displayName
|
||||
logo
|
||||
domainName
|
||||
inviteHash
|
||||
allowImpersonation
|
||||
subscriptionStatus
|
||||
activationStatus
|
||||
featureFlags {
|
||||
id
|
||||
key
|
||||
value
|
||||
workspaceId
|
||||
}
|
||||
currentCacheVersion
|
||||
currentBillingSubscription {
|
||||
id
|
||||
status
|
||||
interval
|
||||
}
|
||||
}
|
||||
workspaces {
|
||||
workspace {
|
||||
id
|
||||
displayName
|
||||
logo
|
||||
domainName
|
||||
}
|
||||
}
|
||||
...UserQueryFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user