5623 add an inviteteam onboarding step (#5769)

## Changes
- add a new invite Team onboarding step
- update currentUser.state to currentUser.onboardingStep

## Edge cases
We will never display invite team onboarding step 
- if number of workspaceMember > 1
- if a workspaceMember as been deleted

## Important changes
Update typeorm package version to 0.3.20 because we needed a fix on
`indexPredicates` pushed in 0.3.20 version
(https://github.com/typeorm/typeorm/issues/10191)

## Result
<img width="844" alt="image"
src="https://github.com/twentyhq/twenty/assets/29927851/0dab54cf-7c66-4c64-b0c9-b0973889a148">



https://github.com/twentyhq/twenty/assets/29927851/13268d0a-cfa7-42a4-84c6-9e1fbbe48912
This commit is contained in:
martmull
2024-06-12 21:13:18 +02:00
committed by GitHub
parent 2fdd2f4949
commit 3986824017
60 changed files with 1009 additions and 372 deletions

View File

@ -0,0 +1,34 @@
import React from 'react';
import styled from '@emotion/styled';
const StyledContainer = styled.div`
display: flex;
align-items: center;
width: 100%;
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
color: ${({ theme }) => theme.font.color.extraLight};
&:before,
&:after {
content: '';
height: 1px;
flex-grow: 1;
background: ${({ theme }) => theme.background.transparent.light};
}
&:before {
margin: 0 ${({ theme }) => theme.spacing(4)} 0 0;
}
&:after {
margin: 0 0 0 ${({ theme }) => theme.spacing(4)};
}
`;
export const SeparatorLineText = ({
children,
}: {
children: React.ReactNode;
}) => {
return <StyledContainer>{children}</StyledContainer>;
};

View File

@ -0,0 +1,16 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
import { SeparatorLineText } from '../SeparatorLineText';
const meta: Meta<typeof SeparatorLineText> = {
title: 'UI/Display/Text/SeparatorLineText',
component: SeparatorLineText,
args: { children: 'Or' },
decorators: [ComponentDecorator],
};
export default meta;
type Story = StoryObj<typeof SeparatorLineText>;
export const Default: Story = {};

View File

@ -117,6 +117,7 @@ export type TextInputV2ComponentProps = Omit<
onChange?: (text: string) => void;
fullWidth?: boolean;
error?: string;
noErrorHelper?: boolean;
RightIcon?: IconComponent;
LeftIcon?: IconComponent;
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
@ -134,6 +135,7 @@ const TextInputV2Component = (
onKeyDown,
fullWidth,
error,
noErrorHelper = false,
required,
type,
autoFocus,
@ -207,7 +209,9 @@ const TextInputV2Component = (
)}
</StyledTrailingIconContainer>
</StyledInputContainer>
{error && <StyledErrorHelper>{error}</StyledErrorHelper>}
{error && !noErrorHelper && (
<StyledErrorHelper>{error}</StyledErrorHelper>
)}
</StyledContainer>
);
};

View File

@ -47,6 +47,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: false },
{ loc: AppPath.Verify, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.Verify, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -58,6 +59,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.SignInUp, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.SignInUp, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -69,6 +71,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.Invite, status: OnboardingStatus.Completed, res: true },
{ loc: AppPath.Invite, status: OnboardingStatus.CompletedWithoutSubscription, res: true },
@ -80,6 +83,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.ResetPassword, status: OnboardingStatus.Completed, res: true },
{ loc: AppPath.ResetPassword, status: OnboardingStatus.CompletedWithoutSubscription, res: true },
@ -91,6 +95,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.CreateWorkspace, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -102,6 +107,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.CreateProfile, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.CreateProfile, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -113,9 +119,22 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.SyncEmails, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.SyncEmails, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.Incomplete, res: true },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.Canceled, res: false },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.Unpaid, res: false },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.PastDue, res: false },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.OngoingUserCreation, res: true },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.OngoingWorkspaceActivation, res: true },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.OngoingProfileCreation, res: true },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.OngoingSyncEmail, res: true },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.OngoingInviteTeam, res: true },
{ loc: AppPath.InviteTeam, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.InviteTeam, 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 },
@ -124,6 +143,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.PlanRequired, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.PlanRequired, status: OnboardingStatus.CompletedWithoutSubscription, res: true },
@ -135,6 +155,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.PlanRequiredSuccess, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -146,6 +167,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.Index, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.Index, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -157,6 +179,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.TasksPage, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.TasksPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -168,6 +191,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.OpportunitiesPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -179,6 +203,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.RecordIndexPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -190,6 +215,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.RecordShowPage, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -201,6 +227,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.SettingsCatchAll, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -212,6 +239,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.DevelopersCatchAll, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -223,6 +251,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.Impersonate, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.Impersonate, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -234,6 +263,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.Authorize, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.Authorize, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -245,6 +275,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.NotFoundWildcard, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
@ -256,6 +287,7 @@ const testCases = [
{ 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.OngoingInviteTeam, res: true },
{ loc: AppPath.NotFound, status: OnboardingStatus.Completed, res: false },
{ loc: AppPath.NotFound, status: OnboardingStatus.CompletedWithoutSubscription, res: false },
];

View File

@ -28,7 +28,8 @@ export const useShowAuthModal = () => {
OnboardingStatus.OngoingUserCreation === onboardingStatus ||
OnboardingStatus.OngoingProfileCreation === onboardingStatus ||
OnboardingStatus.OngoingWorkspaceActivation === onboardingStatus ||
OnboardingStatus.OngoingSyncEmail === onboardingStatus
OnboardingStatus.OngoingSyncEmail === onboardingStatus ||
OnboardingStatus.OngoingInviteTeam === onboardingStatus
) {
return true;
}

View File

@ -0,0 +1,33 @@
import { useTheme } from '@emotion/react';
import { motion } from 'framer-motion';
type AnimatedTranslationProps = {
children: React.ReactNode;
};
export const AnimatedTranslation = ({ children }: AnimatedTranslationProps) => {
const theme = useTheme();
return (
<motion.div
initial="hidden"
animate="visible"
variants={{
hidden: {
opacity: 0,
y: -20,
},
visible: {
opacity: 1,
y: 0,
transition: {
duration: theme.animation.duration.normal, // Replace this with your theme's duration
ease: 'easeInOut',
},
},
}}
>
{children}
</motion.div>
);
};