Create workspace after signup

This commit is contained in:
martmull
2024-01-31 16:13:23 +01:00
parent 0092211921
commit 369a459603
7 changed files with 136 additions and 18 deletions
@@ -86,6 +86,14 @@ export type CreateRefreshTokenInput = {
expiresAt: Scalars['DateTime'];
};
export type CreateWorkspaceInput = {
allowImpersonation?: InputMaybe<Scalars['Boolean']>;
displayName?: InputMaybe<Scalars['String']>;
domainName?: InputMaybe<Scalars['String']>;
inviteHash?: InputMaybe<Scalars['String']>;
logo?: InputMaybe<Scalars['String']>;
};
export type CursorPaging = {
/** Paginate after opaque cursor */
after?: InputMaybe<Scalars['ConnectionCursor']>;
@@ -265,6 +273,11 @@ export type MutationCreateOneRefreshTokenArgs = {
};
export type MutationCreateWorkspaceArgs = {
data: CreateWorkspaceInput;
};
export type MutationDeleteOneObjectArgs = {
input: DeleteOneObjectInput;
};
@@ -859,6 +872,13 @@ export type UploadProfilePictureMutationVariables = Exact<{
export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProfilePicture: string };
export type CreateWorkspaceMutationVariables = Exact<{
input: CreateWorkspaceInput;
}>;
export type CreateWorkspaceMutation = { __typename?: 'Mutation', createWorkspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null, allowImpersonation: boolean, subscriptionStatus: string } };
export type DeleteCurrentWorkspaceMutationVariables = Exact<{ [key: string]: never; }>;
@@ -1668,6 +1688,44 @@ 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 CreateWorkspaceDocument = gql`
mutation CreateWorkspace($input: CreateWorkspaceInput!) {
createWorkspace(data: $input) {
id
domainName
displayName
logo
allowImpersonation
subscriptionStatus
}
}
`;
export type CreateWorkspaceMutationFn = Apollo.MutationFunction<CreateWorkspaceMutation, CreateWorkspaceMutationVariables>;
/**
* __useCreateWorkspaceMutation__
*
* To run a mutation, you first call `useCreateWorkspaceMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useCreateWorkspaceMutation` 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 [createWorkspaceMutation, { data, loading, error }] = useCreateWorkspaceMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useCreateWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<CreateWorkspaceMutation, CreateWorkspaceMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<CreateWorkspaceMutation, CreateWorkspaceMutationVariables>(CreateWorkspaceDocument, options);
}
export type CreateWorkspaceMutationHookResult = ReturnType<typeof useCreateWorkspaceMutation>;
export type CreateWorkspaceMutationResult = Apollo.MutationResult<CreateWorkspaceMutation>;
export type CreateWorkspaceMutationOptions = Apollo.BaseMutationOptions<CreateWorkspaceMutation, CreateWorkspaceMutationVariables>;
export const DeleteCurrentWorkspaceDocument = gql`
mutation DeleteCurrentWorkspace {
deleteCurrentWorkspace {
@@ -0,0 +1,14 @@
import { gql } from '@apollo/client';
export const CREATE_WORKSPACE = gql`
mutation CreateWorkspace($input: CreateWorkspaceInput!) {
createWorkspace(data: $input) {
id
domainName
displayName
logo
allowImpersonation
subscriptionStatus
}
}
`;
@@ -12,13 +12,14 @@ import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus';
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 { useCreateWorkspaceMutation } from '~/generated/graphql';
const StyledContentContainer = styled.div`
width: 100%;
@@ -48,7 +49,7 @@ export const CreateWorkspace = () => {
const onboardingStatus = useOnboardingStatus();
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const [updateWorkspace] = useUpdateWorkspaceMutation();
const [createWorkspace] = useCreateWorkspaceMutation();
// Form
const {
@@ -67,7 +68,7 @@ export const CreateWorkspace = () => {
const onSubmit: SubmitHandler<Form> = useCallback(
async (data) => {
try {
const result = await updateWorkspace({
const result = await createWorkspace({
variables: {
input: {
displayName: data.name,
@@ -75,20 +76,20 @@ export const CreateWorkspace = () => {
},
});
setCurrentWorkspace({
id: result.data?.updateWorkspace?.id ?? '',
id: result.data?.createWorkspace?.id ?? '',
displayName: data.name,
subscriptionStatus:
result.data?.updateWorkspace?.subscriptionStatus ?? 'incomplete',
result.data?.createWorkspace?.subscriptionStatus ?? 'incomplete',
allowImpersonation:
result.data?.updateWorkspace?.allowImpersonation ?? false,
result.data?.createWorkspace?.allowImpersonation ?? false,
});
if (result.errors || !result.data?.updateWorkspace) {
if (result.errors || !result.data?.createWorkspace) {
throw result.errors ?? new Error('Unknown error');
}
setTimeout(() => {
navigate('/create/profile');
navigate(AppPath.CreateProfile);
}, 20);
} catch (error: any) {
enqueueSnackBar(error?.message, {
@@ -96,7 +97,7 @@ export const CreateWorkspace = () => {
});
}
},
[enqueueSnackBar, navigate, setCurrentWorkspace, updateWorkspace],
[enqueueSnackBar, navigate, setCurrentWorkspace, createWorkspace],
);
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
@@ -91,8 +91,13 @@ export class UserService extends TypeOrmQueryService<User> {
async updateUser(
userId: string,
data: QueryDeepPartialEntity<User>,
): Promise<void> {
): Promise<User> {
await this.userRepository.update(userId, data);
return await this.userRepository.findOneOrFail({
where: { id: userId },
relations: ['defaultWorkspace'],
});
}
async deleteUser(userId: string): Promise<User> {
@@ -0,0 +1,31 @@
import { Field, InputType } from '@nestjs/graphql';
import { IsBoolean, IsOptional, IsString } from 'class-validator';
@InputType()
export class CreateWorkspaceInput {
@Field({ nullable: true })
@IsString()
@IsOptional()
domainName?: string;
@Field({ nullable: true })
@IsString()
@IsOptional()
displayName?: string;
@Field({ nullable: true })
@IsString()
@IsOptional()
logo?: string;
@Field({ nullable: true })
@IsString()
@IsOptional()
inviteHash?: string;
@Field({ nullable: true })
@IsBoolean()
@IsOptional()
allowImpersonation?: boolean;
}
@@ -10,6 +10,7 @@ import { WorkspaceManagerService } from 'src/workspace/workspace-manager/workspa
import { Workspace } from 'src/core/workspace/workspace.entity';
import { User } from 'src/core/user/user.entity';
import { UserService } from 'src/core/user/services/user.service';
import { CreateWorkspaceInput } from 'src/core/workspace/dtos/create-workspace-input';
export class WorkspaceService extends TypeOrmQueryService<Workspace> {
constructor(
@@ -21,18 +22,24 @@ export class WorkspaceService extends TypeOrmQueryService<Workspace> {
super(workspaceRepository);
}
async createWorkspace(user: User) {
async createWorkspace(user: User, data: CreateWorkspaceInput) {
const workspaceToCreate = this.workspaceRepository.create({
displayName: '',
domainName: '',
inviteHash: v4(),
subscriptionStatus: 'active',
...data,
});
const workspace = await this.workspaceRepository.save(workspaceToCreate);
await this.userService.updateUser(user.id, { defaultWorkspace: workspace });
await this.workspaceManagerService.init(user.defaultWorkspace.id);
await this.userService.createWorkspaceMember(user);
const updatedUser = await this.userService.updateUser(user.id, {
defaultWorkspace: workspace,
});
await this.workspaceManagerService.init(workspace.id);
await this.userService.createWorkspaceMember(updatedUser);
return workspace;
}
async deleteWorkspace(id: string) {
@@ -14,6 +14,7 @@ import { UpdateWorkspaceInput } from 'src/core/workspace/dtos/update-workspace-i
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { AuthUser } from 'src/decorators/auth-user.decorator';
import { User } from 'src/core/user/user.entity';
import { CreateWorkspaceInput } from 'src/core/workspace/dtos/create-workspace-input';
import { Workspace } from './workspace.entity';
@@ -39,10 +40,11 @@ export class WorkspaceResolver {
@Mutation(() => Workspace)
@UseGuards(JwtAuthGuard)
async createWorkspace(@AuthUser() user: User): Promise<Workspace> {
await this.workspaceService.createWorkspace(user);
return user.defaultWorkspace;
async createWorkspace(
@Args('data') data: CreateWorkspaceInput,
@AuthUser() user: User,
): Promise<Workspace> {
return await this.workspaceService.createWorkspace(user, data);
}
@Mutation(() => Workspace)