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

@ -4,6 +4,7 @@ import {
Column,
CreateDateColumn,
Entity,
Index,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
@ -20,6 +21,14 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@Entity({ name: 'keyValuePair', schema: 'core' })
@ObjectType('KeyValuePair')
@Unique('IndexOnKeyUserIdWorkspaceIdUnique', ['key', 'userId', 'workspaceId'])
@Index('IndexOnKeyWorkspaceIdAndNullUserIdUnique', ['key', 'workspaceId'], {
unique: true,
where: '"userId" is NULL',
})
@Index('IndexOnKeyUserIdAndNullWorkspaceIdUnique', ['key', 'userId'], {
unique: true,
where: '"workspaceId" is NULL',
})
export class KeyValuePair {
@IDField(() => UUIDScalarType)
@PrimaryGeneratedColumn('uuid')

View File

@ -1,55 +1,70 @@
import { InjectRepository } from '@nestjs/typeorm';
import { BadRequestException } from '@nestjs/common';
import { Repository } from 'typeorm';
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
import { UserStates } from 'src/engine/core-modules/user-state/enums/user-states.enum';
import { UserStateEmailSyncValues } from 'src/engine/core-modules/user-state/enums/user-state-email-sync-values.enum';
export enum KeyValueTypes {
USER_STATE = 'USER_STATE',
}
type KeyValuePairs = {
[KeyValueTypes.USER_STATE]: {
[UserStates.SYNC_EMAIL_ONBOARDING_STEP]: UserStateEmailSyncValues;
};
};
export class KeyValuePairService<TYPE extends keyof KeyValuePairs> {
export class KeyValuePairService<TYPE> {
constructor(
@InjectRepository(KeyValuePair, 'core')
private readonly keyValuePairRepository: Repository<KeyValuePair>,
) {}
async get<K extends keyof KeyValuePairs[TYPE]>(
userId: string,
workspaceId: string,
key: K,
) {
return await this.keyValuePairRepository.findOne({
where: {
userId,
workspaceId,
key: key as string,
},
});
async get<K extends keyof TYPE>({
userId,
workspaceId,
key,
}: {
userId?: string;
workspaceId?: string;
key: K;
}): Promise<TYPE[K] | undefined> {
return (
await this.keyValuePairRepository.findOne({
where: {
userId,
workspaceId,
key: key as string,
},
})
)?.value as TYPE[K] | undefined;
}
async set<K extends keyof KeyValuePairs[TYPE]>(
userId: string,
workspaceId: string,
key: K,
value: KeyValuePairs[TYPE][K],
) {
await this.keyValuePairRepository.upsert(
{
userId,
workspaceId,
key: key as string,
value: value as string,
},
{ conflictPaths: ['userId', 'workspaceId', 'key'] },
async set<K extends keyof TYPE>({
userId,
workspaceId,
key,
value,
}: {
userId?: string;
workspaceId?: string;
key: K;
value: TYPE[K];
}) {
if (!userId && !workspaceId) {
throw new BadRequestException('userId and workspaceId are undefined');
}
const upsertData = {
userId,
workspaceId,
key: key as string,
value: value as string,
};
const conflictPaths = Object.keys(upsertData).filter(
(key) => key !== 'value' && upsertData[key] !== undefined,
);
const indexPredicate = !userId
? '"userId" is NULL'
: !workspaceId
? '"workspaceId" is NULL'
: undefined;
await this.keyValuePairRepository.upsert(upsertData, {
conflictPaths,
indexPredicate,
});
}
}