3959 create a activationstatus in coreworkspace and use it in front to redirect properly (#3989)
* Add computed field to workspace entity * Add activationStatus to front requests * Update Selector * Use activation status * Stop using selector for mock values * Remove isCurrentWorkspaceActiveSelector * Use activation status * Fix typo * Use activation status * Create hook for sign in up navigate * Update hook to handle profile creation * Use varaible * Use more readable boolean function
This commit is contained in:
@ -0,0 +1,44 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState.ts';
|
||||
import { billingState } from '@/client-config/states/billingState.ts';
|
||||
import { AppPath } from '@/types/AppPath.ts';
|
||||
import { WorkspaceMember } from '~/generated/graphql.tsx';
|
||||
|
||||
export const useNavigateAfterSignInUp = () => {
|
||||
const navigate = useNavigate();
|
||||
const billing = useRecoilValue(billingState);
|
||||
const navigateAfterSignInUp = useCallback(
|
||||
(
|
||||
currentWorkspace: CurrentWorkspace,
|
||||
currentWorkspaceMember: WorkspaceMember | null,
|
||||
) => {
|
||||
if (
|
||||
billing?.isBillingEnabled &&
|
||||
currentWorkspace.subscriptionStatus !== 'active'
|
||||
) {
|
||||
navigate(AppPath.PlanRequired);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentWorkspace.activationStatus !== 'active') {
|
||||
navigate(AppPath.CreateWorkspace);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!currentWorkspaceMember?.name.firstName ||
|
||||
!currentWorkspaceMember?.name.lastName
|
||||
) {
|
||||
navigate(AppPath.CreateProfile);
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(AppPath.Index);
|
||||
},
|
||||
[billing, navigate],
|
||||
);
|
||||
return { navigateAfterSignInUp };
|
||||
};
|
||||
@ -1,10 +1,9 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { SubmitHandler, UseFormReturn } from 'react-hook-form';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts';
|
||||
import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm.ts';
|
||||
import { billingState } from '@/client-config/states/billingState';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
@ -26,14 +25,18 @@ export enum SignInUpStep {
|
||||
}
|
||||
|
||||
export const useSignInUp = (form: UseFormReturn<Form>) => {
|
||||
const navigate = useNavigate();
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
|
||||
const isMatchingLocation = useIsMatchingLocation();
|
||||
const billing = useRecoilValue(billingState);
|
||||
|
||||
const workspaceInviteHash = useParams().workspaceInviteHash;
|
||||
|
||||
const { navigateAfterSignInUp } = useNavigateAfterSignInUp();
|
||||
|
||||
const [signInUpStep, setSignInUpStep] = useState<SignInUpStep>(
|
||||
SignInUpStep.Init,
|
||||
);
|
||||
|
||||
const [signInUpMode, setSignInUpMode] = useState<SignInUpMode>(() => {
|
||||
if (isMatchingLocation(AppPath.Invite)) {
|
||||
return SignInUpMode.Invite;
|
||||
@ -43,6 +46,7 @@ export const useSignInUp = (form: UseFormReturn<Form>) => {
|
||||
? SignInUpMode.SignIn
|
||||
: SignInUpMode.SignUp;
|
||||
});
|
||||
|
||||
const {
|
||||
signInWithCredentials,
|
||||
signUpWithCredentials,
|
||||
@ -84,7 +88,10 @@ export const useSignInUp = (form: UseFormReturn<Form>) => {
|
||||
throw new Error('Email and password are required');
|
||||
}
|
||||
|
||||
const { workspace: currentWorkspace } =
|
||||
const {
|
||||
workspace: currentWorkspace,
|
||||
workspaceMember: currentWorkspaceMember,
|
||||
} =
|
||||
signInUpMode === SignInUpMode.SignIn
|
||||
? await signInWithCredentials(
|
||||
data.email.toLowerCase().trim(),
|
||||
@ -96,19 +103,7 @@ export const useSignInUp = (form: UseFormReturn<Form>) => {
|
||||
workspaceInviteHash,
|
||||
);
|
||||
|
||||
if (
|
||||
billing?.isBillingEnabled &&
|
||||
currentWorkspace.subscriptionStatus !== 'active'
|
||||
) {
|
||||
navigate(AppPath.PlanRequired);
|
||||
return;
|
||||
}
|
||||
if (currentWorkspace.displayName) {
|
||||
navigate(AppPath.Index);
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(AppPath.CreateWorkspace);
|
||||
navigateAfterSignInUp(currentWorkspace, currentWorkspaceMember);
|
||||
} catch (err: any) {
|
||||
enqueueSnackBar(err?.message, {
|
||||
variant: 'error',
|
||||
@ -120,8 +115,7 @@ export const useSignInUp = (form: UseFormReturn<Form>) => {
|
||||
signInWithCredentials,
|
||||
signUpWithCredentials,
|
||||
workspaceInviteHash,
|
||||
billing?.isBillingEnabled,
|
||||
navigate,
|
||||
navigateAfterSignInUp,
|
||||
enqueueSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
@ -11,6 +11,7 @@ export type CurrentWorkspace = Pick<
|
||||
| 'allowImpersonation'
|
||||
| 'featureFlags'
|
||||
| 'subscriptionStatus'
|
||||
| 'activationStatus'
|
||||
>;
|
||||
|
||||
export const currentWorkspaceState = atom<CurrentWorkspace | null>({
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
import { selector } from 'recoil';
|
||||
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
|
||||
export const isCurrentWorkspaceActiveSelector = selector({
|
||||
key: 'isCurrentWorkspaceActiveSelector',
|
||||
get: ({ get }) => {
|
||||
const currentWorkspaceMember = get(currentWorkspaceMemberState);
|
||||
return !!currentWorkspaceMember;
|
||||
},
|
||||
});
|
||||
@ -39,13 +39,13 @@ export const getOnboardingStatus = ({
|
||||
return OnboardingStatus.Canceled;
|
||||
}
|
||||
|
||||
if (!currentWorkspaceMember) {
|
||||
if (currentWorkspace?.activationStatus !== 'active') {
|
||||
return OnboardingStatus.OngoingWorkspaceActivation;
|
||||
}
|
||||
|
||||
if (
|
||||
!currentWorkspaceMember.name.firstName ||
|
||||
!currentWorkspaceMember.name.lastName
|
||||
!currentWorkspaceMember?.name.firstName ||
|
||||
!currentWorkspaceMember?.name.lastName
|
||||
) {
|
||||
return OnboardingStatus.OngoingProfileCreation;
|
||||
}
|
||||
|
||||
@ -31,14 +31,14 @@ const meta: Meta<typeof CommandMenu> = {
|
||||
const setCurrentWorkspaceMember = useSetRecoilState(
|
||||
currentWorkspaceMemberState,
|
||||
);
|
||||
const { addToCommandMenu, setToIntitialCommandMenu, openCommandMenu } =
|
||||
const { addToCommandMenu, setToInitialCommandMenu, openCommandMenu } =
|
||||
useCommandMenu();
|
||||
|
||||
setCurrentWorkspace(mockDefaultWorkspace);
|
||||
setCurrentWorkspaceMember(mockedWorkspaceMemberData);
|
||||
|
||||
useEffect(() => {
|
||||
setToIntitialCommandMenu();
|
||||
setToInitialCommandMenu();
|
||||
addToCommandMenu([
|
||||
{
|
||||
id: 'create-task',
|
||||
@ -58,7 +58,7 @@ const meta: Meta<typeof CommandMenu> = {
|
||||
},
|
||||
]);
|
||||
openCommandMenu();
|
||||
}, [addToCommandMenu, setToIntitialCommandMenu, openCommandMenu]);
|
||||
}, [addToCommandMenu, setToInitialCommandMenu, openCommandMenu]);
|
||||
|
||||
return <Story />;
|
||||
},
|
||||
|
||||
@ -107,11 +107,11 @@ describe('useCommandMenu', () => {
|
||||
expect(onClickMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should setToIntitialCommandMenu command menu', () => {
|
||||
it('should setToInitialCommandMenu command menu', () => {
|
||||
const { result } = renderHooks();
|
||||
|
||||
act(() => {
|
||||
result.current.commandMenu.setToIntitialCommandMenu();
|
||||
result.current.commandMenu.setToInitialCommandMenu();
|
||||
});
|
||||
|
||||
expect(result.current.commandMenuCommands.length).toBe(5);
|
||||
|
||||
@ -61,7 +61,7 @@ export const useCommandMenu = () => {
|
||||
[setCommands],
|
||||
);
|
||||
|
||||
const setToIntitialCommandMenu = () => {
|
||||
const setToInitialCommandMenu = () => {
|
||||
setCommands(commandMenuCommands);
|
||||
};
|
||||
|
||||
@ -87,6 +87,6 @@ export const useCommandMenu = () => {
|
||||
toggleCommandMenu,
|
||||
addToCommandMenu,
|
||||
onItemClick,
|
||||
setToIntitialCommandMenu,
|
||||
setToInitialCommandMenu,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState.ts';
|
||||
import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
|
||||
@ -9,14 +10,17 @@ export const ObjectMetadataItemsProvider = ({
|
||||
children,
|
||||
}: React.PropsWithChildren) => {
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
const isCurrentWorkspaceActive = useRecoilValue(
|
||||
isCurrentWorkspaceActiveSelector,
|
||||
);
|
||||
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
const shouldDisplayChildren = () => {
|
||||
if (objectMetadataItems.length) {
|
||||
return true;
|
||||
}
|
||||
return !currentWorkspaceMember;
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<ObjectMetadataItemsLoadEffect />
|
||||
{(!isCurrentWorkspaceActive || !!objectMetadataItems.length) && (
|
||||
{shouldDisplayChildren() && (
|
||||
<RelationPickerScope relationPickerScopeId="relation-picker">
|
||||
{children}
|
||||
</RelationPickerScope>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||
import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError';
|
||||
import { useGetObjectOrderByField } from '@/object-metadata/hooks/useGetObjectOrderByField';
|
||||
import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapToObjectRecordIdentifier';
|
||||
@ -40,9 +40,8 @@ export const useObjectMetadataItem = (
|
||||
{ objectNameSingular }: ObjectMetadataItemIdentifier,
|
||||
depth?: number,
|
||||
) => {
|
||||
const isCurrentWorkspaceActive = useRecoilValue(
|
||||
isCurrentWorkspaceActiveSelector,
|
||||
);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
|
||||
const mockObjectMetadataItems = getObjectMetadataItemsMock();
|
||||
|
||||
let objectMetadataItem = useRecoilValue(
|
||||
@ -54,7 +53,7 @@ export const useObjectMetadataItem = (
|
||||
|
||||
let objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
if (!isCurrentWorkspaceActive) {
|
||||
if (currentWorkspace?.activationStatus !== 'active') {
|
||||
objectMetadataItem =
|
||||
mockObjectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||
import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError';
|
||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
@ -12,9 +12,8 @@ import { ObjectMetadataItemIdentifier } from '../types/ObjectMetadataItemIdentif
|
||||
export const useObjectMetadataItemOnly = ({
|
||||
objectNameSingular,
|
||||
}: ObjectMetadataItemIdentifier) => {
|
||||
const isCurrentWorkspaceActive = useRecoilValue(
|
||||
isCurrentWorkspaceActiveSelector,
|
||||
);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
|
||||
const mockObjectMetadataItems = getObjectMetadataItemsMock();
|
||||
|
||||
let objectMetadataItem = useRecoilValue(
|
||||
@ -26,7 +25,7 @@ export const useObjectMetadataItemOnly = ({
|
||||
|
||||
let objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
if (!isCurrentWorkspaceActive) {
|
||||
if (currentWorkspace?.activationStatus !== 'active') {
|
||||
objectMetadataItem =
|
||||
mockObjectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -10,9 +10,7 @@ export const useObjectNamePluralFromSingular = ({
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
}) => {
|
||||
const isCurrentWorkspaceActive = useRecoilValue(
|
||||
isCurrentWorkspaceActiveSelector,
|
||||
);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const mockObjectMetadataItems = getObjectMetadataItemsMock();
|
||||
|
||||
let objectMetadataItem = useRecoilValue(
|
||||
@ -22,7 +20,7 @@ export const useObjectNamePluralFromSingular = ({
|
||||
}),
|
||||
);
|
||||
|
||||
if (!isCurrentWorkspaceActive) {
|
||||
if (currentWorkspace?.activationStatus !== 'active') {
|
||||
objectMetadataItem =
|
||||
mockObjectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -10,9 +10,8 @@ export const useObjectNameSingularFromPlural = ({
|
||||
}: {
|
||||
objectNamePlural: string;
|
||||
}) => {
|
||||
const isCurrentWorkspaceActive = useRecoilValue(
|
||||
isCurrentWorkspaceActiveSelector,
|
||||
);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
|
||||
const mockObjectMetadataItems = getObjectMetadataItemsMock();
|
||||
|
||||
let objectMetadataItem = useRecoilValue(
|
||||
@ -22,7 +21,7 @@ export const useObjectNameSingularFromPlural = ({
|
||||
}),
|
||||
);
|
||||
|
||||
if (!isCurrentWorkspaceActive) {
|
||||
if (currentWorkspace?.activationStatus !== 'active') {
|
||||
objectMetadataItem =
|
||||
mockObjectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { isCurrentWorkspaceActiveSelector } from '@/auth/states/selectors/isCurrentWorkspaceActiveSelector';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts';
|
||||
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';
|
||||
@ -14,9 +14,7 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
|
||||
const { setRecordTableData, setIsRecordTableInitialLoading } =
|
||||
useRecordTable();
|
||||
|
||||
const isCurrentWorkspaceActive = useRecoilValue(
|
||||
isCurrentWorkspaceActiveSelector,
|
||||
);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
@ -58,7 +56,10 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
|
||||
});
|
||||
|
||||
return {
|
||||
records: isCurrentWorkspaceActive ? records : signInBackgroundMockCompanies,
|
||||
records:
|
||||
currentWorkspace?.activationStatus === 'active'
|
||||
? records
|
||||
: signInBackgroundMockCompanies,
|
||||
totalCount: totalCount || 0,
|
||||
loading,
|
||||
fetchMoreRecords,
|
||||
|
||||
@ -26,6 +26,7 @@ export const USER_QUERY_FRAGMENT = gql`
|
||||
inviteHash
|
||||
allowImpersonation
|
||||
subscriptionStatus
|
||||
activationStatus
|
||||
featureFlags {
|
||||
id
|
||||
key
|
||||
|
||||
@ -28,6 +28,7 @@ export const GET_CURRENT_USER = gql`
|
||||
inviteHash
|
||||
allowImpersonation
|
||||
subscriptionStatus
|
||||
activationStatus
|
||||
featureFlags {
|
||||
id
|
||||
key
|
||||
|
||||
Reference in New Issue
Block a user