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

@ -1,4 +1,4 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import {
Entity,
@ -18,7 +18,12 @@ import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-mem
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
import { UserState } from 'src/engine/core-modules/user-state/dtos/user-state.dto';
import { OnboardingStep } from 'src/engine/core-modules/onboarding/enums/onboarding-step.enum';
registerEnumType(OnboardingStep, {
name: 'OnboardingStep',
description: 'Onboarding step',
});
@Entity({ name: 'user', schema: 'core' })
@ObjectType('User')
@ -114,6 +119,6 @@ export class User {
@OneToMany(() => UserWorkspace, (userWorkspace) => userWorkspace.user)
workspaces: Relation<UserWorkspace[]>;
@Field(() => UserState, { nullable: false })
state: UserState;
@Field(() => OnboardingStep, { nullable: true })
onboardingStep: OnboardingStep;
}

View File

@ -11,7 +11,7 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
import { UserStateModule } from 'src/engine/core-modules/user-state/user-state.module';
import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module';
import { userAutoResolverOpts } from './user.auto-resolver-opts';
@ -28,8 +28,8 @@ import { UserService } from './services/user.service';
}),
DataSourceModule,
FileUploadModule,
UserStateModule,
WorkspaceModule,
OnboardingModule,
],
exports: [UserService],
providers: [UserService, UserResolver, TypeORMService],

View File

@ -27,11 +27,8 @@ import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
import { User } from 'src/engine/core-modules/user/user.entity';
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { UserState } from 'src/engine/core-modules/user-state/dtos/user-state.dto';
import { UserStateService } from 'src/engine/core-modules/user-state/user-state.service';
import { DEFAULT_USER_STATE } from 'src/engine/core-modules/user-state/constants/default-user-state';
import { OnboardingStep } from 'src/engine/core-modules/onboarding/enums/onboarding-step.enum';
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
const getHMACKey = (email?: string, key?: string | null) => {
if (!email || !key) return null;
@ -47,10 +44,10 @@ export class UserResolver {
constructor(
@InjectRepository(User, 'core')
private readonly userRepository: Repository<User>,
private readonly userStateService: UserStateService,
private readonly userService: UserService,
private readonly environmentService: EnvironmentService,
private readonly fileUploadService: FileUploadService,
private readonly onboardingService: OnboardingService,
) {}
@Query(() => User)
@ -119,15 +116,15 @@ export class UserResolver {
return this.userService.deleteUser(userId);
}
@ResolveField(() => UserState)
async state(
@Parent() user: User,
@AuthWorkspace() workspace: Workspace,
): Promise<UserState> {
if (!user || !workspace) {
return DEFAULT_USER_STATE;
@ResolveField(() => OnboardingStep)
async onboardingStep(@Parent() user: User): Promise<OnboardingStep | null> {
if (!user) {
return null;
}
return this.userStateService.getUserState(user, workspace);
return this.onboardingService.getOnboardingStep(
user,
user.defaultWorkspace,
);
}
}