3628 timebox separate user creation from workspace creation (#3737)

* Remove workspace schema creation from signUp

* Set user workspaceMember nullable

* Remove workspace creation

* Handle null workspace in tokens

* Update onboarding status

* Generate types

* Move createWorkspace to workspace resolver

* Create workspace after signup

* Update createWorkspace return type

* Update createWorkspace return type

* Create core.workspace at signup

* WIP

* Fix create workspace

* Fix create workspace

* Clean code

* Remove useless recoil set

* Simplify create workspace request

* Set currentWorkspace at login

* Fix tests

* Create a recoil value for is workspaceSchema created

* Rename createWorkspace to createWorkspaceSchema

* Code review returns

* Use AppPath when possible

* Try without state

* Fix

* Fixes

* Rename createWorkspaceSchema to activateWorkspace

* Remove defaultAvatarUrl from user

* Add defaultAvatarUrl to core user

This reverts commit 1701c30eb18804558293cc42043aedf96ea888df.

* Add defaultAvatarUrl to core user

This reverts commit 1701c30eb18804558293cc42043aedf96ea888df.

* Fix ci

* Fix tests

* Fix storybook

* Fix test

* Remove useless query

* Fix test

* Fix test

* Fix mock data

* Fix test

* Clean Mock Requests

* Fix tentative

* Revert "Clean Mock Requests"

This reverts commit 8aa20a34363ffddfdee24f18fc80b27ea0ad5e1d.

* Fix

* Revert "Fix"

This reverts commit 2df7e9b6569b8bfb53f6a45391db725e28d16a18.

* Revert "Revert "Clean Mock Requests""

This reverts commit 3aefef8e9600d161434a047e845563d1b8e0692e.

* Revert "Fix tentative"

This reverts commit 13e7748d6f3b3858d30fb08adbc8ad347c5556ee.

* Update filename

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
martmull
2024-02-09 12:06:11 +01:00
committed by GitHub
parent 3fc18aeec1
commit 7425223f83
49 changed files with 769 additions and 355 deletions

View File

@ -88,7 +88,7 @@ export const PageChangeEffect = () => {
) {
navigate(AppPath.PlanRequired);
} else if (
onboardingStatus === OnboardingStatus.OngoingWorkspaceCreation &&
onboardingStatus === OnboardingStatus.OngoingWorkspaceActivation &&
!isMatchingLocation(AppPath.CreateWorkspace)
) {
navigate(AppPath.CreateWorkspace);
@ -101,7 +101,7 @@ export const PageChangeEffect = () => {
onboardingStatus === OnboardingStatus.Completed &&
isMatchingOnboardingRoute
) {
navigate('/');
navigate(AppPath.Index);
} else if (isMatchingLocation(AppPath.Invite)) {
const inviteHash =
matchPath({ path: '/invite/:workspaceInviteHash' }, location.pathname)

View File

@ -19,6 +19,10 @@ export type Scalars = {
Upload: any;
};
export type ActivateWorkspaceInput = {
displayName?: InputMaybe<Scalars['String']>;
};
export type Analytics = {
__typename?: 'Analytics';
/** Boolean that confirms query was dispatched */
@ -77,15 +81,6 @@ export type ClientConfig = {
telemetry: Telemetry;
};
export type CreateOneRefreshTokenInput = {
/** The record to create */
refreshToken: CreateRefreshTokenInput;
};
export type CreateRefreshTokenInput = {
expiresAt: Scalars['DateTime'];
};
export type CursorPaging = {
/** Paginate after opaque cursor */
after?: InputMaybe<Scalars['ConnectionCursor']>;
@ -223,6 +218,7 @@ export type LoginToken = {
export type Mutation = {
__typename?: 'Mutation';
activateWorkspace: Workspace;
challenge: LoginToken;
createEvent: Analytics;
createOneObject: Object;
@ -247,6 +243,11 @@ export type Mutation = {
};
export type MutationActivateWorkspaceArgs = {
data: ActivateWorkspaceInput;
};
export type MutationChallengeArgs = {
email: Scalars['String'];
password: Scalars['String'];
@ -259,11 +260,6 @@ export type MutationCreateEventArgs = {
};
export type MutationCreateOneRefreshTokenArgs = {
input: CreateOneRefreshTokenInput;
};
export type MutationDeleteOneObjectArgs = {
input: DeleteOneObjectInput;
};
@ -532,6 +528,7 @@ export type User = {
__typename?: 'User';
canImpersonate: Scalars['Boolean'];
createdAt: Scalars['DateTime'];
defaultAvatarUrl?: Maybe<Scalars['String']>;
defaultWorkspace: Workspace;
deletedAt?: Maybe<Scalars['DateTime']>;
disabled?: Maybe<Scalars['Boolean']>;
@ -545,7 +542,7 @@ export type User = {
passwordResetTokenExpiresAt?: Maybe<Scalars['DateTime']>;
supportUserHash?: Maybe<Scalars['String']>;
updatedAt: Scalars['DateTime'];
workspaceMember: WorkspaceMember;
workspaceMember?: Maybe<WorkspaceMember>;
};
export type UserEdge = {
@ -778,7 +775,7 @@ export type ImpersonateMutationVariables = Exact<{
}>;
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
export type RenewTokenMutationVariables = Exact<{
refreshToken: Scalars['String'];
@ -809,7 +806,7 @@ export type VerifyMutationVariables = Exact<{
}>;
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } };
export type CheckUserExistsQueryVariables = Exact<{
email: Scalars['String'];
@ -846,7 +843,7 @@ export type UploadImageMutationVariables = Exact<{
export type UploadImageMutation = { __typename?: 'Mutation', uploadImage: string };
export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } };
export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } };
export type DeleteUserAccountMutationVariables = Exact<{ [key: string]: never; }>;
@ -860,6 +857,18 @@ export type UploadProfilePictureMutationVariables = Exact<{
export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProfilePicture: string };
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, canImpersonate: boolean, supportUserHash?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale: string, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, defaultWorkspace: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, domainName?: string | null, inviteHash?: string | null, allowImpersonation: boolean, subscriptionStatus: string, featureFlags?: Array<{ __typename?: 'FeatureFlag', id: string, key: string, value: boolean, workspaceId: string }> | null } } };
export type ActivateWorkspaceMutationVariables = Exact<{
input: ActivateWorkspaceInput;
}>;
export type ActivateWorkspaceMutation = { __typename?: 'Mutation', activateWorkspace: { __typename?: 'Workspace', id: string } };
export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: never; }>;
@ -1677,6 +1686,103 @@ export function useUploadProfilePictureMutation(baseOptions?: Apollo.MutationHoo
export type UploadProfilePictureMutationHookResult = ReturnType<typeof useUploadProfilePictureMutation>;
export type UploadProfilePictureMutationResult = Apollo.MutationResult<UploadProfilePictureMutation>;
export type UploadProfilePictureMutationOptions = Apollo.BaseMutationOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>;
export const GetCurrentUserDocument = 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
featureFlags {
id
key
value
workspaceId
}
}
}
}
`;
/**
* __useGetCurrentUserQuery__
*
* To run a query within a React component, call `useGetCurrentUserQuery` and pass it any options that fit your needs.
* When your component renders, `useGetCurrentUserQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetCurrentUserQuery({
* variables: {
* },
* });
*/
export function useGetCurrentUserQuery(baseOptions?: Apollo.QueryHookOptions<GetCurrentUserQuery, GetCurrentUserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetCurrentUserQuery, GetCurrentUserQueryVariables>(GetCurrentUserDocument, options);
}
export function useGetCurrentUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetCurrentUserQuery, GetCurrentUserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetCurrentUserQuery, GetCurrentUserQueryVariables>(GetCurrentUserDocument, options);
}
export type GetCurrentUserQueryHookResult = ReturnType<typeof useGetCurrentUserQuery>;
export type GetCurrentUserLazyQueryHookResult = ReturnType<typeof useGetCurrentUserLazyQuery>;
export type GetCurrentUserQueryResult = Apollo.QueryResult<GetCurrentUserQuery, GetCurrentUserQueryVariables>;
export const ActivateWorkspaceDocument = gql`
mutation ActivateWorkspace($input: ActivateWorkspaceInput!) {
activateWorkspace(data: $input) {
id
}
}
`;
export type ActivateWorkspaceMutationFn = Apollo.MutationFunction<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>;
/**
* __useActivateWorkspaceMutation__
*
* To run a mutation, you first call `useActivateWorkspaceMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useActivateWorkspaceMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [activateWorkspaceMutation, { data, loading, error }] = useActivateWorkspaceMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useActivateWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>(ActivateWorkspaceDocument, options);
}
export type ActivateWorkspaceMutationHookResult = ReturnType<typeof useActivateWorkspaceMutation>;
export type ActivateWorkspaceMutationResult = Apollo.MutationResult<ActivateWorkspaceMutation>;
export type ActivateWorkspaceMutationOptions = Apollo.BaseMutationOptions<ActivateWorkspaceMutation, ActivateWorkspaceMutationVariables>;
export const DeleteCurrentWorkspaceDocument = gql`
mutation DeleteCurrentWorkspace {
deleteCurrentWorkspace {

View File

@ -66,16 +66,6 @@ describe('useOnboardingStatus', () => {
expect(result.current.onboardingStatus).toBe('ongoing_user_creation');
});
it('should return undefined when currentWorkspaceMember in undefined', async () => {
const { result } = renderHooks();
act(() => {
result.current.setTokenPair(tokenPair);
});
expect(result.current.onboardingStatus).toBe(undefined);
});
it('should return "incomplete"', async () => {
const { result } = renderHooks();
const {
@ -120,14 +110,9 @@ describe('useOnboardingStatus', () => {
expect(result.current.onboardingStatus).toBe('canceled');
});
it('should return "ongoing_workspace_creation"', async () => {
it('should return "ongoing_workspace_activation"', async () => {
const { result } = renderHooks();
const {
setTokenPair,
setBilling,
setCurrentWorkspace,
setCurrentWorkspaceMember,
} = result.current;
const { setTokenPair, setBilling, setCurrentWorkspace } = result.current;
act(() => {
setTokenPair(tokenPair);
@ -135,12 +120,31 @@ describe('useOnboardingStatus', () => {
setCurrentWorkspace({
...currentWorkspace,
displayName: '',
subscriptionStatus: 'completed',
subscriptionStatus: 'active',
});
setCurrentWorkspaceMember(currentWorkspaceMember);
});
expect(result.current.onboardingStatus).toBe('ongoing_workspace_creation');
expect(result.current.onboardingStatus).toBe(
'ongoing_workspace_activation',
);
});
it('should return "ongoing_workspace_activation"', async () => {
const { result } = renderHooks();
const { setTokenPair, setBilling, setCurrentWorkspace } = result.current;
act(() => {
setTokenPair(tokenPair);
setBilling(billing);
setCurrentWorkspace({
...currentWorkspace,
subscriptionStatus: 'active',
});
});
expect(result.current.onboardingStatus).toBe(
'ongoing_workspace_activation',
);
});
it('should return "ongoing_profile_creation"', async () => {
@ -157,7 +161,7 @@ describe('useOnboardingStatus', () => {
setBilling(billing);
setCurrentWorkspace({
...currentWorkspace,
subscriptionStatus: 'completed',
subscriptionStatus: 'active',
});
setCurrentWorkspaceMember(currentWorkspaceMember);
});
@ -179,7 +183,7 @@ describe('useOnboardingStatus', () => {
setBilling(billing);
setCurrentWorkspace({
...currentWorkspace,
subscriptionStatus: 'completed',
subscriptionStatus: 'active',
});
setCurrentWorkspaceMember({
...currentWorkspaceMember,

View File

@ -89,13 +89,16 @@ export const useAuth = () => {
setTokenPair(verifyResult.data?.verify.tokens);
const user = verifyResult.data?.verify.user;
const workspaceMember = {
...user.workspaceMember,
colorScheme: user.workspaceMember?.colorScheme as ColorScheme,
};
const workspace = user.defaultWorkspace ?? null;
let workspaceMember = null;
setCurrentUser(user);
setCurrentWorkspaceMember(workspaceMember);
if (user.workspaceMember) {
workspaceMember = {
...user.workspaceMember,
colorScheme: user.workspaceMember?.colorScheme as ColorScheme,
};
setCurrentWorkspaceMember(workspaceMember);
}
const workspace = user.defaultWorkspace ?? null;
setCurrentWorkspace(workspace);
return {
user,

View File

@ -143,16 +143,15 @@ export const useSignInUp = () => {
billing?.isBillingEnabled &&
currentWorkspace.subscriptionStatus !== 'active'
) {
navigate('/plan-required');
navigate(AppPath.PlanRequired);
return;
}
if (currentWorkspace.displayName) {
navigate('/');
navigate(AppPath.Index);
return;
}
navigate('/create/workspace');
navigate(AppPath.CreateWorkspace);
} catch (err: any) {
enqueueSnackBar(err?.message, {
variant: 'error',

View File

@ -0,0 +1,11 @@
import { selector } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
export const isCurrentWorkspaceActiveSelector = selector({
key: 'isCurrentWorkspaceActiveSelector',
get: ({ get }) => {
const currentWorkspaceMember = get(currentWorkspaceMemberState);
return !!currentWorkspaceMember;
},
});

View File

@ -11,27 +11,24 @@ describe('getOnboardingStatus', () => {
currentWorkspace: null,
});
const unknownStatus = getOnboardingStatus({
const ongoingWorkspaceActivation = getOnboardingStatus({
isLoggedIn: true,
currentWorkspaceMember: null,
currentWorkspace: null,
});
const ongoingWorkspaceCreation = getOnboardingStatus({
isLoggedIn: true,
currentWorkspaceMember: {
id: '1',
name: {
firstName: 'John',
lastName: 'Doe',
},
} as WorkspaceMember,
currentWorkspace: {
id: '1',
displayName: null,
} as CurrentWorkspace,
});
const ongoingWorkspaceActivationPreviouslyActive = getOnboardingStatus({
isLoggedIn: true,
currentWorkspaceMember: null,
currentWorkspace: {
id: '1',
displayName: 'My Workspace',
} as CurrentWorkspace,
});
const ongoingProfileCreation = getOnboardingStatus({
isLoggedIn: true,
currentWorkspaceMember: {
@ -110,8 +107,10 @@ describe('getOnboardingStatus', () => {
});
expect(ongoingUserCreation).toBe('ongoing_user_creation');
expect(unknownStatus).toBe(undefined);
expect(ongoingWorkspaceCreation).toBe('ongoing_workspace_creation');
expect(ongoingWorkspaceActivation).toBe('ongoing_workspace_activation');
expect(ongoingWorkspaceActivationPreviouslyActive).toBe(
'ongoing_workspace_activation',
);
expect(ongoingProfileCreation).toBe('ongoing_profile_creation');
expect(completed).toBe('completed');
expect(incomplete).toBe('incomplete');

View File

@ -5,7 +5,7 @@ export enum OnboardingStatus {
Incomplete = 'incomplete',
Canceled = 'canceled',
OngoingUserCreation = 'ongoing_user_creation',
OngoingWorkspaceCreation = 'ongoing_workspace_creation',
OngoingWorkspaceActivation = 'ongoing_workspace_activation',
OngoingProfileCreation = 'ongoing_profile_creation',
Completed = 'completed',
}
@ -28,11 +28,6 @@ export const getOnboardingStatus = ({
return OnboardingStatus.OngoingUserCreation;
}
// if the user has not been fetched yet, we can't know the onboarding status
if (!currentWorkspaceMember) {
return undefined;
}
if (
isBillingEnabled &&
currentWorkspace?.subscriptionStatus === 'incomplete'
@ -44,9 +39,10 @@ export const getOnboardingStatus = ({
return OnboardingStatus.Canceled;
}
if (!currentWorkspace?.displayName) {
return OnboardingStatus.OngoingWorkspaceCreation;
if (!currentWorkspaceMember) {
return OnboardingStatus.OngoingWorkspaceActivation;
}
if (
!currentWorkspaceMember.name.firstName ||
!currentWorkspaceMember.name.lastName

View File

@ -3,6 +3,7 @@ import { Meta, StoryObj } from '@storybook/react';
import { expect, userEvent, within } from '@storybook/test';
import { useSetRecoilState } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { CommandType } from '@/command-menu/types/Command';
@ -11,7 +12,10 @@ import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWith
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockDefaultWorkspace } from '~/testing/mock-data/users';
import {
mockDefaultWorkspace,
mockedWorkspaceMemberData,
} from '~/testing/mock-data/users';
import { sleep } from '~/testing/sleep';
import { CommandMenu } from '../CommandMenu';
@ -24,10 +28,14 @@ const meta: Meta<typeof CommandMenu> = {
decorators: [
(Story) => {
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState,
);
const { addToCommandMenu, setToIntitialCommandMenu, openCommandMenu } =
useCommandMenu();
setCurrentWorkspace(mockDefaultWorkspace);
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
useEffect(() => {
setToIntitialCommandMenu();

View File

@ -3,6 +3,7 @@ import { useRecoilState } from 'recoil';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { AppPath } from '@/types/AppPath';
import {
IconCheckbox,
IconList,
@ -71,7 +72,7 @@ export const MobileNavigationBar = () => {
onClick: () => {
closeCommandMenu();
setIsNavigationDrawerOpen(false);
navigate('/tasks');
navigate(AppPath.TasksPage);
},
},
{

View File

@ -1,6 +1,6 @@
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
@ -9,12 +9,14 @@ export const ObjectMetadataItemsProvider = ({
children,
}: React.PropsWithChildren) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isCurrentWorkspaceActive = useRecoilValue(
isCurrentWorkspaceActiveSelector,
);
return (
<>
<ObjectMetadataItemsLoadEffect />
{(!currentWorkspace || !!objectMetadataItems.length) && (
{(!isCurrentWorkspaceActive || !!objectMetadataItems.length) && (
<RelationPickerScope relationPickerScopeId="relation-picker">
{children}
</RelationPickerScope>

View File

@ -1,7 +1,7 @@
import { gql } from '@apollo/client';
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError';
import { useGetObjectOrderByField } from '@/object-metadata/hooks/useGetObjectOrderByField';
import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapToObjectRecordIdentifier';
@ -40,7 +40,9 @@ export const useObjectMetadataItem = (
{ objectNameSingular }: ObjectMetadataItemIdentifier,
depth?: number,
) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isCurrentWorkspaceActive = useRecoilValue(
isCurrentWorkspaceActiveSelector,
);
const mockObjectMetadataItems = getObjectMetadataItemsMock();
let objectMetadataItem = useRecoilValue(
@ -52,7 +54,7 @@ export const useObjectMetadataItem = (
let objectMetadataItems = useRecoilValue(objectMetadataItemsState);
if (!currentWorkspace) {
if (!isCurrentWorkspaceActive) {
objectMetadataItem =
mockObjectMetadataItems.find(
(objectMetadataItem) =>

View File

@ -1,6 +1,6 @@
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError';
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
@ -12,7 +12,9 @@ import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentif
export const useObjectMetadataItemOnly = ({
objectNameSingular,
}: ObjectMetadataItemIdentifier) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isCurrentWorkspaceActive = useRecoilValue(
isCurrentWorkspaceActiveSelector,
);
const mockObjectMetadataItems = getObjectMetadataItemsMock();
let objectMetadataItem = useRecoilValue(
@ -24,7 +26,7 @@ export const useObjectMetadataItemOnly = ({
let objectMetadataItems = useRecoilValue(objectMetadataItemsState);
if (!currentWorkspace) {
if (!isCurrentWorkspaceActive) {
objectMetadataItem =
mockObjectMetadataItems.find(
(objectMetadataItem) =>

View File

@ -1,6 +1,6 @@
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import { isDefined } from '~/utils/isDefined';
@ -10,7 +10,9 @@ export const useObjectNamePluralFromSingular = ({
}: {
objectNameSingular: string;
}) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isCurrentWorkspaceActive = useRecoilValue(
isCurrentWorkspaceActiveSelector,
);
const mockObjectMetadataItems = getObjectMetadataItemsMock();
let objectMetadataItem = useRecoilValue(
@ -20,7 +22,7 @@ export const useObjectNamePluralFromSingular = ({
}),
);
if (!currentWorkspace) {
if (!isCurrentWorkspaceActive) {
objectMetadataItem =
mockObjectMetadataItems.find(
(objectMetadataItem) =>

View File

@ -1,6 +1,6 @@
import { useRecoilValue } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import { isDefined } from '~/utils/isDefined';
@ -10,7 +10,9 @@ export const useObjectNameSingularFromPlural = ({
}: {
objectNamePlural: string;
}) => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isCurrentWorkspaceActive = useRecoilValue(
isCurrentWorkspaceActiveSelector,
);
const mockObjectMetadataItems = getObjectMetadataItemsMock();
let objectMetadataItem = useRecoilValue(
@ -20,7 +22,7 @@ export const useObjectNameSingularFromPlural = ({
}),
);
if (!currentWorkspace) {
if (!isCurrentWorkspaceActive) {
objectMetadataItem =
mockObjectMetadataItems.find(
(objectMetadataItem) =>

View File

@ -3,7 +3,7 @@ import { MockedProvider } from '@apollo/client/testing';
import { renderHook } from '@testing-library/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import {
@ -39,7 +39,7 @@ const Wrapper = ({ children }: { children: ReactNode }) => (
);
describe('useFindManyRecords', () => {
it('should skip fetch if currentWorkspace is undefined', async () => {
it('should skip fetch if currentWorkspaceMember is undefined', async () => {
const { result } = renderHook(
() => useFindManyRecords({ objectNameSingular: 'person' }),
{
@ -56,12 +56,12 @@ describe('useFindManyRecords', () => {
const { result } = renderHook(
() => {
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
setCurrentWorkspace({
const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState,
);
setCurrentWorkspaceMember({
id: '32219445-f587-4c40-b2b1-6d3205ed96da',
displayName: 'cool-workspace',
allowImpersonation: false,
subscriptionStatus: 'incomplete',
name: { firstName: 'John', lastName: 'Connor' },
});
const mockObjectMetadataItems = getObjectMetadataItemsMock();

View File

@ -4,7 +4,7 @@ import { isNonEmptyArray } from '@apollo/client/utilities';
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { useMapConnectionToRecords } from '@/object-record/hooks/useMapConnectionToRecords';
@ -65,12 +65,12 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
);
const { enqueueSnackBar } = useSnackBar();
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { data, loading, error, fetchMore } = useQuery<
ObjectRecordQueryResult<T>
>(findManyRecordsQuery, {
skip: skip || !objectMetadataItem || !currentWorkspace,
skip: skip || !objectMetadataItem || !currentWorkspaceMember,
variables: {
filter,
limit,

View File

@ -10,6 +10,7 @@ import {
} from '@storybook/test';
import { useSetRecoilState } from 'recoil';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
@ -17,7 +18,10 @@ import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/Componen
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockDefaultWorkspace } from '~/testing/mock-data/users';
import {
mockDefaultWorkspace,
mockedWorkspaceMemberData,
} from '~/testing/mock-data/users';
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
import {
@ -27,10 +31,14 @@ import {
const RelationWorkspaceSetterEffect = () => {
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState,
);
useEffect(() => {
setCurrentWorkspace(mockDefaultWorkspace);
}, [setCurrentWorkspace]);
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
}, [setCurrentWorkspace, setCurrentWorkspaceMember]);
return <></>;
};

View File

@ -1,6 +1,6 @@
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter';
@ -13,8 +13,10 @@ import { useFindManyRecords } from '../../hooks/useFindManyRecords';
export const useLoadRecordIndexTable = (objectNameSingular: string) => {
const { setRecordTableData, setIsRecordTableInitialLoading } =
useRecordTable();
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const isCurrentWorkspaceActive = useRecoilValue(
isCurrentWorkspaceActiveSelector,
);
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
});
@ -51,7 +53,7 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
});
return {
records: currentWorkspace ? records : signInBackgroundMockCompanies,
records: isCurrentWorkspaceActive ? records : signInBackgroundMockCompanies,
loading,
fetchMoreRecords,
queryStateIdentifier,

View File

@ -1,6 +0,0 @@
import { atomFamily } from 'recoil';
export const isCreateModeScopedState = atomFamily<boolean, string>({
key: 'isCreateModeScopedState',
default: false,
});

View File

@ -3,7 +3,7 @@ import { MockedProvider } from '@apollo/client/testing';
import { renderHook } from '@testing-library/react';
import { RecoilRoot, useSetRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
import { EntitiesForMultipleEntitySelect } from '@/object-record/relation-picker/types/EntitiesForMultipleEntitySelect';
@ -66,12 +66,12 @@ describe('useFilteredSearchEntityQuery', () => {
it('returns the correct result when everything is provided', async () => {
const { result } = renderHook(
() => {
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
setCurrentWorkspace({
const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState,
);
setCurrentWorkspaceMember({
id: '32219445-f587-4c40-b2b1-6d3205ed96da',
displayName: 'cool-workspace',
allowImpersonation: false,
subscriptionStatus: 'incomplete',
name: { firstName: 'John', lastName: 'Connor' },
});
const mockObjectMetadataItems = getObjectMetadataItemsMock();

View File

@ -28,7 +28,6 @@ export const SignInBackgroundMockContainerEffect = ({
const {
setAvailableTableColumns,
setOnEntityCountChange,
setRecordTableData,
setTableColumns,
resetTableRowSelection,
} = useRecordTable({
@ -77,7 +76,6 @@ export const SignInBackgroundMockContainerEffect = ({
setAvailableFieldDefinitions,
objectMetadataItem,
setAvailableTableColumns,
setRecordTableData,
setTableColumns,
]);

View File

@ -5,7 +5,7 @@ import { useSetRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { GET_CURRENT_USER_AND_VIEWS } from '@/users/graphql/queries/getCurrentUserAndViews';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
export const UserProvider = ({ children }: React.PropsWithChildren) => {
@ -13,21 +13,22 @@ export const UserProvider = ({ children }: React.PropsWithChildren) => {
const setCurrentUser = useSetRecoilState(currentUserState);
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setCurrentWorkspaceMember = useSetRecoilState(
currentWorkspaceMemberState,
);
const { loading: queryLoading, data: queryData } = useQuery(
GET_CURRENT_USER_AND_VIEWS,
);
const { loading: queryLoading, data: queryData } = useQuery(GET_CURRENT_USER);
useEffect(() => {
if (!queryLoading) {
setIsLoading(false);
}
if (queryData?.currentUser?.workspaceMember) {
if (queryData?.currentUser) {
setCurrentUser(queryData.currentUser);
setCurrentWorkspace(queryData.currentUser.defaultWorkspace);
}
if (queryData?.currentUser?.workspaceMember) {
const workspaceMember = queryData.currentUser.workspaceMember;
setCurrentWorkspaceMember({
...workspaceMember,

View File

@ -0,0 +1,40 @@
// This query cannot be put in the graphQL folder because it cannot be generated by the graphQL codegen.
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
featureFlags {
id
key
value
workspaceId
}
}
}
}
`;

View File

@ -1,103 +0,0 @@
// This query cannot be put in the graphQL folder because it cannot be generated by the graphQL codegen.
import { gql } from '@apollo/client';
export const GET_CURRENT_USER_AND_VIEWS = gql`
query GetCurrentUserAndViews {
currentUser {
id
firstName
lastName
email
canImpersonate
supportUserHash
workspaceMember {
id
name {
firstName
lastName
}
colorScheme
avatarUrl
locale
}
defaultWorkspace {
id
displayName
logo
domainName
inviteHash
allowImpersonation
subscriptionStatus
featureFlags {
id
key
value
workspaceId
}
}
}
views {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
cursor
node {
id
createdAt
updatedAt
name
objectMetadataId
type
deletedAt
viewFilters {
edges {
cursor
node {
id
createdAt
updatedAt
fieldMetadataId
operand
value
displayValue
deletedAt
}
}
}
viewSorts {
edges {
cursor
node {
id
createdAt
updatedAt
fieldMetadataId
direction
deletedAt
}
}
}
viewFields {
edges {
cursor
node {
id
createdAt
updatedAt
fieldMetadataId
isVisible
size
position
deletedAt
}
}
}
}
}
}
}
`;

View File

@ -0,0 +1,9 @@
import { gql } from '@apollo/client';
export const ACTIVATE_WORKSPACE = gql`
mutation ActivateWorkspace($input: ActivateWorkspaceInput!) {
activateWorkspace(data: $input) {
id
}
}
`;

View File

@ -1,6 +1,5 @@
import { useCallback } from 'react';
import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
import { useRecoilState } from 'recoil';
@ -54,7 +53,6 @@ const validationSchema = z
type Form = z.infer<typeof validationSchema>;
export const CreateProfile = () => {
const navigate = useNavigate();
const onboardingStatus = useOnboardingStatus();
const { enqueueSnackBar } = useSnackBar();
@ -114,8 +112,6 @@ export const CreateProfile = () => {
colorScheme: 'System',
}) as any,
);
navigate('/');
} catch (error: any) {
enqueueSnackBar(error?.message, {
variant: 'error',
@ -125,7 +121,6 @@ export const CreateProfile = () => {
[
currentWorkspaceMember?.id,
enqueueSnackBar,
navigate,
setCurrentWorkspaceMember,
updateOneRecord,
],

View File

@ -3,22 +3,24 @@ import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
import { useSetRecoilState } from 'recoil';
import { z } from 'zod';
import { SubTitle } from '@/auth/components/SubTitle';
import { Title } from '@/auth/components/Title';
import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
import { FIND_MANY_OBJECT_METADATA_ITEMS } from '@/object-metadata/graphql/queries';
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
import { WorkspaceLogoUploader } from '@/settings/workspace/components/WorkspaceLogoUploader';
import { AppPath } from '@/types/AppPath';
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { MainButton } from '@/ui/input/button/components/MainButton';
import { TextInput } from '@/ui/input/components/TextInput';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import { useActivateWorkspaceMutation } from '~/generated/graphql';
const StyledContentContainer = styled.div`
width: 100%;
@ -46,9 +48,9 @@ export const CreateWorkspace = () => {
const { enqueueSnackBar } = useSnackBar();
const onboardingStatus = useOnboardingStatus();
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const [updateWorkspace] = useUpdateWorkspaceMutation();
const [activateWorkspace] = useActivateWorkspaceMutation();
const apolloMetadataClient = useApolloMetadataClient();
// Form
const {
@ -67,28 +69,25 @@ export const CreateWorkspace = () => {
const onSubmit: SubmitHandler<Form> = useCallback(
async (data) => {
try {
const result = await updateWorkspace({
const result = await activateWorkspace({
variables: {
input: {
displayName: data.name,
},
},
});
setCurrentWorkspace({
id: result.data?.updateWorkspace?.id ?? '',
displayName: data.name,
subscriptionStatus:
result.data?.updateWorkspace?.subscriptionStatus ?? 'incomplete',
allowImpersonation:
result.data?.updateWorkspace?.allowImpersonation ?? false,
refetchQueries: [GET_CURRENT_USER],
});
if (result.errors || !result.data?.updateWorkspace) {
await apolloMetadataClient?.refetchQueries({
include: [FIND_MANY_OBJECT_METADATA_ITEMS],
});
if (result.errors) {
throw result.errors ?? new Error('Unknown error');
}
setTimeout(() => {
navigate('/create/profile');
navigate(AppPath.CreateProfile);
}, 20);
} catch (error: any) {
enqueueSnackBar(error?.message, {
@ -96,7 +95,7 @@ export const CreateWorkspace = () => {
});
}
},
[enqueueSnackBar, navigate, setCurrentWorkspace, updateWorkspace],
[enqueueSnackBar, navigate, apolloMetadataClient, activateWorkspace],
);
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
@ -115,7 +114,7 @@ export const CreateWorkspace = () => {
[onSubmit],
);
if (onboardingStatus !== OnboardingStatus.OngoingWorkspaceCreation) {
if (onboardingStatus !== OnboardingStatus.OngoingWorkspaceActivation) {
return null;
}

View File

@ -6,8 +6,7 @@ import { useRecoilValue } from 'recoil';
import { useAuth } from '@/auth/hooks/useAuth';
import { useIsLogged } from '@/auth/hooks/useIsLogged';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { AppPath } from '../../modules/types/AppPath';
import { AppPath } from '@/types/AppPath';
export const VerifyEffect = () => {
const [searchParams] = useSearchParams();

View File

@ -4,7 +4,7 @@ import { within } from '@storybook/test';
import { graphql, HttpResponse } from 'msw';
import { AppPath } from '@/types/AppPath';
import { GET_CURRENT_USER_AND_VIEWS } from '@/users/graphql/queries/getCurrentUserAndViews';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import {
PageDecorator,
PageDecoratorArgs,
@ -22,16 +22,13 @@ const meta: Meta<PageDecoratorArgs> = {
parameters: {
msw: {
handlers: [
graphql.query(
getOperationName(GET_CURRENT_USER_AND_VIEWS) ?? '',
() => {
return HttpResponse.json({
data: {
currentUser: mockedOnboardingUsersData[0],
},
});
},
),
graphql.query(getOperationName(GET_CURRENT_USER) ?? '', () => {
return HttpResponse.json({
data: {
currentUser: mockedOnboardingUsersData[0],
},
});
}),
graphqlMocks.handlers,
],
},

View File

@ -1,14 +1,18 @@
import { getOperationName } from '@apollo/client/utilities';
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
import { graphql, HttpResponse } from 'msw';
import { useSetRecoilState } from 'recoil';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { AppPath } from '@/types/AppPath';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import {
PageDecorator,
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { mockedOnboardingUsersData } from '~/testing/mock-data/users';
import { CreateWorkspace } from '../CreateWorkspace';
@ -25,7 +29,18 @@ const meta: Meta<PageDecoratorArgs> = {
],
args: { routePath: AppPath.CreateWorkspace },
parameters: {
msw: graphqlMocks,
msw: {
handlers: [
graphql.query(getOperationName(GET_CURRENT_USER) ?? '', () => {
return HttpResponse.json({
data: {
currentUser: mockedOnboardingUsersData[1],
},
});
}),
graphqlMocks.handlers,
],
},
},
};

View File

@ -4,7 +4,7 @@ import { within } from '@storybook/test';
import { graphql, HttpResponse } from 'msw';
import { AppPath } from '@/types/AppPath';
import { GET_CURRENT_USER_AND_VIEWS } from '@/users/graphql/queries/getCurrentUserAndViews';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import {
PageDecorator,
PageDecoratorArgs,
@ -22,22 +22,19 @@ const meta: Meta<PageDecoratorArgs> = {
parameters: {
msw: {
handlers: [
graphql.query(
getOperationName(GET_CURRENT_USER_AND_VIEWS) ?? '',
() => {
return HttpResponse.json({
data: {
currentUser: {
...mockedOnboardingUsersData[0],
defaultWorkspace: {
...mockedOnboardingUsersData[0].defaultWorkspace,
subscriptionStatus: 'incomplete',
},
graphql.query(getOperationName(GET_CURRENT_USER) ?? '', () => {
return HttpResponse.json({
data: {
currentUser: {
...mockedOnboardingUsersData[0],
defaultWorkspace: {
...mockedOnboardingUsersData[0].defaultWorkspace,
subscriptionStatus: 'incomplete',
},
},
});
},
),
},
});
}),
graphqlMocks.handlers,
],
},

View File

@ -4,7 +4,7 @@ import { fireEvent, within } from '@storybook/test';
import { graphql, HttpResponse } from 'msw';
import { AppPath } from '@/types/AppPath';
import { GET_CURRENT_USER_AND_VIEWS } from '@/users/graphql/queries/getCurrentUserAndViews';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import {
PageDecorator,
PageDecoratorArgs,
@ -22,16 +22,13 @@ const meta: Meta<PageDecoratorArgs> = {
parameters: {
msw: {
handlers: [
graphql.query(
getOperationName(GET_CURRENT_USER_AND_VIEWS) ?? '',
() => {
return HttpResponse.json({
data: {
currentUser: mockedOnboardingUsersData[0],
},
});
},
),
graphql.query(getOperationName(GET_CURRENT_USER) ?? '', () => {
return HttpResponse.json({
data: {
currentUser: mockedOnboardingUsersData[0],
},
});
}),
graphqlMocks.handlers,
],
},

View File

@ -6,10 +6,9 @@ import { useRecoilState, useSetRecoilState } from 'recoil';
import { useIsLogged } from '@/auth/hooks/useIsLogged';
import { currentUserState } from '@/auth/states/currentUserState';
import { tokenPairState } from '@/auth/states/tokenPairState';
import { AppPath } from '@/types/AppPath';
import { useImpersonateMutation } from '~/generated/graphql';
import { AppPath } from '../../modules/types/AppPath';
export const ImpersonateEffect = () => {
const navigate = useNavigate();
const { userId } = useParams();

View File

@ -2,6 +2,7 @@ import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
import { SignInBackgroundMockPage } from '@/sign-in-background-mock/components/SignInBackgroundMockPage';
import { AppPath } from '@/types/AppPath';
import { MainButton } from '@/ui/input/button/components/MainButton';
import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder';
import { StyledEmptyTextContainer } from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled';
@ -49,7 +50,7 @@ export const NotFound = () => {
<MainButton
title="Back to content"
fullWidth
onClick={() => navigate('/')}
onClick={() => navigate(AppPath.Index)}
/>
</StyledButtonContainer>
</StyledErrorContainer>

View File

@ -1,10 +1,6 @@
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import styled from '@emotion/styled';
import { isNonEmptyString } from '@sniptt/guards';
import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus';
import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
@ -32,10 +28,6 @@ export const RecordIndexPage = () => {
objectNamePlural,
});
const onboardingStatus = useOnboardingStatus();
const navigate = useNavigate();
const { findObjectMetadataItemByNamePlural } =
useObjectMetadataItemForSettings();
@ -44,15 +36,6 @@ export const RecordIndexPage = () => {
findObjectMetadataItemByNamePlural(objectNamePlural)?.icon,
);
useEffect(() => {
if (
!isNonEmptyString(objectNamePlural) &&
onboardingStatus === OnboardingStatus.Completed
) {
navigate('/');
}
}, [objectNamePlural, navigate, onboardingStatus]);
const { createOneRecord: createOneObject } = useCreateOneRecord({
objectNameSingular,
});

View File

@ -4,7 +4,7 @@ import { graphql, HttpResponse } from 'msw';
import { CREATE_EVENT } from '@/analytics/graphql/queries/createEvent';
import { GET_CLIENT_CONFIG } from '@/client-config/graphql/queries/getClientConfig';
import { FIND_MANY_OBJECT_METADATA_ITEMS } from '@/object-metadata/graphql/queries';
import { GET_CURRENT_USER_AND_VIEWS } from '@/users/graphql/queries/getCurrentUserAndViews';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import { REACT_APP_SERVER_BASE_URL } from '~/config';
import { mockedActivities } from '~/testing/mock-data/activities';
import { mockedCompaniesData } from '~/testing/mock-data/companies';
@ -22,22 +22,10 @@ const metadataGraphql = graphql.link(`${REACT_APP_SERVER_BASE_URL}/metadata`);
export const graphqlMocks = {
handlers: [
graphql.query(getOperationName(GET_CURRENT_USER_AND_VIEWS) ?? '', () => {
graphql.query(getOperationName(GET_CURRENT_USER) ?? '', () => {
return HttpResponse.json({
data: {
currentUser: mockedUsersData[0],
views: {
edges: mockedViewsData.map((view) => ({
node: view,
cursor: null,
})),
pageInfo: {
hasNextPage: false,
hasPreviousPage: false,
startCursor: null,
endCursor: null,
},
},
},
});
}),

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ type MockedUser = Pick<
| '__typename'
| 'supportUserHash'
> & {
workspaceMember: WorkspaceMember;
workspaceMember: WorkspaceMember | null;
locale: string;
defaultWorkspace: Workspace;
};
@ -34,7 +34,7 @@ export const mockDefaultWorkspace: Workspace = {
updatedAt: '2023-04-26T10:23:42.33625+00:00',
};
const workspaceMember: WorkspaceMember = {
export const mockedWorkspaceMemberData: WorkspaceMember = {
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
colorScheme: 'Light',
avatarUrl,
@ -59,7 +59,7 @@ export const mockedUsersData: Array<MockedUser> = [
canImpersonate: false,
supportUserHash:
'a95afad9ff6f0b364e2a3fd3e246a1a852c22b6e55a3ca33745a86c201f9c10d',
workspaceMember,
workspaceMember: mockedWorkspaceMemberData,
defaultWorkspace: mockDefaultWorkspace,
locale: 'en',
},
@ -73,7 +73,7 @@ export const mockedUsersData: Array<MockedUser> = [
supportUserHash:
'54ac3986035961724cdb9a7a30c70e6463a4b68f0ecd2014c727171a82144b74',
workspaceMember: {
...workspaceMember,
...mockedWorkspaceMemberData,
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6c',
name: {
firstName: 'Felix',
@ -97,7 +97,7 @@ export const mockedOnboardingUsersData: Array<MockedUser> = [
supportUserHash:
'4fb61d34ed3a4aeda2476d4b308b5162db9e1809b2b8277e6fdc6efc4a609254',
workspaceMember: {
...workspaceMember,
...mockedWorkspaceMemberData,
id: 'd454f075-c72f-4ebe-bac7-d28e75e74a23',
name: {
firstName: '',
@ -116,7 +116,7 @@ export const mockedOnboardingUsersData: Array<MockedUser> = [
firstName: '',
lastName: '',
canImpersonate: false,
workspaceMember,
workspaceMember: null,
defaultWorkspace: {
...mockDefaultWorkspace,
displayName: '',