diff --git a/.github/workflows/ci-front.yaml b/.github/workflows/ci-front.yaml index 480036076..aa933a0a4 100644 --- a/.github/workflows/ci-front.yaml +++ b/.github/workflows/ci-front.yaml @@ -36,12 +36,12 @@ jobs: - name: Front / Run linter run: cd front && yarn lint - name: Front / Build Storybook - run: cd front && yarn build-storybook --quiet + run: cd front && yarn storybook:build --quiet - name: Front / Run storybook tests run: | cd front && npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \ "npx http-server storybook-static --silent --port 6006" \ - "yarn coverage-storybook" + "yarn storybook:coverage" - name: Front / Run jest tests run: | cd front && yarn test diff --git a/front/package.json b/front/package.json index c49c90d42..3c27b8d54 100644 --- a/front/package.json +++ b/front/package.json @@ -25,6 +25,7 @@ "js-cookie": "^3.0.5", "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.26", + "lodash.debounce": "^4.0.8", "luxon": "^3.3.0", "react": "^18.2.0", "react-datepicker": "^4.11.0", @@ -46,10 +47,12 @@ "test": "craco test", "coverage": "craco test --coverage .", "lint": "eslint src --max-warnings=0", - "storybook": "storybook dev -p 6006 -s ../public", - "test-storybook": "test-storybook", - "build-storybook": "storybook build -s public", - "coverage-storybook": "test-storybook --coverage && npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook --check-coverage", + "storybook:dev": "storybook dev -p 6006 -s ../public", + "storybook:test": "test-storybook", + "storybook:build": "storybook build -s public", + "storybook:coverage": "test-storybook --coverage && npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook --check-coverage", + "build-storybook": "yarn storybook:build", + "coverage-storybook": "yarn storybook:coverage", "graphql:generate": "dotenv cross-var graphql-codegen --config codegen.js", "chromatic": "dotenv cross-var npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN" }, @@ -115,6 +118,7 @@ "@testing-library/user-event": "^13.5.0", "@types/jest": "^27.5.2", "@types/js-cookie": "^3.0.3", + "@types/lodash.debounce": "^4.0.7", "@types/luxon": "^3.3.0", "@types/react-datepicker": "^4.11.2", "@types/scroll-into-view": "^1.16.0", diff --git a/front/src/App.tsx b/front/src/App.tsx index 3d8dd82dd..b6c052c8e 100644 --- a/front/src/App.tsx +++ b/front/src/App.tsx @@ -2,8 +2,8 @@ import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; import { AnimatePresence, LayoutGroup } from 'framer-motion'; import { useTrackPageView } from '@/analytics/hooks/useTrackPageView'; -import { RequireAuth } from '@/auth/components/RequireAuth'; -import { RequireNotAuth } from '@/auth/components/RequireNotAuth'; +import { RequireOnboarded } from '@/auth/components/RequireOnboarded'; +import { RequireOnboarding } from '@/auth/components/RequireOnboarding'; import { AuthModal } from '@/auth/components/ui/Modal'; import { useGoToHotkeys } from '@/hotkeys/hooks/useGoToHotkeys'; import { AuthLayout } from '@/ui/layout/AuthLayout'; @@ -52,10 +52,20 @@ export function App() { return ( + + + + + + } + /> + } /> } /> @@ -70,17 +80,7 @@ export function App() { } /> - - } - /> - - - - - + } /> diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 7ed07e6fd..3e9ef86c1 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -15,6 +15,7 @@ export type Scalars = { Float: number; DateTime: string; JSON: any; + Upload: any; }; export type AffectedRows = { @@ -54,6 +55,12 @@ export type BoolFilter = { not?: InputMaybe; }; +export type ClientConfig = { + __typename?: 'ClientConfig'; + display_google_login: Scalars['Boolean']; + prefill_login_with_seed: Scalars['Boolean']; +}; + export type Comment = { __typename?: 'Comment'; author: User; @@ -75,6 +82,19 @@ export type CommentCreateInput = { updatedAt?: InputMaybe; }; +export type CommentCreateManyAuthorInput = { + body: Scalars['String']; + commentThreadId: Scalars['String']; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentCreateManyAuthorInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + export type CommentCreateManyCommentThreadInput = { authorId: Scalars['String']; body: Scalars['String']; @@ -88,15 +108,54 @@ export type CommentCreateManyCommentThreadInputEnvelope = { skipDuplicates?: InputMaybe; }; +export type CommentCreateManyWorkspaceInput = { + authorId: Scalars['String']; + body: Scalars['String']; + commentThreadId: Scalars['String']; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type CommentCreateNestedManyWithoutAuthorInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; +}; + export type CommentCreateNestedManyWithoutCommentThreadInput = { createMany?: InputMaybe; }; +export type CommentCreateOrConnectWithoutAuthorInput = { + create: CommentCreateWithoutAuthorInput; + where: CommentWhereUniqueInput; +}; + export type CommentCreateOrConnectWithoutCommentThreadInput = { create: CommentCreateWithoutCommentThreadInput; where: CommentWhereUniqueInput; }; +export type CommentCreateOrConnectWithoutWorkspaceInput = { + create: CommentCreateWithoutWorkspaceInput; + where: CommentWhereUniqueInput; +}; + +export type CommentCreateWithoutAuthorInput = { + body: Scalars['String']; + commentThread: CommentThreadCreateNestedOneWithoutCommentsInput; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CommentCreateWithoutCommentThreadInput = { author: UserCreateNestedOneWithoutCommentsInput; body: Scalars['String']; @@ -105,6 +164,15 @@ export type CommentCreateWithoutCommentThreadInput = { updatedAt?: InputMaybe; }; +export type CommentCreateWithoutWorkspaceInput = { + author: UserCreateNestedOneWithoutCommentsInput; + body: Scalars['String']; + commentThread: CommentThreadCreateNestedOneWithoutCommentsInput; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CommentListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -144,10 +212,46 @@ export type CommentThreadCreateInput = { updatedAt?: InputMaybe; }; +export type CommentThreadCreateManyWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentThreadCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + export type CommentThreadCreateNestedOneWithoutCommentsInput = { connect?: InputMaybe; }; +export type CommentThreadCreateOrConnectWithoutCommentsInput = { + create: CommentThreadCreateWithoutCommentsInput; + where: CommentThreadWhereUniqueInput; +}; + +export type CommentThreadCreateOrConnectWithoutWorkspaceInput = { + create: CommentThreadCreateWithoutWorkspaceInput; + where: CommentThreadWhereUniqueInput; +}; + +export type CommentThreadCreateWithoutCommentsInput = { + commentThreadTargets?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentThreadCreateWithoutWorkspaceInput = { + commentThreadTargets?: InputMaybe; + comments?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CommentThreadOrderByWithRelationInput = { commentThreadTargets?: InputMaybe; comments?: InputMaybe; @@ -169,6 +273,15 @@ export enum CommentThreadScalarFieldEnum { WorkspaceId = 'workspaceId' } +export type CommentThreadScalarWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CommentThreadTarget = { __typename?: 'CommentThreadTarget'; commentThread: CommentThread; @@ -303,6 +416,70 @@ export type CommentThreadUpdateInput = { updatedAt?: InputMaybe; }; +export type CommentThreadUpdateManyMutationInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentThreadUpdateManyWithWhereWithoutWorkspaceInput = { + data: CommentThreadUpdateManyMutationInput; + where: CommentThreadScalarWhereInput; +}; + +export type CommentThreadUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type CommentThreadUpdateOneRequiredWithoutCommentsNestedInput = { + connect?: InputMaybe; + connectOrCreate?: InputMaybe; + create?: InputMaybe; + update?: InputMaybe; + upsert?: InputMaybe; +}; + +export type CommentThreadUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: CommentThreadUpdateWithoutWorkspaceInput; + where: CommentThreadWhereUniqueInput; +}; + +export type CommentThreadUpdateWithoutCommentsInput = { + commentThreadTargets?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentThreadUpdateWithoutWorkspaceInput = { + commentThreadTargets?: InputMaybe; + comments?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentThreadUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: CommentThreadCreateWithoutWorkspaceInput; + update: CommentThreadUpdateWithoutWorkspaceInput; + where: CommentThreadWhereUniqueInput; +}; + +export type CommentThreadUpsertWithoutCommentsInput = { + create: CommentThreadCreateWithoutCommentsInput; + update: CommentThreadUpdateWithoutCommentsInput; +}; + export type CommentThreadWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -325,11 +502,35 @@ export type CommentUpdateManyMutationInput = { updatedAt?: InputMaybe; }; +export type CommentUpdateManyWithWhereWithoutAuthorInput = { + data: CommentUpdateManyMutationInput; + where: CommentScalarWhereInput; +}; + export type CommentUpdateManyWithWhereWithoutCommentThreadInput = { data: CommentUpdateManyMutationInput; where: CommentScalarWhereInput; }; +export type CommentUpdateManyWithWhereWithoutWorkspaceInput = { + data: CommentUpdateManyMutationInput; + where: CommentScalarWhereInput; +}; + +export type CommentUpdateManyWithoutAuthorNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + export type CommentUpdateManyWithoutCommentThreadNestedInput = { connect?: InputMaybe>; connectOrCreate?: InputMaybe>; @@ -344,11 +545,43 @@ export type CommentUpdateManyWithoutCommentThreadNestedInput = { upsert?: InputMaybe>; }; +export type CommentUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type CommentUpdateWithWhereUniqueWithoutAuthorInput = { + data: CommentUpdateWithoutAuthorInput; + where: CommentWhereUniqueInput; +}; + export type CommentUpdateWithWhereUniqueWithoutCommentThreadInput = { data: CommentUpdateWithoutCommentThreadInput; where: CommentWhereUniqueInput; }; +export type CommentUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: CommentUpdateWithoutWorkspaceInput; + where: CommentWhereUniqueInput; +}; + +export type CommentUpdateWithoutAuthorInput = { + body?: InputMaybe; + commentThread?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CommentUpdateWithoutCommentThreadInput = { author?: InputMaybe; body?: InputMaybe; @@ -357,12 +590,33 @@ export type CommentUpdateWithoutCommentThreadInput = { updatedAt?: InputMaybe; }; +export type CommentUpdateWithoutWorkspaceInput = { + author?: InputMaybe; + body?: InputMaybe; + commentThread?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type CommentUpsertWithWhereUniqueWithoutAuthorInput = { + create: CommentCreateWithoutAuthorInput; + update: CommentUpdateWithoutAuthorInput; + where: CommentWhereUniqueInput; +}; + export type CommentUpsertWithWhereUniqueWithoutCommentThreadInput = { create: CommentCreateWithoutCommentThreadInput; update: CommentUpdateWithoutCommentThreadInput; where: CommentWhereUniqueInput; }; +export type CommentUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: CommentCreateWithoutWorkspaceInput; + update: CommentUpdateWithoutWorkspaceInput; + where: CommentWhereUniqueInput; +}; + export type CommentWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -430,6 +684,22 @@ export type CompanyCreateManyAccountOwnerInputEnvelope = { skipDuplicates?: InputMaybe; }; +export type CompanyCreateManyWorkspaceInput = { + accountOwnerId?: InputMaybe; + address: Scalars['String']; + createdAt?: InputMaybe; + domainName: Scalars['String']; + employees?: InputMaybe; + id?: InputMaybe; + name: Scalars['String']; + updatedAt?: InputMaybe; +}; + +export type CompanyCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + export type CompanyCreateNestedManyWithoutAccountOwnerInput = { connect?: InputMaybe>; connectOrCreate?: InputMaybe>; @@ -446,6 +716,11 @@ export type CompanyCreateOrConnectWithoutAccountOwnerInput = { where: CompanyWhereUniqueInput; }; +export type CompanyCreateOrConnectWithoutWorkspaceInput = { + create: CompanyCreateWithoutWorkspaceInput; + where: CompanyWhereUniqueInput; +}; + export type CompanyCreateWithoutAccountOwnerInput = { address: Scalars['String']; createdAt?: InputMaybe; @@ -457,6 +732,18 @@ export type CompanyCreateWithoutAccountOwnerInput = { updatedAt?: InputMaybe; }; +export type CompanyCreateWithoutWorkspaceInput = { + accountOwner?: InputMaybe; + address: Scalars['String']; + createdAt?: InputMaybe; + domainName: Scalars['String']; + employees?: InputMaybe; + id?: InputMaybe; + name: Scalars['String']; + people?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CompanyListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -539,6 +826,11 @@ export type CompanyUpdateManyWithWhereWithoutAccountOwnerInput = { where: CompanyScalarWhereInput; }; +export type CompanyUpdateManyWithWhereWithoutWorkspaceInput = { + data: CompanyUpdateManyMutationInput; + where: CompanyScalarWhereInput; +}; + export type CompanyUpdateManyWithoutAccountOwnerNestedInput = { connect?: InputMaybe>; connectOrCreate?: InputMaybe>; @@ -553,6 +845,20 @@ export type CompanyUpdateManyWithoutAccountOwnerNestedInput = { upsert?: InputMaybe>; }; +export type CompanyUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + export type CompanyUpdateOneWithoutPeopleNestedInput = { connect?: InputMaybe; }; @@ -562,6 +868,11 @@ export type CompanyUpdateWithWhereUniqueWithoutAccountOwnerInput = { where: CompanyWhereUniqueInput; }; +export type CompanyUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: CompanyUpdateWithoutWorkspaceInput; + where: CompanyWhereUniqueInput; +}; + export type CompanyUpdateWithoutAccountOwnerInput = { address?: InputMaybe; createdAt?: InputMaybe; @@ -573,12 +884,30 @@ export type CompanyUpdateWithoutAccountOwnerInput = { updatedAt?: InputMaybe; }; +export type CompanyUpdateWithoutWorkspaceInput = { + accountOwner?: InputMaybe; + address?: InputMaybe; + createdAt?: InputMaybe; + domainName?: InputMaybe; + employees?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + people?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CompanyUpsertWithWhereUniqueWithoutAccountOwnerInput = { create: CompanyCreateWithoutAccountOwnerInput; update: CompanyUpdateWithoutAccountOwnerInput; where: CompanyWhereUniqueInput; }; +export type CompanyUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: CompanyCreateWithoutWorkspaceInput; + update: CompanyUpdateWithoutWorkspaceInput; + where: CompanyWhereUniqueInput; +}; + export type CompanyWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -647,6 +976,10 @@ export type EnumPipelineProgressableTypeFilter = { notIn?: InputMaybe>; }; +export enum FileFolder { + ProfilePicture = 'ProfilePicture' +} + export type IntNullableFilter = { equals?: InputMaybe; gt?: InputMaybe; @@ -697,6 +1030,10 @@ export type Mutation = { updateOneCompany?: Maybe; updateOnePerson?: Maybe; updateOnePipelineProgress?: Maybe; + updateUser: User; + updateWorkspace: Workspace; + uploadFile: Scalars['String']; + uploadImage: Scalars['String']; verify: Verify; }; @@ -787,6 +1124,29 @@ export type MutationUpdateOnePipelineProgressArgs = { }; +export type MutationUpdateUserArgs = { + data: UserUpdateInput; + where: UserWhereUniqueInput; +}; + + +export type MutationUpdateWorkspaceArgs = { + data: WorkspaceUpdateInput; +}; + + +export type MutationUploadFileArgs = { + file: Scalars['Upload']; + fileFolder?: InputMaybe; +}; + + +export type MutationUploadImageArgs = { + file: Scalars['Upload']; + fileFolder?: InputMaybe; +}; + + export type MutationVerifyArgs = { loginToken: Scalars['String']; }; @@ -916,10 +1276,44 @@ export type PersonCreateInput = { updatedAt?: InputMaybe; }; +export type PersonCreateManyWorkspaceInput = { + city: Scalars['String']; + companyId?: InputMaybe; + createdAt?: InputMaybe; + email: Scalars['String']; + firstName: Scalars['String']; + id?: InputMaybe; + lastName: Scalars['String']; + phone: Scalars['String']; + updatedAt?: InputMaybe; +}; + +export type PersonCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + export type PersonCreateNestedManyWithoutCompanyInput = { connect?: InputMaybe>; }; +export type PersonCreateOrConnectWithoutWorkspaceInput = { + create: PersonCreateWithoutWorkspaceInput; + where: PersonWhereUniqueInput; +}; + +export type PersonCreateWithoutWorkspaceInput = { + city: Scalars['String']; + company?: InputMaybe; + createdAt?: InputMaybe; + email: Scalars['String']; + firstName: Scalars['String']; + id?: InputMaybe; + lastName: Scalars['String']; + phone: Scalars['String']; + updatedAt?: InputMaybe; +}; + export type PersonListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -957,6 +1351,21 @@ export enum PersonScalarFieldEnum { WorkspaceId = 'workspaceId' } +export type PersonScalarWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + city?: InputMaybe; + companyId?: InputMaybe; + createdAt?: InputMaybe; + email?: InputMaybe; + firstName?: InputMaybe; + id?: InputMaybe; + lastName?: InputMaybe; + phone?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type PersonUpdateInput = { city?: InputMaybe; company?: InputMaybe; @@ -969,10 +1378,63 @@ export type PersonUpdateInput = { updatedAt?: InputMaybe; }; +export type PersonUpdateManyMutationInput = { + city?: InputMaybe; + createdAt?: InputMaybe; + email?: InputMaybe; + firstName?: InputMaybe; + id?: InputMaybe; + lastName?: InputMaybe; + phone?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PersonUpdateManyWithWhereWithoutWorkspaceInput = { + data: PersonUpdateManyMutationInput; + where: PersonScalarWhereInput; +}; + export type PersonUpdateManyWithoutCompanyNestedInput = { connect?: InputMaybe>; }; +export type PersonUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type PersonUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: PersonUpdateWithoutWorkspaceInput; + where: PersonWhereUniqueInput; +}; + +export type PersonUpdateWithoutWorkspaceInput = { + city?: InputMaybe; + company?: InputMaybe; + createdAt?: InputMaybe; + email?: InputMaybe; + firstName?: InputMaybe; + id?: InputMaybe; + lastName?: InputMaybe; + phone?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PersonUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: PersonCreateWithoutWorkspaceInput; + update: PersonUpdateWithoutWorkspaceInput; + where: PersonWhereUniqueInput; +}; + export type PersonWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -1005,10 +1467,61 @@ export type Pipeline = { updatedAt: Scalars['DateTime']; }; +export type PipelineCreateManyWorkspaceInput = { + createdAt?: InputMaybe; + icon: Scalars['String']; + id?: InputMaybe; + name: Scalars['String']; + pipelineProgressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + export type PipelineCreateNestedOneWithoutPipelineProgressesInput = { connect?: InputMaybe; }; +export type PipelineCreateNestedOneWithoutPipelineStagesInput = { + connect?: InputMaybe; + connectOrCreate?: InputMaybe; + create?: InputMaybe; +}; + +export type PipelineCreateOrConnectWithoutPipelineStagesInput = { + create: PipelineCreateWithoutPipelineStagesInput; + where: PipelineWhereUniqueInput; +}; + +export type PipelineCreateOrConnectWithoutWorkspaceInput = { + create: PipelineCreateWithoutWorkspaceInput; + where: PipelineWhereUniqueInput; +}; + +export type PipelineCreateWithoutPipelineStagesInput = { + createdAt?: InputMaybe; + icon: Scalars['String']; + id?: InputMaybe; + name: Scalars['String']; + pipelineProgressableType?: InputMaybe; + pipelineProgresses?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineCreateWithoutWorkspaceInput = { + createdAt?: InputMaybe; + icon: Scalars['String']; + id?: InputMaybe; + name: Scalars['String']; + pipelineProgressableType?: InputMaybe; + pipelineProgresses?: InputMaybe; + pipelineStages?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type PipelineOrderByWithRelationInput = { createdAt?: InputMaybe; icon?: InputMaybe; @@ -1043,6 +1556,106 @@ export type PipelineProgressCreateInput = { updatedAt?: InputMaybe; }; +export type PipelineProgressCreateManyPipelineInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipelineStageId: Scalars['String']; + progressableId: Scalars['String']; + progressableType: PipelineProgressableType; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressCreateManyPipelineInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type PipelineProgressCreateManyPipelineStageInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipelineId: Scalars['String']; + progressableId: Scalars['String']; + progressableType: PipelineProgressableType; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressCreateManyPipelineStageInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type PipelineProgressCreateManyWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipelineId: Scalars['String']; + pipelineStageId: Scalars['String']; + progressableId: Scalars['String']; + progressableType: PipelineProgressableType; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type PipelineProgressCreateNestedManyWithoutPipelineInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; +}; + +export type PipelineProgressCreateNestedManyWithoutPipelineStageInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; +}; + +export type PipelineProgressCreateOrConnectWithoutPipelineInput = { + create: PipelineProgressCreateWithoutPipelineInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressCreateOrConnectWithoutPipelineStageInput = { + create: PipelineProgressCreateWithoutPipelineStageInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressCreateOrConnectWithoutWorkspaceInput = { + create: PipelineProgressCreateWithoutWorkspaceInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressCreateWithoutPipelineInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipelineStage: PipelineStageCreateNestedOneWithoutPipelineProgressesInput; + progressableId: Scalars['String']; + progressableType: PipelineProgressableType; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressCreateWithoutPipelineStageInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipeline: PipelineCreateNestedOneWithoutPipelineProgressesInput; + progressableId: Scalars['String']; + progressableType: PipelineProgressableType; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressCreateWithoutWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipeline: PipelineCreateNestedOneWithoutPipelineProgressesInput; + pipelineStage: PipelineStageCreateNestedOneWithoutPipelineProgressesInput; + progressableId: Scalars['String']; + progressableType: PipelineProgressableType; + updatedAt?: InputMaybe; +}; + export type PipelineProgressListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -1077,6 +1690,19 @@ export enum PipelineProgressScalarFieldEnum { WorkspaceId = 'workspaceId' } +export type PipelineProgressScalarWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + createdAt?: InputMaybe; + id?: InputMaybe; + pipelineId?: InputMaybe; + pipelineStageId?: InputMaybe; + progressableId?: InputMaybe; + progressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type PipelineProgressUpdateInput = { createdAt?: InputMaybe; id?: InputMaybe; @@ -1087,6 +1713,132 @@ export type PipelineProgressUpdateInput = { updatedAt?: InputMaybe; }; +export type PipelineProgressUpdateManyMutationInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + progressableId?: InputMaybe; + progressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressUpdateManyWithWhereWithoutPipelineInput = { + data: PipelineProgressUpdateManyMutationInput; + where: PipelineProgressScalarWhereInput; +}; + +export type PipelineProgressUpdateManyWithWhereWithoutPipelineStageInput = { + data: PipelineProgressUpdateManyMutationInput; + where: PipelineProgressScalarWhereInput; +}; + +export type PipelineProgressUpdateManyWithWhereWithoutWorkspaceInput = { + data: PipelineProgressUpdateManyMutationInput; + where: PipelineProgressScalarWhereInput; +}; + +export type PipelineProgressUpdateManyWithoutPipelineNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type PipelineProgressUpdateManyWithoutPipelineStageNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type PipelineProgressUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type PipelineProgressUpdateWithWhereUniqueWithoutPipelineInput = { + data: PipelineProgressUpdateWithoutPipelineInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressUpdateWithWhereUniqueWithoutPipelineStageInput = { + data: PipelineProgressUpdateWithoutPipelineStageInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: PipelineProgressUpdateWithoutWorkspaceInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressUpdateWithoutPipelineInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipelineStage?: InputMaybe; + progressableId?: InputMaybe; + progressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressUpdateWithoutPipelineStageInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipeline?: InputMaybe; + progressableId?: InputMaybe; + progressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressUpdateWithoutWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + pipeline?: InputMaybe; + pipelineStage?: InputMaybe; + progressableId?: InputMaybe; + progressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineProgressUpsertWithWhereUniqueWithoutPipelineInput = { + create: PipelineProgressCreateWithoutPipelineInput; + update: PipelineProgressUpdateWithoutPipelineInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressUpsertWithWhereUniqueWithoutPipelineStageInput = { + create: PipelineProgressCreateWithoutPipelineStageInput; + update: PipelineProgressUpdateWithoutPipelineStageInput; + where: PipelineProgressWhereUniqueInput; +}; + +export type PipelineProgressUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: PipelineProgressCreateWithoutWorkspaceInput; + update: PipelineProgressUpdateWithoutWorkspaceInput; + where: PipelineProgressWhereUniqueInput; +}; + export type PipelineProgressWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -1127,6 +1879,18 @@ export enum PipelineScalarFieldEnum { WorkspaceId = 'workspaceId' } +export type PipelineScalarWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + createdAt?: InputMaybe; + icon?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipelineProgressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type PipelineStage = { __typename?: 'PipelineStage'; color: Scalars['String']; @@ -1140,10 +1904,77 @@ export type PipelineStage = { updatedAt: Scalars['DateTime']; }; +export type PipelineStageCreateManyPipelineInput = { + color: Scalars['String']; + createdAt?: InputMaybe; + id?: InputMaybe; + name: Scalars['String']; + type: Scalars['String']; + updatedAt?: InputMaybe; +}; + +export type PipelineStageCreateManyPipelineInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type PipelineStageCreateManyWorkspaceInput = { + color: Scalars['String']; + createdAt?: InputMaybe; + id?: InputMaybe; + name: Scalars['String']; + pipelineId: Scalars['String']; + type: Scalars['String']; + updatedAt?: InputMaybe; +}; + +export type PipelineStageCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type PipelineStageCreateNestedManyWithoutPipelineInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; +}; + export type PipelineStageCreateNestedOneWithoutPipelineProgressesInput = { connect?: InputMaybe; }; +export type PipelineStageCreateOrConnectWithoutPipelineInput = { + create: PipelineStageCreateWithoutPipelineInput; + where: PipelineStageWhereUniqueInput; +}; + +export type PipelineStageCreateOrConnectWithoutWorkspaceInput = { + create: PipelineStageCreateWithoutWorkspaceInput; + where: PipelineStageWhereUniqueInput; +}; + +export type PipelineStageCreateWithoutPipelineInput = { + color: Scalars['String']; + createdAt?: InputMaybe; + id?: InputMaybe; + name: Scalars['String']; + pipelineProgresses?: InputMaybe; + type: Scalars['String']; + updatedAt?: InputMaybe; +}; + +export type PipelineStageCreateWithoutWorkspaceInput = { + color: Scalars['String']; + createdAt?: InputMaybe; + id?: InputMaybe; + name: Scalars['String']; + pipeline: PipelineCreateNestedOneWithoutPipelineStagesInput; + pipelineProgresses?: InputMaybe; + type: Scalars['String']; + updatedAt?: InputMaybe; +}; + export type PipelineStageListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -1183,10 +2014,113 @@ export enum PipelineStageScalarFieldEnum { WorkspaceId = 'workspaceId' } +export type PipelineStageScalarWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + color?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipelineId?: InputMaybe; + type?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineStageUpdateManyMutationInput = { + color?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + type?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineStageUpdateManyWithWhereWithoutPipelineInput = { + data: PipelineStageUpdateManyMutationInput; + where: PipelineStageScalarWhereInput; +}; + +export type PipelineStageUpdateManyWithWhereWithoutWorkspaceInput = { + data: PipelineStageUpdateManyMutationInput; + where: PipelineStageScalarWhereInput; +}; + +export type PipelineStageUpdateManyWithoutPipelineNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type PipelineStageUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + export type PipelineStageUpdateOneRequiredWithoutPipelineProgressesNestedInput = { connect?: InputMaybe; }; +export type PipelineStageUpdateWithWhereUniqueWithoutPipelineInput = { + data: PipelineStageUpdateWithoutPipelineInput; + where: PipelineStageWhereUniqueInput; +}; + +export type PipelineStageUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: PipelineStageUpdateWithoutWorkspaceInput; + where: PipelineStageWhereUniqueInput; +}; + +export type PipelineStageUpdateWithoutPipelineInput = { + color?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipelineProgresses?: InputMaybe; + type?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineStageUpdateWithoutWorkspaceInput = { + color?: InputMaybe; + createdAt?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipeline?: InputMaybe; + pipelineProgresses?: InputMaybe; + type?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineStageUpsertWithWhereUniqueWithoutPipelineInput = { + create: PipelineStageCreateWithoutPipelineInput; + update: PipelineStageUpdateWithoutPipelineInput; + where: PipelineStageWhereUniqueInput; +}; + +export type PipelineStageUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: PipelineStageCreateWithoutWorkspaceInput; + update: PipelineStageUpdateWithoutWorkspaceInput; + where: PipelineStageWhereUniqueInput; +}; + export type PipelineStageWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -1206,10 +2140,83 @@ export type PipelineStageWhereUniqueInput = { id?: InputMaybe; }; +export type PipelineUpdateManyMutationInput = { + createdAt?: InputMaybe; + icon?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipelineProgressableType?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineUpdateManyWithWhereWithoutWorkspaceInput = { + data: PipelineUpdateManyMutationInput; + where: PipelineScalarWhereInput; +}; + +export type PipelineUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + export type PipelineUpdateOneRequiredWithoutPipelineProgressesNestedInput = { connect?: InputMaybe; }; +export type PipelineUpdateOneRequiredWithoutPipelineStagesNestedInput = { + connect?: InputMaybe; + connectOrCreate?: InputMaybe; + create?: InputMaybe; + update?: InputMaybe; + upsert?: InputMaybe; +}; + +export type PipelineUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: PipelineUpdateWithoutWorkspaceInput; + where: PipelineWhereUniqueInput; +}; + +export type PipelineUpdateWithoutPipelineStagesInput = { + createdAt?: InputMaybe; + icon?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipelineProgressableType?: InputMaybe; + pipelineProgresses?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineUpdateWithoutWorkspaceInput = { + createdAt?: InputMaybe; + icon?: InputMaybe; + id?: InputMaybe; + name?: InputMaybe; + pipelineProgressableType?: InputMaybe; + pipelineProgresses?: InputMaybe; + pipelineStages?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type PipelineUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: PipelineCreateWithoutWorkspaceInput; + update: PipelineUpdateWithoutWorkspaceInput; + where: PipelineWhereUniqueInput; +}; + +export type PipelineUpsertWithoutPipelineStagesInput = { + create: PipelineCreateWithoutPipelineStagesInput; + update: PipelineUpdateWithoutPipelineStagesInput; +}; + export type PipelineWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -1230,6 +2237,8 @@ export type PipelineWhereUniqueInput = { export type Query = { __typename?: 'Query'; + clientConfig: ClientConfig; + currentUser: User; findManyCommentThreads: Array; findManyCompany: Array; findManyPerson: Array; @@ -1363,9 +2372,9 @@ export type User = { displayName: Scalars['String']; email: Scalars['String']; emailVerified: Scalars['Boolean']; - firstName: Scalars['String']; + firstName?: Maybe; id: Scalars['ID']; - lastName: Scalars['String']; + lastName?: Maybe; lastSeen?: Maybe; locale: Scalars['String']; metadata?: Maybe; @@ -1382,22 +2391,50 @@ export type UserCreateNestedOneWithoutCompaniesInput = { connect?: InputMaybe; }; +export type UserCreateNestedOneWithoutWorkspaceMemberInput = { + connect?: InputMaybe; + connectOrCreate?: InputMaybe; + create?: InputMaybe; +}; + export type UserCreateOrConnectWithoutCommentsInput = { create: UserCreateWithoutCommentsInput; where: UserWhereUniqueInput; }; +export type UserCreateOrConnectWithoutWorkspaceMemberInput = { + create: UserCreateWithoutWorkspaceMemberInput; + where: UserWhereUniqueInput; +}; + export type UserCreateWithoutCommentsInput = { avatarUrl?: InputMaybe; companies?: InputMaybe; createdAt?: InputMaybe; disabled?: InputMaybe; - displayName?: InputMaybe; email: Scalars['String']; emailVerified?: InputMaybe; - firstName: Scalars['String']; + firstName?: InputMaybe; id?: InputMaybe; - lastName: Scalars['String']; + lastName?: InputMaybe; + lastSeen?: InputMaybe; + locale: Scalars['String']; + metadata?: InputMaybe; + phoneNumber?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type UserCreateWithoutWorkspaceMemberInput = { + avatarUrl?: InputMaybe; + comments?: InputMaybe; + companies?: InputMaybe; + createdAt?: InputMaybe; + disabled?: InputMaybe; + email: Scalars['String']; + emailVerified?: InputMaybe; + firstName?: InputMaybe; + id?: InputMaybe; + lastName?: InputMaybe; lastSeen?: InputMaybe; locale: Scalars['String']; metadata?: InputMaybe; @@ -1411,7 +2448,6 @@ export type UserOrderByWithRelationInput = { companies?: InputMaybe; createdAt?: InputMaybe; disabled?: InputMaybe; - displayName?: InputMaybe; email?: InputMaybe; emailVerified?: InputMaybe; firstName?: InputMaybe; @@ -1434,7 +2470,6 @@ export enum UserScalarFieldEnum { CreatedAt = 'createdAt', DeletedAt = 'deletedAt', Disabled = 'disabled', - DisplayName = 'displayName', Email = 'email', EmailVerified = 'emailVerified', FirstName = 'firstName', @@ -1448,6 +2483,24 @@ export enum UserScalarFieldEnum { UpdatedAt = 'updatedAt' } +export type UserUpdateInput = { + avatarUrl?: InputMaybe; + comments?: InputMaybe; + companies?: InputMaybe; + createdAt?: InputMaybe; + disabled?: InputMaybe; + email?: InputMaybe; + emailVerified?: InputMaybe; + firstName?: InputMaybe; + id?: InputMaybe; + lastName?: InputMaybe; + lastSeen?: InputMaybe; + locale?: InputMaybe; + metadata?: InputMaybe; + phoneNumber?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type UserUpdateOneRequiredWithoutCommentsNestedInput = { connect?: InputMaybe; connectOrCreate?: InputMaybe; @@ -1456,6 +2509,14 @@ export type UserUpdateOneRequiredWithoutCommentsNestedInput = { upsert?: InputMaybe; }; +export type UserUpdateOneRequiredWithoutWorkspaceMemberNestedInput = { + connect?: InputMaybe; + connectOrCreate?: InputMaybe; + create?: InputMaybe; + update?: InputMaybe; + upsert?: InputMaybe; +}; + export type UserUpdateOneWithoutCompaniesNestedInput = { connect?: InputMaybe; }; @@ -1465,12 +2526,29 @@ export type UserUpdateWithoutCommentsInput = { companies?: InputMaybe; createdAt?: InputMaybe; disabled?: InputMaybe; - displayName?: InputMaybe; email?: InputMaybe; emailVerified?: InputMaybe; - firstName?: InputMaybe; + firstName?: InputMaybe; id?: InputMaybe; - lastName?: InputMaybe; + lastName?: InputMaybe; + lastSeen?: InputMaybe; + locale?: InputMaybe; + metadata?: InputMaybe; + phoneNumber?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type UserUpdateWithoutWorkspaceMemberInput = { + avatarUrl?: InputMaybe; + comments?: InputMaybe; + companies?: InputMaybe; + createdAt?: InputMaybe; + disabled?: InputMaybe; + email?: InputMaybe; + emailVerified?: InputMaybe; + firstName?: InputMaybe; + id?: InputMaybe; + lastName?: InputMaybe; lastSeen?: InputMaybe; locale?: InputMaybe; metadata?: InputMaybe; @@ -1483,6 +2561,11 @@ export type UserUpsertWithoutCommentsInput = { update: UserUpdateWithoutCommentsInput; }; +export type UserUpsertWithoutWorkspaceMemberInput = { + create: UserCreateWithoutWorkspaceMemberInput; + update: UserUpdateWithoutWorkspaceMemberInput; +}; + export type UserWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -1492,12 +2575,11 @@ export type UserWhereInput = { companies?: InputMaybe; createdAt?: InputMaybe; disabled?: InputMaybe; - displayName?: InputMaybe; email?: InputMaybe; emailVerified?: InputMaybe; - firstName?: InputMaybe; + firstName?: InputMaybe; id?: InputMaybe; - lastName?: InputMaybe; + lastName?: InputMaybe; lastSeen?: InputMaybe; locale?: InputMaybe; metadata?: InputMaybe; @@ -1522,8 +2604,8 @@ export type Workspace = { comments?: Maybe>; companies?: Maybe>; createdAt: Scalars['DateTime']; - displayName: Scalars['String']; - domainName: Scalars['String']; + displayName?: Maybe; + domainName?: Maybe; id: Scalars['ID']; logo?: Maybe; people?: Maybe>; @@ -1544,6 +2626,105 @@ export type WorkspaceMember = { workspace: Workspace; }; +export type WorkspaceMemberCreateManyWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; + userId: Scalars['String']; +}; + +export type WorkspaceMemberCreateManyWorkspaceInputEnvelope = { + data: Array; + skipDuplicates?: InputMaybe; +}; + +export type WorkspaceMemberCreateOrConnectWithoutWorkspaceInput = { + create: WorkspaceMemberCreateWithoutWorkspaceInput; + where: WorkspaceMemberWhereUniqueInput; +}; + +export type WorkspaceMemberCreateWithoutWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; + user: UserCreateNestedOneWithoutWorkspaceMemberInput; +}; + +export type WorkspaceMemberScalarWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; + userId?: InputMaybe; +}; + +export type WorkspaceMemberUpdateManyMutationInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type WorkspaceMemberUpdateManyWithWhereWithoutWorkspaceInput = { + data: WorkspaceMemberUpdateManyMutationInput; + where: WorkspaceMemberScalarWhereInput; +}; + +export type WorkspaceMemberUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + connectOrCreate?: InputMaybe>; + create?: InputMaybe>; + createMany?: InputMaybe; + delete?: InputMaybe>; + deleteMany?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; + update?: InputMaybe>; + updateMany?: InputMaybe>; + upsert?: InputMaybe>; +}; + +export type WorkspaceMemberUpdateWithWhereUniqueWithoutWorkspaceInput = { + data: WorkspaceMemberUpdateWithoutWorkspaceInput; + where: WorkspaceMemberWhereUniqueInput; +}; + +export type WorkspaceMemberUpdateWithoutWorkspaceInput = { + createdAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; + user?: InputMaybe; +}; + +export type WorkspaceMemberUpsertWithWhereUniqueWithoutWorkspaceInput = { + create: WorkspaceMemberCreateWithoutWorkspaceInput; + update: WorkspaceMemberUpdateWithoutWorkspaceInput; + where: WorkspaceMemberWhereUniqueInput; +}; + +export type WorkspaceMemberWhereUniqueInput = { + id?: InputMaybe; + userId?: InputMaybe; +}; + +export type WorkspaceUpdateInput = { + commentThreads?: InputMaybe; + comments?: InputMaybe; + companies?: InputMaybe; + createdAt?: InputMaybe; + displayName?: InputMaybe; + domainName?: InputMaybe; + id?: InputMaybe; + logo?: InputMaybe; + people?: InputMaybe; + pipelineProgresses?: InputMaybe; + pipelineStages?: InputMaybe; + pipelines?: InputMaybe; + updatedAt?: InputMaybe; + workspaceMember?: InputMaybe; +}; + export type CreateEventMutationVariables = Exact<{ type: Scalars['String']; data: Scalars['JSON']; @@ -1552,6 +2733,11 @@ export type CreateEventMutationVariables = Exact<{ export type CreateEventMutation = { __typename?: 'Mutation', createEvent: { __typename?: 'Analytics', success: boolean } }; +export type GetClientConfigQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetClientConfigQuery = { __typename?: 'Query', clientConfig: { __typename?: 'ClientConfig', display_google_login: boolean, prefill_login_with_seed: boolean } }; + export type ChallengeMutationVariables = Exact<{ email: Scalars['String']; password: Scalars['String']; @@ -1565,7 +2751,7 @@ export type VerifyMutationVariables = Exact<{ }>; -export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, email: string, displayName: string, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, workspace: { __typename?: 'Workspace', id: string, domainName: string, displayName: string, logo?: string | null } } | null }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type VerifyMutation = { __typename?: 'Mutation', verify: { __typename?: 'Verify', user: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null } } | null }, tokens: { __typename?: 'AuthTokenPair', accessToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type RenewTokenMutationVariables = Exact<{ refreshToken: Scalars['String']; @@ -1583,7 +2769,7 @@ export type CreateCommentMutationVariables = Exact<{ }>; -export type CreateCommentMutation = { __typename?: 'Mutation', createOneComment: { __typename?: 'Comment', id: string, createdAt: string, body: string, commentThreadId: string, author: { __typename?: 'User', id: string, displayName: string, firstName: string, lastName: string, avatarUrl?: string | null } } }; +export type CreateCommentMutation = { __typename?: 'Mutation', createOneComment: { __typename?: 'Comment', id: string, createdAt: string, body: string, commentThreadId: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } } }; export type CreateCommentThreadWithCommentMutationVariables = Exact<{ commentThreadId: Scalars['String']; @@ -1603,14 +2789,14 @@ export type GetCommentThreadsByTargetsQueryVariables = Exact<{ }>; -export type GetCommentThreadsByTargetsQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName: string, lastName: string, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, commentableId: string, commentableType: CommentableType }> | null }> }; +export type GetCommentThreadsByTargetsQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', id: string, commentableId: string, commentableType: CommentableType }> | null }> }; export type GetCommentThreadQueryVariables = Exact<{ commentThreadId: Scalars['String']; }>; -export type GetCommentThreadQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName: string, lastName: string, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', commentableId: string, commentableType: CommentableType }> | null }> }; +export type GetCommentThreadQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', commentableId: string, commentableType: CommentableType }> | null }> }; export type AddCommentThreadTargetOnCommentThreadMutationVariables = Exact<{ commentThreadId: Scalars['String']; @@ -1644,7 +2830,7 @@ export type GetCompaniesQueryVariables = Exact<{ }>; -export type GetCompaniesQuery = { __typename?: 'Query', companies: Array<{ __typename?: 'Company', id: string, domainName: string, name: string, createdAt: string, address: string, employees?: number | null, _commentCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, firstName: string, lastName: string } | null }> }; +export type GetCompaniesQuery = { __typename?: 'Query', companies: Array<{ __typename?: 'Company', id: string, domainName: string, name: string, createdAt: string, address: string, employees?: number | null, _commentCount: number, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null } | null }> }; export type UpdateCompanyMutationVariables = Exact<{ id?: InputMaybe; @@ -1657,7 +2843,7 @@ export type UpdateCompanyMutationVariables = Exact<{ }>; -export type UpdateCompanyMutation = { __typename?: 'Mutation', updateOneCompany?: { __typename?: 'Company', address: string, createdAt: string, domainName: string, employees?: number | null, id: string, name: string, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, firstName: string, lastName: string } | null } | null }; +export type UpdateCompanyMutation = { __typename?: 'Mutation', updateOneCompany?: { __typename?: 'Company', address: string, createdAt: string, domainName: string, employees?: number | null, id: string, name: string, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null } | null } | null }; export type InsertCompanyMutationVariables = Exact<{ id: Scalars['String']; @@ -1678,39 +2864,6 @@ export type DeleteCompaniesMutationVariables = Exact<{ export type DeleteCompaniesMutation = { __typename?: 'Mutation', deleteManyCompany: { __typename?: 'AffectedRows', count: number } }; -export type GetPipelinesQueryVariables = Exact<{ - where?: InputMaybe; -}>; - - -export type GetPipelinesQuery = { __typename?: 'Query', findManyPipeline: Array<{ __typename?: 'Pipeline', id: string, name: string, pipelineProgressableType: PipelineProgressableType, pipelineStages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, color: string, pipelineProgresses?: Array<{ __typename?: 'PipelineProgress', id: string, progressableType: PipelineProgressableType, progressableId: string }> | null }> | null }> }; - -export type UpdateOnePipelineProgressMutationVariables = Exact<{ - id?: InputMaybe; - pipelineStageId?: InputMaybe; -}>; - - -export type UpdateOnePipelineProgressMutation = { __typename?: 'Mutation', updateOnePipelineProgress?: { __typename?: 'PipelineProgress', id: string } | null }; - -export type CreateOnePipelineProgressMutationVariables = Exact<{ - uuid: Scalars['String']; - entityType: PipelineProgressableType; - entityId: Scalars['String']; - pipelineId: Scalars['String']; - pipelineStageId: Scalars['String']; -}>; - - -export type CreateOnePipelineProgressMutation = { __typename?: 'Mutation', createOnePipelineProgress: { __typename?: 'PipelineProgress', id: string } }; - -export type DeleteManyPipelineProgressMutationVariables = Exact<{ - ids?: InputMaybe | Scalars['String']>; -}>; - - -export type DeleteManyPipelineProgressMutation = { __typename?: 'Mutation', deleteManyPipelineProgress: { __typename?: 'AffectedRows', count: number } }; - export type GetPeopleQueryVariables = Exact<{ orderBy?: InputMaybe | PersonOrderByWithRelationInput>; where?: InputMaybe; @@ -1754,6 +2907,39 @@ export type DeletePeopleMutationVariables = Exact<{ export type DeletePeopleMutation = { __typename?: 'Mutation', deleteManyPerson: { __typename?: 'AffectedRows', count: number } }; +export type GetPipelinesQueryVariables = Exact<{ + where?: InputMaybe; +}>; + + +export type GetPipelinesQuery = { __typename?: 'Query', findManyPipeline: Array<{ __typename?: 'Pipeline', id: string, name: string, pipelineProgressableType: PipelineProgressableType, pipelineStages?: Array<{ __typename?: 'PipelineStage', id: string, name: string, color: string, pipelineProgresses?: Array<{ __typename?: 'PipelineProgress', id: string, progressableType: PipelineProgressableType, progressableId: string }> | null }> | null }> }; + +export type UpdateOnePipelineProgressMutationVariables = Exact<{ + id?: InputMaybe; + pipelineStageId?: InputMaybe; +}>; + + +export type UpdateOnePipelineProgressMutation = { __typename?: 'Mutation', updateOnePipelineProgress?: { __typename?: 'PipelineProgress', id: string } | null }; + +export type CreateOnePipelineProgressMutationVariables = Exact<{ + uuid: Scalars['String']; + entityType: PipelineProgressableType; + entityId: Scalars['String']; + pipelineId: Scalars['String']; + pipelineStageId: Scalars['String']; +}>; + + +export type CreateOnePipelineProgressMutation = { __typename?: 'Mutation', createOnePipelineProgress: { __typename?: 'PipelineProgress', id: string } }; + +export type DeleteManyPipelineProgressMutationVariables = Exact<{ + ids?: InputMaybe | Scalars['String']>; +}>; + + +export type DeleteManyPipelineProgressMutation = { __typename?: 'Mutation', deleteManyPipelineProgress: { __typename?: 'AffectedRows', count: number } }; + export type SearchPeopleQueryVariables = Exact<{ where?: InputMaybe; limit?: InputMaybe; @@ -1770,7 +2956,7 @@ export type SearchUserQueryVariables = Exact<{ }>; -export type SearchUserQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName: string, lastName: string }> }; +export type SearchUserQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> }; export type EmptyQueryQueryVariables = Exact<{ [key: string]: never; }>; @@ -1786,27 +2972,31 @@ export type SearchCompanyQueryVariables = Exact<{ export type SearchCompanyQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> }; -export type GetCurrentUserQueryVariables = Exact<{ - uuid?: InputMaybe; -}>; +export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>; -export type GetCurrentUserQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName: string, lastName: string, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, workspace: { __typename?: 'Workspace', id: string, domainName: string, displayName: string, logo?: string | null } } | null }> }; +export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, workspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null } } | null } }; export type GetUsersQueryVariables = Exact<{ [key: string]: never; }>; -export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName: string, lastName: string }> }; +export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> }; + +export type UpdateUserMutationVariables = Exact<{ + data: UserUpdateInput; + where: UserWhereUniqueInput; +}>; + + +export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }; + +export type UpdateWorkspaceMutationVariables = Exact<{ + data: WorkspaceUpdateInput; +}>; + + +export type UpdateWorkspaceMutation = { __typename?: 'Mutation', updateWorkspace: { __typename?: 'Workspace', id: string, domainName?: string | null, displayName?: string | null, logo?: string | null } }; -export type GetClientConfigQuery = { - __typename?: 'Query'; - clientConfig: { - __typename?: 'ClientConfig'; - display_google_login: boolean; - prefill_login_with_seed: boolean; - }; -}; -export type GetClientConfigQueryVariables = {}; export const CreateEventDocument = gql` mutation CreateEvent($type: String!, $data: JSON!) { @@ -1842,6 +3032,41 @@ export function useCreateEventMutation(baseOptions?: Apollo.MutationHookOptions< export type CreateEventMutationHookResult = ReturnType; export type CreateEventMutationResult = Apollo.MutationResult; export type CreateEventMutationOptions = Apollo.BaseMutationOptions; +export const GetClientConfigDocument = gql` + query GetClientConfig { + clientConfig { + display_google_login + prefill_login_with_seed + } +} + `; + +/** + * __useGetClientConfigQuery__ + * + * To run a query within a React component, call `useGetClientConfigQuery` and pass it any options that fit your needs. + * When your component renders, `useGetClientConfigQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetClientConfigQuery({ + * variables: { + * }, + * }); + */ +export function useGetClientConfigQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetClientConfigDocument, options); + } +export function useGetClientConfigLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetClientConfigDocument, options); + } +export type GetClientConfigQueryHookResult = ReturnType; +export type GetClientConfigLazyQueryHookResult = ReturnType; +export type GetClientConfigQueryResult = Apollo.QueryResult; export const ChallengeDocument = gql` mutation Challenge($email: String!, $password: String!) { challenge(email: $email, password: $password) { @@ -1886,6 +3111,8 @@ export const VerifyDocument = gql` id email displayName + firstName + lastName workspaceMember { id workspace { @@ -2503,162 +3730,6 @@ export function useDeleteCompaniesMutation(baseOptions?: Apollo.MutationHookOpti export type DeleteCompaniesMutationHookResult = ReturnType; export type DeleteCompaniesMutationResult = Apollo.MutationResult; export type DeleteCompaniesMutationOptions = Apollo.BaseMutationOptions; -export const GetPipelinesDocument = gql` - query GetPipelines($where: PipelineWhereInput) { - findManyPipeline(where: $where) { - id - name - pipelineProgressableType - pipelineStages { - id - name - color - pipelineProgresses { - id - progressableType - progressableId - } - } - } -} - `; - -/** - * __useGetPipelinesQuery__ - * - * To run a query within a React component, call `useGetPipelinesQuery` and pass it any options that fit your needs. - * When your component renders, `useGetPipelinesQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useGetPipelinesQuery({ - * variables: { - * where: // value for 'where' - * }, - * }); - */ -export function useGetPipelinesQuery(baseOptions?: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetPipelinesDocument, options); - } -export function useGetPipelinesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetPipelinesDocument, options); - } -export type GetPipelinesQueryHookResult = ReturnType; -export type GetPipelinesLazyQueryHookResult = ReturnType; -export type GetPipelinesQueryResult = Apollo.QueryResult; -export const UpdateOnePipelineProgressDocument = gql` - mutation UpdateOnePipelineProgress($id: String, $pipelineStageId: String) { - updateOnePipelineProgress( - where: {id: $id} - data: {pipelineStage: {connect: {id: $pipelineStageId}}} - ) { - id - } -} - `; -export type UpdateOnePipelineProgressMutationFn = Apollo.MutationFunction; - -/** - * __useUpdateOnePipelineProgressMutation__ - * - * To run a mutation, you first call `useUpdateOnePipelineProgressMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useUpdateOnePipelineProgressMutation` 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 [updateOnePipelineProgressMutation, { data, loading, error }] = useUpdateOnePipelineProgressMutation({ - * variables: { - * id: // value for 'id' - * pipelineStageId: // value for 'pipelineStageId' - * }, - * }); - */ -export function useUpdateOnePipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(UpdateOnePipelineProgressDocument, options); - } -export type UpdateOnePipelineProgressMutationHookResult = ReturnType; -export type UpdateOnePipelineProgressMutationResult = Apollo.MutationResult; -export type UpdateOnePipelineProgressMutationOptions = Apollo.BaseMutationOptions; -export const CreateOnePipelineProgressDocument = gql` - mutation CreateOnePipelineProgress($uuid: String!, $entityType: PipelineProgressableType!, $entityId: String!, $pipelineId: String!, $pipelineStageId: String!) { - createOnePipelineProgress( - data: {id: $uuid, progressableType: $entityType, progressableId: $entityId, pipeline: {connect: {id: $pipelineId}}, pipelineStage: {connect: {id: $pipelineStageId}}} - ) { - id - } -} - `; -export type CreateOnePipelineProgressMutationFn = Apollo.MutationFunction; - -/** - * __useCreateOnePipelineProgressMutation__ - * - * To run a mutation, you first call `useCreateOnePipelineProgressMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useCreateOnePipelineProgressMutation` 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 [createOnePipelineProgressMutation, { data, loading, error }] = useCreateOnePipelineProgressMutation({ - * variables: { - * uuid: // value for 'uuid' - * entityType: // value for 'entityType' - * entityId: // value for 'entityId' - * pipelineId: // value for 'pipelineId' - * pipelineStageId: // value for 'pipelineStageId' - * }, - * }); - */ -export function useCreateOnePipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateOnePipelineProgressDocument, options); - } -export type CreateOnePipelineProgressMutationHookResult = ReturnType; -export type CreateOnePipelineProgressMutationResult = Apollo.MutationResult; -export type CreateOnePipelineProgressMutationOptions = Apollo.BaseMutationOptions; -export const DeleteManyPipelineProgressDocument = gql` - mutation DeleteManyPipelineProgress($ids: [String!]) { - deleteManyPipelineProgress(where: {id: {in: $ids}}) { - count - } -} - `; -export type DeleteManyPipelineProgressMutationFn = Apollo.MutationFunction; - -/** - * __useDeleteManyPipelineProgressMutation__ - * - * To run a mutation, you first call `useDeleteManyPipelineProgressMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useDeleteManyPipelineProgressMutation` 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 [deleteManyPipelineProgressMutation, { data, loading, error }] = useDeleteManyPipelineProgressMutation({ - * variables: { - * ids: // value for 'ids' - * }, - * }); - */ -export function useDeleteManyPipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(DeleteManyPipelineProgressDocument, options); - } -export type DeleteManyPipelineProgressMutationHookResult = ReturnType; -export type DeleteManyPipelineProgressMutationResult = Apollo.MutationResult; -export type DeleteManyPipelineProgressMutationOptions = Apollo.BaseMutationOptions; export const GetPeopleDocument = gql` query GetPeople($orderBy: [PersonOrderByWithRelationInput!], $where: PersonWhereInput, $limit: Int) { people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) { @@ -2847,6 +3918,162 @@ export function useDeletePeopleMutation(baseOptions?: Apollo.MutationHookOptions export type DeletePeopleMutationHookResult = ReturnType; export type DeletePeopleMutationResult = Apollo.MutationResult; export type DeletePeopleMutationOptions = Apollo.BaseMutationOptions; +export const GetPipelinesDocument = gql` + query GetPipelines($where: PipelineWhereInput) { + findManyPipeline(where: $where) { + id + name + pipelineProgressableType + pipelineStages { + id + name + color + pipelineProgresses { + id + progressableType + progressableId + } + } + } +} + `; + +/** + * __useGetPipelinesQuery__ + * + * To run a query within a React component, call `useGetPipelinesQuery` and pass it any options that fit your needs. + * When your component renders, `useGetPipelinesQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetPipelinesQuery({ + * variables: { + * where: // value for 'where' + * }, + * }); + */ +export function useGetPipelinesQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetPipelinesDocument, options); + } +export function useGetPipelinesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetPipelinesDocument, options); + } +export type GetPipelinesQueryHookResult = ReturnType; +export type GetPipelinesLazyQueryHookResult = ReturnType; +export type GetPipelinesQueryResult = Apollo.QueryResult; +export const UpdateOnePipelineProgressDocument = gql` + mutation UpdateOnePipelineProgress($id: String, $pipelineStageId: String) { + updateOnePipelineProgress( + where: {id: $id} + data: {pipelineStage: {connect: {id: $pipelineStageId}}} + ) { + id + } +} + `; +export type UpdateOnePipelineProgressMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateOnePipelineProgressMutation__ + * + * To run a mutation, you first call `useUpdateOnePipelineProgressMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateOnePipelineProgressMutation` 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 [updateOnePipelineProgressMutation, { data, loading, error }] = useUpdateOnePipelineProgressMutation({ + * variables: { + * id: // value for 'id' + * pipelineStageId: // value for 'pipelineStageId' + * }, + * }); + */ +export function useUpdateOnePipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateOnePipelineProgressDocument, options); + } +export type UpdateOnePipelineProgressMutationHookResult = ReturnType; +export type UpdateOnePipelineProgressMutationResult = Apollo.MutationResult; +export type UpdateOnePipelineProgressMutationOptions = Apollo.BaseMutationOptions; +export const CreateOnePipelineProgressDocument = gql` + mutation CreateOnePipelineProgress($uuid: String!, $entityType: PipelineProgressableType!, $entityId: String!, $pipelineId: String!, $pipelineStageId: String!) { + createOnePipelineProgress( + data: {id: $uuid, progressableType: $entityType, progressableId: $entityId, pipeline: {connect: {id: $pipelineId}}, pipelineStage: {connect: {id: $pipelineStageId}}} + ) { + id + } +} + `; +export type CreateOnePipelineProgressMutationFn = Apollo.MutationFunction; + +/** + * __useCreateOnePipelineProgressMutation__ + * + * To run a mutation, you first call `useCreateOnePipelineProgressMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateOnePipelineProgressMutation` 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 [createOnePipelineProgressMutation, { data, loading, error }] = useCreateOnePipelineProgressMutation({ + * variables: { + * uuid: // value for 'uuid' + * entityType: // value for 'entityType' + * entityId: // value for 'entityId' + * pipelineId: // value for 'pipelineId' + * pipelineStageId: // value for 'pipelineStageId' + * }, + * }); + */ +export function useCreateOnePipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateOnePipelineProgressDocument, options); + } +export type CreateOnePipelineProgressMutationHookResult = ReturnType; +export type CreateOnePipelineProgressMutationResult = Apollo.MutationResult; +export type CreateOnePipelineProgressMutationOptions = Apollo.BaseMutationOptions; +export const DeleteManyPipelineProgressDocument = gql` + mutation DeleteManyPipelineProgress($ids: [String!]) { + deleteManyPipelineProgress(where: {id: {in: $ids}}) { + count + } +} + `; +export type DeleteManyPipelineProgressMutationFn = Apollo.MutationFunction; + +/** + * __useDeleteManyPipelineProgressMutation__ + * + * To run a mutation, you first call `useDeleteManyPipelineProgressMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteManyPipelineProgressMutation` 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 [deleteManyPipelineProgressMutation, { data, loading, error }] = useDeleteManyPipelineProgressMutation({ + * variables: { + * ids: // value for 'ids' + * }, + * }); + */ +export function useDeleteManyPipelineProgressMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DeleteManyPipelineProgressDocument, options); + } +export type DeleteManyPipelineProgressMutationHookResult = ReturnType; +export type DeleteManyPipelineProgressMutationResult = Apollo.MutationResult; +export type DeleteManyPipelineProgressMutationOptions = Apollo.BaseMutationOptions; export const SearchPeopleDocument = gql` query SearchPeople($where: PersonWhereInput, $limit: Int, $orderBy: [PersonOrderByWithRelationInput!]) { searchResults: findManyPerson(where: $where, take: $limit, orderBy: $orderBy) { @@ -3005,13 +4232,14 @@ export type SearchCompanyQueryHookResult = ReturnType; export type SearchCompanyQueryResult = Apollo.QueryResult; export const GetCurrentUserDocument = gql` - query GetCurrentUser($uuid: String) { - users: findManyUser(where: {id: {equals: $uuid}}) { + query GetCurrentUser { + currentUser { id email displayName firstName lastName + avatarUrl workspaceMember { id workspace { @@ -3037,7 +4265,6 @@ export const GetCurrentUserDocument = gql` * @example * const { data, loading, error } = useGetCurrentUserQuery({ * variables: { - * uuid: // value for 'uuid' * }, * }); */ @@ -3090,38 +4317,78 @@ export function useGetUsersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions; export type GetUsersLazyQueryHookResult = ReturnType; export type GetUsersQueryResult = Apollo.QueryResult; - -export const GET_CLIENT_CONFIG = gql` - query GetClientConfig { - clientConfig { - display_google_login - prefill_login_with_seed - } +export const UpdateUserDocument = gql` + mutation UpdateUser($data: UserUpdateInput!, $where: UserWhereUniqueInput!) { + updateUser(data: $data, where: $where) { + id + email + displayName + firstName + lastName + avatarUrl } -`; - -export function useGetClientConfigQuery( - baseOptions?: Apollo.QueryHookOptions< - GetClientConfigQuery, - GetClientConfigQueryVariables - >, -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useQuery( - GET_CLIENT_CONFIG, - options, - ); } + `; +export type UpdateUserMutationFn = Apollo.MutationFunction; -export function useGetClientConfigLazyQuery( - baseOptions?: Apollo.LazyQueryHookOptions< - GetClientConfigQuery, - GetClientConfigQueryVariables - >, -) { - const options = { ...defaultOptions, ...baseOptions }; - return Apollo.useLazyQuery< - GetClientConfigQuery, - GetClientConfigQueryVariables - >(GET_CLIENT_CONFIG, options); -} \ No newline at end of file +/** + * __useUpdateUserMutation__ + * + * To run a mutation, you first call `useUpdateUserMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateUserMutation` 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 [updateUserMutation, { data, loading, error }] = useUpdateUserMutation({ + * variables: { + * data: // value for 'data' + * where: // value for 'where' + * }, + * }); + */ +export function useUpdateUserMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateUserDocument, options); + } +export type UpdateUserMutationHookResult = ReturnType; +export type UpdateUserMutationResult = Apollo.MutationResult; +export type UpdateUserMutationOptions = Apollo.BaseMutationOptions; +export const UpdateWorkspaceDocument = gql` + mutation UpdateWorkspace($data: WorkspaceUpdateInput!) { + updateWorkspace(data: $data) { + id + domainName + displayName + logo + } +} + `; +export type UpdateWorkspaceMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateWorkspaceMutation__ + * + * To run a mutation, you first call `useUpdateWorkspaceMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateWorkspaceMutation` 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 [updateWorkspaceMutation, { data, loading, error }] = useUpdateWorkspaceMutation({ + * variables: { + * data: // value for 'data' + * }, + * }); + */ +export function useUpdateWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateWorkspaceDocument, options); + } +export type UpdateWorkspaceMutationHookResult = ReturnType; +export type UpdateWorkspaceMutationResult = Apollo.MutationResult; +export type UpdateWorkspaceMutationOptions = Apollo.BaseMutationOptions; \ No newline at end of file diff --git a/front/src/modules/apollo/hooks/useApolloFactory.ts b/front/src/modules/apollo/hooks/useApolloFactory.ts index 793145ec4..f1670f051 100644 --- a/front/src/modules/apollo/hooks/useApolloFactory.ts +++ b/front/src/modules/apollo/hooks/useApolloFactory.ts @@ -1,9 +1,16 @@ import { useEffect, useMemo, useRef } from 'react'; -import { InMemoryCache, NormalizedCacheObject } from '@apollo/client'; +import { + ApolloLink, + InMemoryCache, + NormalizedCacheObject, +} from '@apollo/client'; import { useRecoilState } from 'recoil'; +import { isMockModeState } from '@/auth/states/isMockModeState'; import { tokenPairState } from '@/auth/states/tokenPairState'; import { CommentThreadTarget } from '~/generated/graphql'; +import { mockedCompaniesData } from '~/testing/mock-data/companies'; +import { mockedUsersData } from '~/testing/mock-data/users'; import { ApolloFactory } from '../services/apollo.factory'; @@ -11,8 +18,22 @@ export function useApolloFactory() { const apolloRef = useRef | null>(null); const [tokenPair, setTokenPair] = useRecoilState(tokenPairState); + const [isMockMode] = useRecoilState(isMockModeState); const apolloClient = useMemo(() => { + const mockLink = new ApolloLink((operation, forward) => { + return forward(operation).map((response) => { + if (operation.operationName === 'GetCompanies') { + return { data: { companies: mockedCompaniesData } }; + } + if (operation.operationName === 'GetCurrentUser') { + return { data: { currentUser: mockedUsersData[0] } }; + } + + return response; + }); + }); + apolloRef.current = new ApolloFactory({ uri: `${process.env.REACT_APP_API_URL}`, cache: new InMemoryCache({ @@ -42,10 +63,11 @@ export function useApolloFactory() { onUnauthenticatedError() { setTokenPair(null); }, + extraLinks: isMockMode ? [mockLink] : [], }); return apolloRef.current.getClient(); - }, [setTokenPair]); + }, [isMockMode, setTokenPair]); useEffect(() => { if (apolloRef.current) { diff --git a/front/src/modules/apollo/hooks/useApolloMocked.ts b/front/src/modules/apollo/hooks/useApolloMocked.ts deleted file mode 100644 index 91b706db4..000000000 --- a/front/src/modules/apollo/hooks/useApolloMocked.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { useMemo } from 'react'; -import { - ApolloClient, - ApolloLink, - createHttpLink, - from, - InMemoryCache, -} from '@apollo/client'; - -import { mockedCompaniesData } from '~/testing/mock-data/companies'; -import { mockedUsersData } from '~/testing/mock-data/users'; - -export default function useApolloMocked() { - const mockedClient = useMemo(() => { - const apiLink = createHttpLink({ - uri: `${process.env.REACT_APP_API_URL}`, - }); - - const mockLink = new ApolloLink((operation, forward) => { - return forward(operation).map((response) => { - if (operation.operationName === 'GetCompanies') { - return { data: { companies: mockedCompaniesData } }; - } - if (operation.operationName === 'GetCurrentUser') { - return { data: { users: [mockedUsersData[0]] } }; - } - - return response; - }); - }); - - return new ApolloClient({ - link: from([mockLink, apiLink]), - cache: new InMemoryCache(), - defaultOptions: { - query: { - fetchPolicy: 'cache-first', - }, - }, - }); - }, []); - - return mockedClient; -} diff --git a/front/src/modules/apollo/services/apollo.factory.ts b/front/src/modules/apollo/services/apollo.factory.ts index f89543b56..3ff9a8bfc 100644 --- a/front/src/modules/apollo/services/apollo.factory.ts +++ b/front/src/modules/apollo/services/apollo.factory.ts @@ -11,31 +11,24 @@ import { GraphQLErrors } from '@apollo/client/errors'; import { setContext } from '@apollo/client/link/context'; import { onError } from '@apollo/client/link/error'; import { RetryLink } from '@apollo/client/link/retry'; -import { Observable } from '@apollo/client/utilities'; import { renewToken } from '@/auth/services/AuthService'; import { AuthTokenPair } from '~/generated/graphql'; import { loggerLink } from '../../utils/apollo-logger'; import { assertNotNull } from '../../utils/assert'; -import { promiseToObservable } from '../../utils/promise-to-observable'; import { ApolloManager } from '../interfaces/apolloManager.interface'; const logger = loggerLink(() => 'Twenty'); let isRefreshing = false; -let pendingRequests: (() => void)[] = []; - -const resolvePendingRequests = () => { - pendingRequests.map((callback) => callback()); - pendingRequests = []; -}; export interface Options extends ApolloClientOptions { onError?: (err: GraphQLErrors | undefined) => void; onNetworkError?: (err: Error | ServerParseError | ServerError) => void; onTokenPairChange?: (tokenPair: AuthTokenPair) => void; onUnauthenticatedError?: () => void; + extraLinks?: ApolloLink[]; } export class ApolloFactory implements ApolloManager { @@ -49,6 +42,7 @@ export class ApolloFactory implements ApolloManager { onNetworkError, onTokenPairChange, onUnauthenticatedError, + extraLinks, ...options } = opts; @@ -86,38 +80,22 @@ export class ApolloFactory implements ApolloManager { for (const graphQLError of graphQLErrors) { switch (graphQLError?.extensions?.code) { case 'UNAUTHENTICATED': { - // error code is set to UNAUTHENTICATED - // when AuthenticationError thrown in resolver - let forward$: Observable; - if (!isRefreshing) { isRefreshing = true; - forward$ = promiseToObservable( - renewToken(uri, this.tokenPair) - .then((tokens) => { - onTokenPairChange?.(tokens); - resolvePendingRequests(); - return true; - }) - .catch(() => { - pendingRequests = []; - onUnauthenticatedError?.(); - return false; - }) - .finally(() => { - isRefreshing = false; - }), - ).filter((value) => Boolean(value)); - } else { - // Will only emit once the Promise is resolved - forward$ = promiseToObservable( - new Promise((resolve) => { - pendingRequests.push(() => resolve(true)); - }), - ); + renewToken(uri, this.tokenPair) + .then((tokens) => { + onTokenPairChange?.(tokens); + return true; + }) + .catch(() => { + onUnauthenticatedError?.(); + return false; + }) + .finally(() => { + isRefreshing = false; + }); } - - return forward$.flatMap(() => forward(operation)); + return forward(operation); } default: if (process.env.NODE_ENV === 'development') { @@ -148,6 +126,7 @@ export class ApolloFactory implements ApolloManager { [ errorLink, authLink, + ...(extraLinks ? extraLinks : []), // Only show logger in dev mode process.env.NODE_ENV !== 'production' ? logger : null, retryLink, diff --git a/front/src/modules/auth/components/RequireAuth.tsx b/front/src/modules/auth/components/RequireAuth.tsx deleted file mode 100644 index 7c4692b25..000000000 --- a/front/src/modules/auth/components/RequireAuth.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { keyframes } from '@emotion/react'; -import styled from '@emotion/styled'; - -import { useIsLogged } from '../hooks/useIsLogged'; - -const EmptyContainer = styled.div` - align-items: center; - display: flex; - height: 100%; - justify-content: center; - width: 100%; -`; - -const fadeIn = keyframes` - from { - opacity: 0; - } - to { - opacity: 1; - } -`; - -const FadeInStyle = styled.div` - animation: ${fadeIn} 1s forwards; - opacity: 0; -`; - -export function RequireAuth({ - children, -}: { - children: JSX.Element; -}): JSX.Element { - const navigate = useNavigate(); - - const isLogged = useIsLogged(); - - useEffect(() => { - if (!isLogged) { - navigate('/auth'); - } - }, [isLogged, navigate]); - - if (!isLogged) { - return ( - - - Please hold on a moment, we're directing you to our login page... - - - ); - } - - return children; -} diff --git a/front/src/modules/auth/components/RequireOnboarded.tsx b/front/src/modules/auth/components/RequireOnboarded.tsx new file mode 100644 index 000000000..8b05ec357 --- /dev/null +++ b/front/src/modules/auth/components/RequireOnboarded.tsx @@ -0,0 +1,83 @@ +import { useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { keyframes } from '@emotion/react'; +import styled from '@emotion/styled'; +import { useRecoilState } from 'recoil'; + +import { captureHotkeyTypeInFocusState } from '@/hotkeys/states/captureHotkeyTypeInFocusState'; + +import { useOnboardingStatus } from '../hooks/useOnboardingStatus'; +import { OnboardingStatus } from '../utils/getOnboardingStatus'; + +const EmptyContainer = styled.div` + align-items: center; + display: flex; + height: 100%; + justify-content: center; + width: 100%; +`; + +const fadeIn = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + +const FadeInStyle = styled.div` + animation: ${fadeIn} 1s forwards; + opacity: 0; +`; + +export function RequireOnboarded({ + children, +}: { + children: JSX.Element; +}): JSX.Element { + const navigate = useNavigate(); + + const [, setCaptureHotkeyTypeInFocus] = useRecoilState( + captureHotkeyTypeInFocusState, + ); + const onboardingStatus = useOnboardingStatus(); + + useEffect(() => { + if (onboardingStatus === OnboardingStatus.OngoingUserCreation) { + navigate('/auth'); + } else if (onboardingStatus === OnboardingStatus.OngoingWorkspaceCreation) { + navigate('/auth/create/workspace'); + } else if (onboardingStatus === OnboardingStatus.OngoingProfileCreation) { + navigate('/auth/create/profile'); + } + }, [onboardingStatus, navigate]); + + useEffect(() => { + if (onboardingStatus === OnboardingStatus.Completed) { + setCaptureHotkeyTypeInFocus(false); + } + }, [setCaptureHotkeyTypeInFocus, onboardingStatus]); + + if (onboardingStatus !== OnboardingStatus.Completed) { + return ( + + + {onboardingStatus === OnboardingStatus.OngoingUserCreation && ( +
+ Please hold on a moment, we're directing you to our login page... +
+ )} + {onboardingStatus !== OnboardingStatus.OngoingUserCreation && ( +
+ Please hold on a moment, we're directing you to our onboarding + flow... +
+ )} +
+
+ ); + } + + return children; +} diff --git a/front/src/modules/auth/components/RequireNotAuth.tsx b/front/src/modules/auth/components/RequireOnboarding.tsx similarity index 69% rename from front/src/modules/auth/components/RequireNotAuth.tsx rename to front/src/modules/auth/components/RequireOnboarding.tsx index 494bd296f..93aa215a1 100644 --- a/front/src/modules/auth/components/RequireNotAuth.tsx +++ b/front/src/modules/auth/components/RequireOnboarding.tsx @@ -3,7 +3,8 @@ import { useNavigate } from 'react-router-dom'; import { keyframes } from '@emotion/react'; import styled from '@emotion/styled'; -import { useIsLogged } from '../hooks/useIsLogged'; +import { useOnboardingStatus } from '../hooks/useOnboardingStatus'; +import { OnboardingStatus } from '../utils/getOnboardingStatus'; const EmptyContainer = styled.div` align-items: center; @@ -27,22 +28,22 @@ const FadeInStyle = styled.div` opacity: 0; `; -export function RequireNotAuth({ +export function RequireOnboarding({ children, }: { children: JSX.Element; }): JSX.Element { const navigate = useNavigate(); - const isLogged = useIsLogged(); + const onboardingStatus = useOnboardingStatus(); useEffect(() => { - if (isLogged) { + if (onboardingStatus === OnboardingStatus.Completed) { navigate('/'); } - }, [isLogged, navigate]); + }, [navigate, onboardingStatus]); - if (isLogged) { + if (onboardingStatus === OnboardingStatus.Completed) { return ( diff --git a/front/src/modules/auth/hooks/useFetchCurrentUser.ts b/front/src/modules/auth/hooks/useFetchCurrentUser.ts deleted file mode 100644 index 30a2de89c..000000000 --- a/front/src/modules/auth/hooks/useFetchCurrentUser.ts +++ /dev/null @@ -1,13 +0,0 @@ -import jwt from 'jwt-decode'; - -import { AuthTokenPair, useGetCurrentUserQuery } from '~/generated/graphql'; - -export function useFetchCurrentUser(tokenPair: AuthTokenPair | null) { - const userId = tokenPair?.accessToken.token - ? jwt<{ sub: string }>(tokenPair.accessToken.token).sub - : null; - const { data } = useGetCurrentUserQuery({ - variables: { uuid: userId }, - }); - return data?.users?.[0]; -} diff --git a/front/src/modules/auth/hooks/useOnboardingStatus.ts b/front/src/modules/auth/hooks/useOnboardingStatus.ts new file mode 100644 index 000000000..5b9d8499f --- /dev/null +++ b/front/src/modules/auth/hooks/useOnboardingStatus.ts @@ -0,0 +1,20 @@ +import { useMemo } from 'react'; +import { useRecoilState } from 'recoil'; + +import { useIsLogged } from '../hooks/useIsLogged'; +import { currentUserState } from '../states/currentUserState'; +import { + getOnboardingStatus, + OnboardingStatus, +} from '../utils/getOnboardingStatus'; + +export function useOnboardingStatus(): OnboardingStatus { + const [currentUser] = useRecoilState(currentUserState); + const isLoggedIn = useIsLogged(); + const onboardingStatus = useMemo( + () => getOnboardingStatus(isLoggedIn, currentUser), + [currentUser, isLoggedIn], + ); + + return onboardingStatus; +} diff --git a/front/src/modules/auth/states/currentUserState.ts b/front/src/modules/auth/states/currentUserState.ts index 4402a67d3..54aeceb25 100644 --- a/front/src/modules/auth/states/currentUserState.ts +++ b/front/src/modules/auth/states/currentUserState.ts @@ -1,14 +1,8 @@ import { atom } from 'recoil'; -import { User, Workspace, WorkspaceMember } from '~/generated/graphql'; +import { GetCurrentUserQuery } from '~/generated/graphql'; -type CurrentUser = Pick & { - workspaceMember?: - | (Pick & { - workspace: Pick; - }) - | null; -}; +export type CurrentUser = GetCurrentUserQuery['currentUser']; export const currentUserState = atom({ key: 'currentUserState', diff --git a/front/src/modules/auth/utils/getOnboardingStatus.ts b/front/src/modules/auth/utils/getOnboardingStatus.ts new file mode 100644 index 000000000..deb2d7dc7 --- /dev/null +++ b/front/src/modules/auth/utils/getOnboardingStatus.ts @@ -0,0 +1,25 @@ +import { CurrentUser } from '../states/currentUserState'; + +export enum OnboardingStatus { + OngoingUserCreation = 'ongoing_user_creation', + OngoingWorkspaceCreation = 'ongoing_workspace_creation', + OngoingProfileCreation = 'ongoing_profile_creation', + Completed = 'completed', +} + +export function getOnboardingStatus( + isLoggedIn: boolean, + currentUser: CurrentUser | null, +) { + if (!isLoggedIn || !currentUser) { + return OnboardingStatus.OngoingUserCreation; + } + if (!currentUser.workspaceMember?.workspace.displayName) { + return OnboardingStatus.OngoingWorkspaceCreation; + } + if (!currentUser.firstName || !currentUser.lastName) { + return OnboardingStatus.OngoingProfileCreation; + } + + return OnboardingStatus.Completed; +} diff --git a/front/src/modules/pipeline-progress/components/BoardActionBarButtonDeletePipelineProgress.tsx b/front/src/modules/pipeline-progress/components/BoardActionBarButtonDeletePipelineProgress.tsx index eba747e55..86aabd26f 100644 --- a/front/src/modules/pipeline-progress/components/BoardActionBarButtonDeletePipelineProgress.tsx +++ b/front/src/modules/pipeline-progress/components/BoardActionBarButtonDeletePipelineProgress.tsx @@ -26,8 +26,6 @@ export function BoardActionBarButtonDeletePipelineProgress() { }, }); - console.log('boardItems', boardItems); - setBoardItems( Object.fromEntries( Object.entries(boardItems).filter( diff --git a/front/src/modules/relation-picker/components/MultipleEntitySelect.tsx b/front/src/modules/relation-picker/components/MultipleEntitySelect.tsx index ef8bf5fa5..53b47d4f9 100644 --- a/front/src/modules/relation-picker/components/MultipleEntitySelect.tsx +++ b/front/src/modules/relation-picker/components/MultipleEntitySelect.tsx @@ -1,4 +1,4 @@ -import { debounce } from 'lodash'; +import debounce from 'lodash.debounce'; import { EntityForSelect } from '@/relation-picker/types/EntityForSelect'; import { DropdownMenu } from '@/ui/components/menu/DropdownMenu'; diff --git a/front/src/modules/relation-picker/hooks/useEntitySelectSearch.ts b/front/src/modules/relation-picker/hooks/useEntitySelectSearch.ts index 299d38206..512c4e223 100644 --- a/front/src/modules/relation-picker/hooks/useEntitySelectSearch.ts +++ b/front/src/modules/relation-picker/hooks/useEntitySelectSearch.ts @@ -1,4 +1,4 @@ -import { debounce } from 'lodash'; +import debounce from 'lodash.debounce'; import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState'; diff --git a/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts b/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts index 13c0986fc..9f62ec8b6 100644 --- a/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts +++ b/front/src/modules/relation-picker/hooks/useFilteredSearchEntityQuery.ts @@ -12,7 +12,11 @@ import { type SelectStringKeys = NonNullable< { - [K in keyof T]: T[K] extends string ? K : never; + [K in keyof T]: K extends '__typename' + ? never + : T[K] extends string | undefined | null + ? K + : never; }[keyof T] >; diff --git a/front/src/modules/users/services/index.ts b/front/src/modules/users/services/index.ts index b26cf6918..d0d8e2c85 100644 --- a/front/src/modules/users/services/index.ts +++ b/front/src/modules/users/services/index.ts @@ -1,13 +1,15 @@ import { gql } from '@apollo/client'; +export * from './update'; export const GET_CURRENT_USER = gql` - query GetCurrentUser($uuid: String) { - users: findManyUser(where: { id: { equals: $uuid } }) { + query GetCurrentUser { + currentUser { id email displayName firstName lastName + avatarUrl workspaceMember { id workspace { diff --git a/front/src/modules/users/services/update.ts b/front/src/modules/users/services/update.ts new file mode 100644 index 000000000..9dbae1a9c --- /dev/null +++ b/front/src/modules/users/services/update.ts @@ -0,0 +1,14 @@ +import { gql } from '@apollo/client'; + +export const UPDATE_USER = gql` + mutation UpdateUser($data: UserUpdateInput!, $where: UserWhereUniqueInput!) { + updateUser(data: $data, where: $where) { + id + email + displayName + firstName + lastName + avatarUrl + } + } +`; diff --git a/front/src/modules/workspace/services/index.ts b/front/src/modules/workspace/services/index.ts new file mode 100644 index 000000000..c37c258c7 --- /dev/null +++ b/front/src/modules/workspace/services/index.ts @@ -0,0 +1 @@ +export * from './update'; diff --git a/front/src/modules/workspace/services/update.ts b/front/src/modules/workspace/services/update.ts new file mode 100644 index 000000000..8ed42c7a2 --- /dev/null +++ b/front/src/modules/workspace/services/update.ts @@ -0,0 +1,12 @@ +import { gql } from '@apollo/client'; + +export const UPDATE_WORKSPACE = gql` + mutation UpdateWorkspace($data: WorkspaceUpdateInput!) { + updateWorkspace(data: $data) { + id + domainName + displayName + logo + } + } +`; diff --git a/front/src/pages/auth/CreateProfile.tsx b/front/src/pages/auth/CreateProfile.tsx index fe6fe33b6..873000f2f 100644 --- a/front/src/pages/auth/CreateProfile.tsx +++ b/front/src/pages/auth/CreateProfile.tsx @@ -1,14 +1,22 @@ -import { useCallback } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useNavigate } from 'react-router-dom'; +import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; +import { useRecoilState } from 'recoil'; import { SubTitle } from '@/auth/components/ui/SubTitle'; import { Title } from '@/auth/components/ui/Title'; +import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; +import { currentUserState } from '@/auth/states/currentUserState'; +import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; +import { captureHotkeyTypeInFocusState } from '@/hotkeys/states/captureHotkeyTypeInFocusState'; import { MainButton } from '@/ui/components/buttons/MainButton'; import { ImageInput } from '@/ui/components/inputs/ImageInput'; import { TextInput } from '@/ui/components/inputs/TextInput'; import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle'; +import { GET_CURRENT_USER } from '@/users/services'; +import { useUpdateUserMutation } from '~/generated/graphql'; const StyledContentContainer = styled.div` width: 100%; @@ -37,10 +45,58 @@ const StyledComboInputContainer = styled.div` export function CreateProfile() { const navigate = useNavigate(); + const onboardingStatus = useOnboardingStatus(); + + const [currentUser] = useRecoilState(currentUserState); + const [, setCaptureHotkeyTypeInFocus] = useRecoilState( + captureHotkeyTypeInFocusState, + ); + + const [updateUser] = useUpdateUserMutation(); + + const [firstName, setFirstName] = useState(''); + const [lastName, setLastName] = useState(''); const handleCreate = useCallback(async () => { - navigate('/'); - }, [navigate]); + try { + if (!currentUser?.id) { + throw new Error('User is not logged in'); + } + + const { data, errors } = await updateUser({ + variables: { + where: { + id: currentUser?.id, + }, + data: { + firstName: { + set: firstName, + }, + lastName: { + set: lastName, + }, + }, + }, + refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''], + }); + + if (errors || !data?.updateUser) { + throw errors; + } + + setCaptureHotkeyTypeInFocus(false); + navigate('/'); + } catch (error) { + console.error(error); + } + }, [ + currentUser?.id, + firstName, + lastName, + navigate, + setCaptureHotkeyTypeInFocus, + updateUser, + ]); useHotkeys( 'enter', @@ -54,10 +110,20 @@ export function CreateProfile() { [handleCreate], ); + useEffect(() => { + if (onboardingStatus !== OnboardingStatus.OngoingProfileCreation) { + navigate('/'); + } + }, [onboardingStatus, navigate]); + + useEffect(() => { + setCaptureHotkeyTypeInFocus(true); + }, [setCaptureHotkeyTypeInFocus]); + return ( <> Create profile - How you'll be identify on the app. + How you'll be identified on the app. @@ -71,21 +137,28 @@ export function CreateProfile() { - + ); diff --git a/front/src/pages/auth/CreateWorkspace.tsx b/front/src/pages/auth/CreateWorkspace.tsx index 93a6f4471..6bcea161f 100644 --- a/front/src/pages/auth/CreateWorkspace.tsx +++ b/front/src/pages/auth/CreateWorkspace.tsx @@ -1,14 +1,19 @@ -import { useCallback } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useNavigate } from 'react-router-dom'; +import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; import { SubTitle } from '@/auth/components/ui/SubTitle'; import { Title } from '@/auth/components/ui/Title'; +import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; +import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; import { MainButton } from '@/ui/components/buttons/MainButton'; import { ImageInput } from '@/ui/components/inputs/ImageInput'; import { TextInput } from '@/ui/components/inputs/TextInput'; import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle'; +import { GET_CURRENT_USER } from '@/users/services'; +import { useUpdateWorkspaceMutation } from '~/generated/graphql'; const StyledContentContainer = styled.div` width: 100%; @@ -29,10 +34,38 @@ const StyledButtonContainer = styled.div` export function CreateWorkspace() { const navigate = useNavigate(); + const onboardingStatus = useOnboardingStatus(); + + const [workspaceName, setWorkspaceName] = useState(''); + + const [updateWorkspace] = useUpdateWorkspaceMutation(); const handleCreate = useCallback(async () => { - navigate('/auth/create/profile'); - }, [navigate]); + try { + if (!workspaceName) { + throw new Error('Workspace name is required'); + } + + const { data, errors } = await updateWorkspace({ + variables: { + data: { + displayName: { + set: workspaceName, + }, + }, + }, + refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''], + }); + + if (errors || !data?.updateWorkspace) { + throw errors; + } + + navigate('/auth/create/profile'); + } catch (error) { + console.error(error); + } + }, [navigate, updateWorkspace, workspaceName]); useHotkeys( 'enter', @@ -46,6 +79,12 @@ export function CreateWorkspace() { [handleCreate], ); + useEffect(() => { + if (onboardingStatus !== OnboardingStatus.OngoingWorkspaceCreation) { + navigate('/auth/create/profile'); + } + }, [onboardingStatus, navigate]); + return ( <> Create your workspace @@ -63,11 +102,21 @@ export function CreateWorkspace() { title="Workspace name" description="The name of your organization" /> - + - + ); diff --git a/front/src/pages/auth/PasswordLogin.tsx b/front/src/pages/auth/PasswordLogin.tsx index 397aa0fef..661ee61cf 100644 --- a/front/src/pages/auth/PasswordLogin.tsx +++ b/front/src/pages/auth/PasswordLogin.tsx @@ -1,5 +1,6 @@ import { useCallback, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; +import { useNavigate } from 'react-router-dom'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; import { useRecoilState } from 'recoil'; @@ -10,7 +11,6 @@ import { Title } from '@/auth/components/ui/Title'; import { useAuth } from '@/auth/hooks/useAuth'; import { authFlowUserEmailState } from '@/auth/states/authFlowUserEmailState'; import { isMockModeState } from '@/auth/states/isMockModeState'; -import { captureHotkeyTypeInFocusState } from '@/hotkeys/states/captureHotkeyTypeInFocusState'; import { MainButton } from '@/ui/components/buttons/MainButton'; import { TextInput } from '@/ui/components/inputs/TextInput'; import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle'; @@ -47,17 +47,15 @@ const StyledErrorContainer = styled.div` `; export function PasswordLogin() { - const [, setMockMode] = useRecoilState(isMockModeState); - const [, setCaptureHotkeyTypeInFocus] = useRecoilState( - captureHotkeyTypeInFocusState, - ); + const navigate = useNavigate(); const prefillPassword = - process.env.NODE_ENV === 'development' ? 'applecar2025' : ''; + process.env.NODE_ENV === 'development' ? 'Applecar2025' : ''; const [authFlowUserEmail, setAuthFlowUserEmail] = useRecoilState( authFlowUserEmailState, ); + const [, setMockMode] = useRecoilState(isMockModeState); const [internalPassword, setInternalPassword] = useState(prefillPassword); const [formError, setFormError] = useState(''); @@ -65,21 +63,15 @@ export function PasswordLogin() { const handleLogin = useCallback(async () => { try { - await login(authFlowUserEmail, internalPassword); setMockMode(false); - setCaptureHotkeyTypeInFocus(false); - // TODO: Navigate to the workspace selection page when it's ready - // navigate('/auth/create/workspace'); + + await login(authFlowUserEmail, internalPassword); + + navigate('/auth/create/workspace'); } catch (err: any) { setFormError(err.message); } - }, [ - authFlowUserEmail, - internalPassword, - login, - setMockMode, - setCaptureHotkeyTypeInFocus, - ]); + }, [login, authFlowUserEmail, internalPassword, setMockMode, navigate]); useHotkeys( 'enter', diff --git a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx index b2061d988..9d5183094 100644 --- a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx @@ -23,7 +23,7 @@ export const FilterByName: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const filterButton = canvas.getByText('Filter'); + const filterButton = await canvas.findByText('Filter'); await userEvent.click(filterButton); const nameFilterButton = canvas @@ -60,7 +60,7 @@ export const FilterByAccountOwner: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const filterButton = canvas.getByText('Filter'); + const filterButton = await canvas.findByText('Filter'); await userEvent.click(filterButton); const accountOwnerFilterButton = ( @@ -83,7 +83,6 @@ export const FilterByAccountOwner: Story = { const charlesChip = canvas .getAllByTestId('dropdown-menu-item') .find((item) => { - console.log({ item }); return item.textContent?.includes('Charles Test'); }); diff --git a/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx index d8f911538..1fc2bba2c 100644 --- a/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.sortBy.stories.tsx @@ -21,7 +21,7 @@ export const SortByName: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const sortButton = canvas.getByText('Sort'); + const sortButton = await canvas.findByText('Sort'); await userEvent.click(sortButton); const nameSortButton = canvas.getByText('Name', { selector: 'li' }); diff --git a/front/src/pages/people/__stories__/People.filterBy.stories.tsx b/front/src/pages/people/__stories__/People.filterBy.stories.tsx index 727c3b011..d95107b93 100644 --- a/front/src/pages/people/__stories__/People.filterBy.stories.tsx +++ b/front/src/pages/people/__stories__/People.filterBy.stories.tsx @@ -23,7 +23,7 @@ export const Email: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const filterButton = canvas.getByText('Filter'); + const filterButton = await canvas.findByText('Filter'); await userEvent.click(filterButton); const emailFilterButton = canvas @@ -59,7 +59,7 @@ export const CompanyName: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const filterButton = canvas.getByText('Filter'); + const filterButton = await canvas.findByText('Filter'); await userEvent.click(filterButton); const companyFilterButton = canvas diff --git a/front/src/pages/people/__stories__/People.sortBy.stories.tsx b/front/src/pages/people/__stories__/People.sortBy.stories.tsx index c600c05ee..6769d10e9 100644 --- a/front/src/pages/people/__stories__/People.sortBy.stories.tsx +++ b/front/src/pages/people/__stories__/People.sortBy.stories.tsx @@ -22,7 +22,7 @@ export const Email: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const sortButton = canvas.getByText('Sort'); + const sortButton = await canvas.findByText('Sort'); await userEvent.click(sortButton); const emailSortButton = canvas.getByText('Email', { selector: 'li' }); @@ -48,7 +48,7 @@ export const Cancel: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - const sortButton = canvas.getByText('Sort'); + const sortButton = await canvas.findByText('Sort'); await userEvent.click(sortButton); const emailSortButton = canvas.getByText('Email', { selector: 'li' }); diff --git a/front/src/pages/settings/SettingsProfile.tsx b/front/src/pages/settings/SettingsProfile.tsx index 863127c0f..ccb332dd6 100644 --- a/front/src/pages/settings/SettingsProfile.tsx +++ b/front/src/pages/settings/SettingsProfile.tsx @@ -1,4 +1,7 @@ +import { useEffect, useState } from 'react'; +import { getOperationName } from '@apollo/client/utilities'; import styled from '@emotion/styled'; +import debounce from 'lodash.debounce'; import { useRecoilValue } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; @@ -7,6 +10,8 @@ import { TextInput } from '@/ui/components/inputs/TextInput'; import { MainSectionTitle } from '@/ui/components/section-titles/MainSectionTitle'; import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle'; import { NoTopBarContainer } from '@/ui/layout/containers/NoTopBarContainer'; +import { GET_CURRENT_USER } from '@/users/services'; +import { useUpdateUserMutation } from '~/generated/graphql'; const StyledContainer = styled.div` display: flex; @@ -34,6 +39,57 @@ const StyledComboInputContainer = styled.div` export function SettingsProfile() { const currentUser = useRecoilValue(currentUserState); + + const [firstName, setFirstName] = useState(currentUser?.firstName ?? ''); + const [lastName, setLastName] = useState(currentUser?.lastName ?? ''); + + const [updateUser] = useUpdateUserMutation(); + + // TODO: Enhance this with react-hook-form (https://www.react-hook-form.com) + const debouncedUpdate = debounce(async () => { + try { + if (!currentUser?.id) { + throw new Error('User is not logged in'); + } + + const { data, errors } = await updateUser({ + variables: { + where: { + id: currentUser?.id, + }, + data: { + firstName: { + set: firstName, + }, + lastName: { + set: lastName, + }, + }, + }, + refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''], + }); + + if (errors || !data?.updateUser) { + throw errors; + } + } catch (error) { + console.error(error); + } + }, 500); + + useEffect(() => { + if ( + currentUser?.firstName !== firstName || + currentUser?.lastName !== lastName + ) { + debouncedUpdate(); + } + + return () => { + debouncedUpdate.cancel(); + }; + }, [firstName, lastName, currentUser, debouncedUpdate]); + return ( @@ -50,13 +106,15 @@ export function SettingsProfile() { diff --git a/front/src/providers/apollo/ApolloProvider.tsx b/front/src/providers/apollo/ApolloProvider.tsx index f6fef0b05..dded3a368 100644 --- a/front/src/providers/apollo/ApolloProvider.tsx +++ b/front/src/providers/apollo/ApolloProvider.tsx @@ -1,19 +1,11 @@ import { ApolloProvider as ApolloProviderBase } from '@apollo/client'; -import { useRecoilState } from 'recoil'; import { useApolloFactory } from '@/apollo/hooks/useApolloFactory'; -import useApolloMocked from '@/apollo/hooks/useApolloMocked'; -import { isMockModeState } from '@/auth/states/isMockModeState'; export function ApolloProvider({ children }: React.PropsWithChildren) { const apolloClient = useApolloFactory(); - const mockedClient = useApolloMocked(); - - const [isMockMode] = useRecoilState(isMockModeState); return ( - - {children} - + {children} ); } diff --git a/front/src/providers/user/UserProvider.tsx b/front/src/providers/user/UserProvider.tsx index eaa7faddc..6811ef4cd 100644 --- a/front/src/providers/user/UserProvider.tsx +++ b/front/src/providers/user/UserProvider.tsx @@ -1,20 +1,18 @@ import { useEffect } from 'react'; import { useRecoilState } from 'recoil'; -import { useFetchCurrentUser } from '@/auth/hooks/useFetchCurrentUser'; import { currentUserState } from '@/auth/states/currentUserState'; -import { tokenPairState } from '@/auth/states/tokenPairState'; +import { useGetCurrentUserQuery } from '~/generated/graphql'; export function UserProvider({ children }: React.PropsWithChildren) { const [, setCurrentUser] = useRecoilState(currentUserState); - const [tokenPair] = useRecoilState(tokenPairState); - const user = useFetchCurrentUser(tokenPair); + const { data, loading } = useGetCurrentUserQuery(); useEffect(() => { - if (user) { - setCurrentUser(user); + if (data?.currentUser) { + setCurrentUser(data?.currentUser); } - }, [setCurrentUser, user]); + }, [setCurrentUser, data]); - return <>{children}; + return loading ? <> : <>{children}; } diff --git a/front/src/testing/graphqlMocks.ts b/front/src/testing/graphqlMocks.ts index 7eec45908..9b1451eff 100644 --- a/front/src/testing/graphqlMocks.ts +++ b/front/src/testing/graphqlMocks.ts @@ -75,7 +75,7 @@ export const graphqlMocks = [ graphql.query(getOperationName(GET_CURRENT_USER) ?? '', (req, res, ctx) => { return res( ctx.data({ - users: [mockedUsersData[0]], + currentUser: mockedUsersData[0], }), ); }), diff --git a/front/src/testing/mock-data/users.ts b/front/src/testing/mock-data/users.ts index fccfbfd39..079b75ae8 100644 --- a/front/src/testing/mock-data/users.ts +++ b/front/src/testing/mock-data/users.ts @@ -20,7 +20,7 @@ type MockedUser = Pick< export const mockedUsersData: Array = [ { - id: '374fe3a5-df1e-4119-afe0-2a62a2ba481e', + id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', __typename: 'User', email: 'charles@test.com', displayName: 'Charles Test', diff --git a/front/yarn.lock b/front/yarn.lock index ad6acc968..a886ad4e7 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -4963,7 +4963,14 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash@^4.14.167": +"@types/lodash.debounce@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.7.tgz#0285879defb7cdb156ae633cecd62d5680eded9f" + integrity sha512-X1T4wMZ+gT000M2/91SYj0d/7JfeNZ9PeeOldSNoE/lunLeQXKvkmIumI29IaKMotU/ln/McOIvgzZcQ/3TrSA== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.14.167": version "4.14.195" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.195.tgz#bafc975b252eb6cea78882ce8a7b6bf22a6de632" integrity sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg== diff --git a/server/.env.example b/server/.env.example index f01f16cbc..855f68005 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,3 +1,5 @@ +DEBUG_MODE=false +AUTH_GOOGLE_ENABLED=false ACCESS_TOKEN_SECRET=secret_jwt ACCESS_TOKEN_EXPIRES_IN=5m LOGIN_TOKEN_SECRET=secret_login_token diff --git a/server/package.json b/server/package.json index fd556def0..0f2457982 100644 --- a/server/package.json +++ b/server/package.json @@ -22,9 +22,10 @@ "prisma:generate-client": "npx prisma generate --generator client && yarn prisma:generate-gql-select", "prisma:generate-gql-select": "node scripts/generate-model-select-map.js", "prisma:generate-nest-graphql": "npx prisma generate --generator nestgraphql", + "prisma:generate": "yarn prisma:generate-client && yarn prisma:generate-gql-select && yarn prisma:generate-nest-graphql", "prisma:migrate": "npx prisma migrate deploy", "prisma:seed": "npx prisma db seed", - "prisma:reset": "npx prisma migrate reset" + "prisma:reset": "npx prisma migrate reset && yarn prisma:generate" }, "dependencies": { "@apollo/server": "^4.7.3", @@ -101,6 +102,7 @@ "prettier": "^2.3.2", "prisma": "^4.13.0", "prisma-nestjs-graphql": "^18.0.2", + "prisma-query-log": "^3.2.0", "source-map-support": "^0.5.20", "supertest": "^6.1.3", "ts-jest": "28.0.8", diff --git a/server/src/core/@generated/user/user-create-many.input.ts b/server/src/core/@generated/user/user-create-many.input.ts index b66f5263c..de3890076 100644 --- a/server/src/core/@generated/user/user-create-many.input.ts +++ b/server/src/core/@generated/user/user-create-many.input.ts @@ -12,13 +12,15 @@ export class UserCreateManyInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-create-without-comments.input.ts b/server/src/core/@generated/user/user-create-without-comments.input.ts index 2820973bc..092db2744 100644 --- a/server/src/core/@generated/user/user-create-without-comments.input.ts +++ b/server/src/core/@generated/user/user-create-without-comments.input.ts @@ -15,13 +15,15 @@ export class UserCreateWithoutCommentsInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-create-without-companies.input.ts b/server/src/core/@generated/user/user-create-without-companies.input.ts index 05725e78b..a03de9539 100644 --- a/server/src/core/@generated/user/user-create-without-companies.input.ts +++ b/server/src/core/@generated/user/user-create-without-companies.input.ts @@ -15,13 +15,15 @@ export class UserCreateWithoutCompaniesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-create-without-refresh-tokens.input.ts b/server/src/core/@generated/user/user-create-without-refresh-tokens.input.ts index 2de51bc82..0224711f0 100644 --- a/server/src/core/@generated/user/user-create-without-refresh-tokens.input.ts +++ b/server/src/core/@generated/user/user-create-without-refresh-tokens.input.ts @@ -15,13 +15,15 @@ export class UserCreateWithoutRefreshTokensInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-create-without-workspace-member.input.ts b/server/src/core/@generated/user/user-create-without-workspace-member.input.ts index 53bbbe4cb..267c3aec3 100644 --- a/server/src/core/@generated/user/user-create-without-workspace-member.input.ts +++ b/server/src/core/@generated/user/user-create-without-workspace-member.input.ts @@ -15,13 +15,15 @@ export class UserCreateWithoutWorkspaceMemberInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-create.input.ts b/server/src/core/@generated/user/user-create.input.ts index ffd550aa2..16910b681 100644 --- a/server/src/core/@generated/user/user-create.input.ts +++ b/server/src/core/@generated/user/user-create.input.ts @@ -16,13 +16,15 @@ export class UserCreateInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-group-by.output.ts b/server/src/core/@generated/user/user-group-by.output.ts index e0d02f678..a54fabddc 100644 --- a/server/src/core/@generated/user/user-group-by.output.ts +++ b/server/src/core/@generated/user/user-group-by.output.ts @@ -15,13 +15,15 @@ export class UserGroupBy { @Validator.IsOptional() id!: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-max-aggregate.output.ts b/server/src/core/@generated/user/user-max-aggregate.output.ts index be1ba0367..521b75742 100644 --- a/server/src/core/@generated/user/user-max-aggregate.output.ts +++ b/server/src/core/@generated/user/user-max-aggregate.output.ts @@ -13,10 +13,12 @@ export class UserMaxAggregate { @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() firstName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() lastName?: string; @Field(() => String, {nullable:true}) diff --git a/server/src/core/@generated/user/user-min-aggregate.output.ts b/server/src/core/@generated/user/user-min-aggregate.output.ts index 7b5e32b3d..0b9073efa 100644 --- a/server/src/core/@generated/user/user-min-aggregate.output.ts +++ b/server/src/core/@generated/user/user-min-aggregate.output.ts @@ -13,10 +13,12 @@ export class UserMinAggregate { @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() firstName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() lastName?: string; @Field(() => String, {nullable:true}) diff --git a/server/src/core/@generated/user/user-scalar-where-with-aggregates.input.ts b/server/src/core/@generated/user/user-scalar-where-with-aggregates.input.ts index 829bfefbb..070acb214 100644 --- a/server/src/core/@generated/user/user-scalar-where-with-aggregates.input.ts +++ b/server/src/core/@generated/user/user-scalar-where-with-aggregates.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringWithAggregatesFilter } from '../prisma/string-with-aggregates-filter.input'; -import { BoolWithAggregatesFilter } from '../prisma/bool-with-aggregates-filter.input'; import { StringNullableWithAggregatesFilter } from '../prisma/string-nullable-with-aggregates-filter.input'; +import { BoolWithAggregatesFilter } from '../prisma/bool-with-aggregates-filter.input'; import { DateTimeNullableWithAggregatesFilter } from '../prisma/date-time-nullable-with-aggregates-filter.input'; import { HideField } from '@nestjs/graphql'; import { JsonNullableWithAggregatesFilter } from '../prisma/json-nullable-with-aggregates-filter.input'; @@ -23,11 +23,11 @@ export class UserScalarWhereWithAggregatesInput { @Field(() => StringWithAggregatesFilter, {nullable:true}) id?: StringWithAggregatesFilter; - @Field(() => StringWithAggregatesFilter, {nullable:true}) - firstName?: StringWithAggregatesFilter; + @Field(() => StringNullableWithAggregatesFilter, {nullable:true}) + firstName?: StringNullableWithAggregatesFilter; - @Field(() => StringWithAggregatesFilter, {nullable:true}) - lastName?: StringWithAggregatesFilter; + @Field(() => StringNullableWithAggregatesFilter, {nullable:true}) + lastName?: StringNullableWithAggregatesFilter; @Field(() => StringWithAggregatesFilter, {nullable:true}) email?: StringWithAggregatesFilter; diff --git a/server/src/core/@generated/user/user-unchecked-create-without-comments.input.ts b/server/src/core/@generated/user/user-unchecked-create-without-comments.input.ts index 6a3ff5d9f..eaa0600da 100644 --- a/server/src/core/@generated/user/user-unchecked-create-without-comments.input.ts +++ b/server/src/core/@generated/user/user-unchecked-create-without-comments.input.ts @@ -15,13 +15,15 @@ export class UserUncheckedCreateWithoutCommentsInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-unchecked-create-without-companies.input.ts b/server/src/core/@generated/user/user-unchecked-create-without-companies.input.ts index fb40c8775..20e868db1 100644 --- a/server/src/core/@generated/user/user-unchecked-create-without-companies.input.ts +++ b/server/src/core/@generated/user/user-unchecked-create-without-companies.input.ts @@ -15,13 +15,15 @@ export class UserUncheckedCreateWithoutCompaniesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-unchecked-create-without-refresh-tokens.input.ts b/server/src/core/@generated/user/user-unchecked-create-without-refresh-tokens.input.ts index 2a258119f..5410fed9e 100644 --- a/server/src/core/@generated/user/user-unchecked-create-without-refresh-tokens.input.ts +++ b/server/src/core/@generated/user/user-unchecked-create-without-refresh-tokens.input.ts @@ -15,13 +15,15 @@ export class UserUncheckedCreateWithoutRefreshTokensInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-unchecked-create-without-workspace-member.input.ts b/server/src/core/@generated/user/user-unchecked-create-without-workspace-member.input.ts index 12c65db6b..83f674541 100644 --- a/server/src/core/@generated/user/user-unchecked-create-without-workspace-member.input.ts +++ b/server/src/core/@generated/user/user-unchecked-create-without-workspace-member.input.ts @@ -15,13 +15,15 @@ export class UserUncheckedCreateWithoutWorkspaceMemberInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-unchecked-create.input.ts b/server/src/core/@generated/user/user-unchecked-create.input.ts index e9b43a576..70fd59b9e 100644 --- a/server/src/core/@generated/user/user-unchecked-create.input.ts +++ b/server/src/core/@generated/user/user-unchecked-create.input.ts @@ -16,13 +16,15 @@ export class UserUncheckedCreateInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - firstName!: string; + @Validator.IsOptional() + firstName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - lastName!: string; + @Validator.IsOptional() + lastName?: string; @Field(() => String, {nullable:false}) @Validator.IsEmail() diff --git a/server/src/core/@generated/user/user-unchecked-update-many.input.ts b/server/src/core/@generated/user/user-unchecked-update-many.input.ts index fc0db60e6..232edaa25 100644 --- a/server/src/core/@generated/user/user-unchecked-update-many.input.ts +++ b/server/src/core/@generated/user/user-unchecked-update-many.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -15,11 +15,11 @@ export class UserUncheckedUpdateManyInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-unchecked-update-without-comments.input.ts b/server/src/core/@generated/user/user-unchecked-update-without-comments.input.ts index 57678cd5c..6e6ba6f84 100644 --- a/server/src/core/@generated/user/user-unchecked-update-without-comments.input.ts +++ b/server/src/core/@generated/user/user-unchecked-update-without-comments.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUncheckedUpdateWithoutCommentsInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-unchecked-update-without-companies.input.ts b/server/src/core/@generated/user/user-unchecked-update-without-companies.input.ts index 984f85a67..a6494ab94 100644 --- a/server/src/core/@generated/user/user-unchecked-update-without-companies.input.ts +++ b/server/src/core/@generated/user/user-unchecked-update-without-companies.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUncheckedUpdateWithoutCompaniesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-unchecked-update-without-refresh-tokens.input.ts b/server/src/core/@generated/user/user-unchecked-update-without-refresh-tokens.input.ts index 1153e2c0a..30f68b5cf 100644 --- a/server/src/core/@generated/user/user-unchecked-update-without-refresh-tokens.input.ts +++ b/server/src/core/@generated/user/user-unchecked-update-without-refresh-tokens.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUncheckedUpdateWithoutRefreshTokensInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-unchecked-update-without-workspace-member.input.ts b/server/src/core/@generated/user/user-unchecked-update-without-workspace-member.input.ts index 9d30bd8b6..13b4db370 100644 --- a/server/src/core/@generated/user/user-unchecked-update-without-workspace-member.input.ts +++ b/server/src/core/@generated/user/user-unchecked-update-without-workspace-member.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUncheckedUpdateWithoutWorkspaceMemberInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-unchecked-update.input.ts b/server/src/core/@generated/user/user-unchecked-update.input.ts index 20818ebf8..f74808859 100644 --- a/server/src/core/@generated/user/user-unchecked-update.input.ts +++ b/server/src/core/@generated/user/user-unchecked-update.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -19,11 +19,11 @@ export class UserUncheckedUpdateInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-update-many-mutation.input.ts b/server/src/core/@generated/user/user-update-many-mutation.input.ts index 509f91de5..160080960 100644 --- a/server/src/core/@generated/user/user-update-many-mutation.input.ts +++ b/server/src/core/@generated/user/user-update-many-mutation.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -15,11 +15,11 @@ export class UserUpdateManyMutationInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-update-without-comments.input.ts b/server/src/core/@generated/user/user-update-without-comments.input.ts index 57c4cc819..c2fda0438 100644 --- a/server/src/core/@generated/user/user-update-without-comments.input.ts +++ b/server/src/core/@generated/user/user-update-without-comments.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUpdateWithoutCommentsInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-update-without-companies.input.ts b/server/src/core/@generated/user/user-update-without-companies.input.ts index d6746471e..12bbd0ec1 100644 --- a/server/src/core/@generated/user/user-update-without-companies.input.ts +++ b/server/src/core/@generated/user/user-update-without-companies.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUpdateWithoutCompaniesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-update-without-refresh-tokens.input.ts b/server/src/core/@generated/user/user-update-without-refresh-tokens.input.ts index 94d8938ce..b3d03f25a 100644 --- a/server/src/core/@generated/user/user-update-without-refresh-tokens.input.ts +++ b/server/src/core/@generated/user/user-update-without-refresh-tokens.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUpdateWithoutRefreshTokensInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-update-without-workspace-member.input.ts b/server/src/core/@generated/user/user-update-without-workspace-member.input.ts index 6b24e0df7..21f241cbe 100644 --- a/server/src/core/@generated/user/user-update-without-workspace-member.input.ts +++ b/server/src/core/@generated/user/user-update-without-workspace-member.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -18,11 +18,11 @@ export class UserUpdateWithoutWorkspaceMemberInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-update.input.ts b/server/src/core/@generated/user/user-update.input.ts index 8892a70e2..f2f789792 100644 --- a/server/src/core/@generated/user/user-update.input.ts +++ b/server/src/core/@generated/user/user-update.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; -import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableStringFieldUpdateOperationsInput } from '../prisma/nullable-string-field-update-operations.input'; +import { BoolFieldUpdateOperationsInput } from '../prisma/bool-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { HideField } from '@nestjs/graphql'; import { GraphQLJSON } from 'graphql-type-json'; @@ -19,11 +19,11 @@ export class UserUpdateInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - firstName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + firstName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - lastName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + lastName?: NullableStringFieldUpdateOperationsInput; @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) email?: StringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/user/user-where.input.ts b/server/src/core/@generated/user/user-where.input.ts index 2e1cd9434..c7eae991f 100644 --- a/server/src/core/@generated/user/user-where.input.ts +++ b/server/src/core/@generated/user/user-where.input.ts @@ -1,8 +1,8 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { StringFilter } from '../prisma/string-filter.input'; -import { BoolFilter } from '../prisma/bool-filter.input'; import { StringNullableFilter } from '../prisma/string-nullable-filter.input'; +import { BoolFilter } from '../prisma/bool-filter.input'; import { DateTimeNullableFilter } from '../prisma/date-time-nullable-filter.input'; import { HideField } from '@nestjs/graphql'; import { JsonNullableFilter } from '../prisma/json-nullable-filter.input'; @@ -27,11 +27,11 @@ export class UserWhereInput { @Field(() => StringFilter, {nullable:true}) id?: StringFilter; - @Field(() => StringFilter, {nullable:true}) - firstName?: StringFilter; + @Field(() => StringNullableFilter, {nullable:true}) + firstName?: StringNullableFilter; - @Field(() => StringFilter, {nullable:true}) - lastName?: StringFilter; + @Field(() => StringNullableFilter, {nullable:true}) + lastName?: StringNullableFilter; @Field(() => StringFilter, {nullable:true}) email?: StringFilter; diff --git a/server/src/core/@generated/user/user.model.ts b/server/src/core/@generated/user/user.model.ts index 0a053ce3f..9441f85ed 100644 --- a/server/src/core/@generated/user/user.model.ts +++ b/server/src/core/@generated/user/user.model.ts @@ -15,11 +15,11 @@ export class User { @Field(() => ID, {nullable:false}) id!: string; - @Field(() => String, {nullable:false}) - firstName!: string; + @Field(() => String, {nullable:true}) + firstName!: string | null; - @Field(() => String, {nullable:false}) - lastName!: string; + @Field(() => String, {nullable:true}) + lastName!: string | null; @Field(() => String, {nullable:false}) email!: string; diff --git a/server/src/core/@generated/workspace/workspace-create-many.input.ts b/server/src/core/@generated/workspace/workspace-create-many.input.ts index 0a15f1ded..1059d52aa 100644 --- a/server/src/core/@generated/workspace/workspace-create-many.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-many.input.ts @@ -11,13 +11,15 @@ export class WorkspaceCreateManyInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-comment-threads.input.ts b/server/src/core/@generated/workspace/workspace-create-without-comment-threads.input.ts index 4c95327a6..87b098ca1 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-comment-threads.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-comment-threads.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutCommentThreadsInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-comments.input.ts b/server/src/core/@generated/workspace/workspace-create-without-comments.input.ts index 87c853a6e..9edda0694 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-comments.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-comments.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutCommentsInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-companies.input.ts b/server/src/core/@generated/workspace/workspace-create-without-companies.input.ts index 3c18a17c3..04fda1215 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-companies.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-companies.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutCompaniesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-people.input.ts b/server/src/core/@generated/workspace/workspace-create-without-people.input.ts index d78bd0732..9930dd133 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-people.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-people.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutPeopleInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-pipeline-progresses.input.ts b/server/src/core/@generated/workspace/workspace-create-without-pipeline-progresses.input.ts index ae49df118..e96a710c7 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-pipeline-progresses.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-pipeline-progresses.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutPipelineProgressesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-pipeline-stages.input.ts b/server/src/core/@generated/workspace/workspace-create-without-pipeline-stages.input.ts index 5b6041539..9bdb786e3 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-pipeline-stages.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-pipeline-stages.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutPipelineStagesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-pipelines.input.ts b/server/src/core/@generated/workspace/workspace-create-without-pipelines.input.ts index 3136284df..61a433f2c 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-pipelines.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-pipelines.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutPipelinesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create-without-workspace-member.input.ts b/server/src/core/@generated/workspace/workspace-create-without-workspace-member.input.ts index 4f60d70fd..3687f938e 100644 --- a/server/src/core/@generated/workspace/workspace-create-without-workspace-member.input.ts +++ b/server/src/core/@generated/workspace/workspace-create-without-workspace-member.input.ts @@ -18,13 +18,15 @@ export class WorkspaceCreateWithoutWorkspaceMemberInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-create.input.ts b/server/src/core/@generated/workspace/workspace-create.input.ts index 6137eb6e6..c700fcb0f 100644 --- a/server/src/core/@generated/workspace/workspace-create.input.ts +++ b/server/src/core/@generated/workspace/workspace-create.input.ts @@ -19,13 +19,15 @@ export class WorkspaceCreateInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-group-by.output.ts b/server/src/core/@generated/workspace/workspace-group-by.output.ts index 2d3828820..0acfc669c 100644 --- a/server/src/core/@generated/workspace/workspace-group-by.output.ts +++ b/server/src/core/@generated/workspace/workspace-group-by.output.ts @@ -14,13 +14,15 @@ export class WorkspaceGroupBy { @Validator.IsOptional() id!: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-max-aggregate.output.ts b/server/src/core/@generated/workspace/workspace-max-aggregate.output.ts index ba8f25ec2..df11a248b 100644 --- a/server/src/core/@generated/workspace/workspace-max-aggregate.output.ts +++ b/server/src/core/@generated/workspace/workspace-max-aggregate.output.ts @@ -13,10 +13,12 @@ export class WorkspaceMaxAggregate { @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() domainName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() displayName?: string; @Field(() => String, {nullable:true}) diff --git a/server/src/core/@generated/workspace/workspace-min-aggregate.output.ts b/server/src/core/@generated/workspace/workspace-min-aggregate.output.ts index e1ca5e496..c761b7d10 100644 --- a/server/src/core/@generated/workspace/workspace-min-aggregate.output.ts +++ b/server/src/core/@generated/workspace/workspace-min-aggregate.output.ts @@ -13,10 +13,12 @@ export class WorkspaceMinAggregate { @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() domainName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() + @Validator.IsOptional() displayName?: string; @Field(() => String, {nullable:true}) diff --git a/server/src/core/@generated/workspace/workspace-scalar-where-with-aggregates.input.ts b/server/src/core/@generated/workspace/workspace-scalar-where-with-aggregates.input.ts index bafa10616..7a8b4f7d1 100644 --- a/server/src/core/@generated/workspace/workspace-scalar-where-with-aggregates.input.ts +++ b/server/src/core/@generated/workspace/workspace-scalar-where-with-aggregates.input.ts @@ -21,11 +21,11 @@ export class WorkspaceScalarWhereWithAggregatesInput { @Field(() => StringWithAggregatesFilter, {nullable:true}) id?: StringWithAggregatesFilter; - @Field(() => StringWithAggregatesFilter, {nullable:true}) - domainName?: StringWithAggregatesFilter; + @Field(() => StringNullableWithAggregatesFilter, {nullable:true}) + domainName?: StringNullableWithAggregatesFilter; - @Field(() => StringWithAggregatesFilter, {nullable:true}) - displayName?: StringWithAggregatesFilter; + @Field(() => StringNullableWithAggregatesFilter, {nullable:true}) + displayName?: StringNullableWithAggregatesFilter; @Field(() => StringNullableWithAggregatesFilter, {nullable:true}) logo?: StringNullableWithAggregatesFilter; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-comment-threads.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-comment-threads.input.ts index 46cf3451a..c88813d0b 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-comment-threads.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-comment-threads.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutCommentThreadsInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-comments.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-comments.input.ts index 9c395cad9..12b5fad61 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-comments.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-comments.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutCommentsInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-companies.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-companies.input.ts index c0837717e..bab9da2b7 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-companies.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-companies.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutCompaniesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-people.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-people.input.ts index 6685a812f..34bf078af 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-people.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-people.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutPeopleInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-progresses.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-progresses.input.ts index 50f851ed7..f1f4a0df7 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-progresses.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-progresses.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutPipelineProgressesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-stages.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-stages.input.ts index a47af9100..7d004620b 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-stages.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipeline-stages.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutPipelineStagesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipelines.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipelines.input.ts index fd910fc79..afa376a4b 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipelines.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-pipelines.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutPipelinesInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create-without-workspace-member.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create-without-workspace-member.input.ts index be6c04d34..89ab96a85 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create-without-workspace-member.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create-without-workspace-member.input.ts @@ -18,13 +18,15 @@ export class WorkspaceUncheckedCreateWithoutWorkspaceMemberInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-create.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-create.input.ts index 193bd4daa..737c3b918 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-create.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-create.input.ts @@ -19,13 +19,15 @@ export class WorkspaceUncheckedCreateInput { @Validator.IsOptional() id?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - domainName!: string; + @Validator.IsOptional() + domainName?: string; - @Field(() => String, {nullable:false}) + @Field(() => String, {nullable:true}) @Validator.IsString() - displayName!: string; + @Validator.IsOptional() + displayName?: string; @Field(() => String, {nullable:true}) @Validator.IsString() diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-many.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-many.input.ts index 3eff5eeb0..396e39d88 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-many.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-many.input.ts @@ -12,11 +12,11 @@ export class WorkspaceUncheckedUpdateManyInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-comment-threads.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-comment-threads.input.ts index c3b8b3eb5..eff6cb2a9 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-comment-threads.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-comment-threads.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutCommentThreadsInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-comments.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-comments.input.ts index 5a9a01fbe..8859f5025 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-comments.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-comments.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutCommentsInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-companies.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-companies.input.ts index 3f288a1d8..87c8ff33b 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-companies.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-companies.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutCompaniesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-people.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-people.input.ts index 4e731a4c2..92fff10aa 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-people.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-people.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutPeopleInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-progresses.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-progresses.input.ts index 2dbc07b8a..e8d6bcdf1 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-progresses.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-progresses.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutPipelineProgressesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-stages.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-stages.input.ts index 9b3239c35..fee46c1c3 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-stages.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipeline-stages.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutPipelineStagesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipelines.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipelines.input.ts index 6903cc4f1..06f45c274 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipelines.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-pipelines.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutPipelinesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update-without-workspace-member.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update-without-workspace-member.input.ts index 56699a7ff..55096ed40 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update-without-workspace-member.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update-without-workspace-member.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUncheckedUpdateWithoutWorkspaceMemberInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-unchecked-update.input.ts b/server/src/core/@generated/workspace/workspace-unchecked-update.input.ts index 7ef4bc271..c7d8a0dd8 100644 --- a/server/src/core/@generated/workspace/workspace-unchecked-update.input.ts +++ b/server/src/core/@generated/workspace/workspace-unchecked-update.input.ts @@ -20,11 +20,11 @@ export class WorkspaceUncheckedUpdateInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-many-mutation.input.ts b/server/src/core/@generated/workspace/workspace-update-many-mutation.input.ts index e1ebe3656..bd659d9f2 100644 --- a/server/src/core/@generated/workspace/workspace-update-many-mutation.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-many-mutation.input.ts @@ -12,11 +12,11 @@ export class WorkspaceUpdateManyMutationInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-comment-threads.input.ts b/server/src/core/@generated/workspace/workspace-update-without-comment-threads.input.ts index 8786d5854..6e903e8fc 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-comment-threads.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-comment-threads.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutCommentThreadsInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-comments.input.ts b/server/src/core/@generated/workspace/workspace-update-without-comments.input.ts index 705166c99..e36bafc48 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-comments.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-comments.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutCommentsInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-companies.input.ts b/server/src/core/@generated/workspace/workspace-update-without-companies.input.ts index ed610ff6b..ee0e8e299 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-companies.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-companies.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutCompaniesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-people.input.ts b/server/src/core/@generated/workspace/workspace-update-without-people.input.ts index 7862c0704..457b83ae3 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-people.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-people.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutPeopleInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-pipeline-progresses.input.ts b/server/src/core/@generated/workspace/workspace-update-without-pipeline-progresses.input.ts index 4e9cdd407..8ccddaeb1 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-pipeline-progresses.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-pipeline-progresses.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutPipelineProgressesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-pipeline-stages.input.ts b/server/src/core/@generated/workspace/workspace-update-without-pipeline-stages.input.ts index 86a6d79eb..12dba5851 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-pipeline-stages.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-pipeline-stages.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutPipelineStagesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-pipelines.input.ts b/server/src/core/@generated/workspace/workspace-update-without-pipelines.input.ts index d1ffa3512..d61862282 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-pipelines.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-pipelines.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutPipelinesInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update-without-workspace-member.input.ts b/server/src/core/@generated/workspace/workspace-update-without-workspace-member.input.ts index 1b50891b0..446fdcd6c 100644 --- a/server/src/core/@generated/workspace/workspace-update-without-workspace-member.input.ts +++ b/server/src/core/@generated/workspace/workspace-update-without-workspace-member.input.ts @@ -19,11 +19,11 @@ export class WorkspaceUpdateWithoutWorkspaceMemberInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-update.input.ts b/server/src/core/@generated/workspace/workspace-update.input.ts index c69952539..7276fb9ff 100644 --- a/server/src/core/@generated/workspace/workspace-update.input.ts +++ b/server/src/core/@generated/workspace/workspace-update.input.ts @@ -20,11 +20,11 @@ export class WorkspaceUpdateInput { @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) id?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - domainName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + domainName?: NullableStringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, {nullable:true}) - displayName?: StringFieldUpdateOperationsInput; + @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) + displayName?: NullableStringFieldUpdateOperationsInput; @Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true}) logo?: NullableStringFieldUpdateOperationsInput; diff --git a/server/src/core/@generated/workspace/workspace-where-unique.input.ts b/server/src/core/@generated/workspace/workspace-where-unique.input.ts index 1cc87e8a4..77b6c95b9 100644 --- a/server/src/core/@generated/workspace/workspace-where-unique.input.ts +++ b/server/src/core/@generated/workspace/workspace-where-unique.input.ts @@ -9,8 +9,4 @@ export class WorkspaceWhereUniqueInput { @Validator.IsString() @Validator.IsOptional() id?: string; - - @Field(() => String, {nullable:true}) - @Validator.IsString() - domainName?: string; } diff --git a/server/src/core/@generated/workspace/workspace-where.input.ts b/server/src/core/@generated/workspace/workspace-where.input.ts index 24c7da0d7..af2357372 100644 --- a/server/src/core/@generated/workspace/workspace-where.input.ts +++ b/server/src/core/@generated/workspace/workspace-where.input.ts @@ -29,11 +29,11 @@ export class WorkspaceWhereInput { @Field(() => StringFilter, {nullable:true}) id?: StringFilter; - @Field(() => StringFilter, {nullable:true}) - domainName?: StringFilter; + @Field(() => StringNullableFilter, {nullable:true}) + domainName?: StringNullableFilter; - @Field(() => StringFilter, {nullable:true}) - displayName?: StringFilter; + @Field(() => StringNullableFilter, {nullable:true}) + displayName?: StringNullableFilter; @Field(() => StringNullableFilter, {nullable:true}) logo?: StringNullableFilter; diff --git a/server/src/core/@generated/workspace/workspace.model.ts b/server/src/core/@generated/workspace/workspace.model.ts index b709c0cfb..9cf4eb6be 100644 --- a/server/src/core/@generated/workspace/workspace.model.ts +++ b/server/src/core/@generated/workspace/workspace.model.ts @@ -18,11 +18,11 @@ export class Workspace { @Field(() => ID, {nullable:false}) id!: string; - @Field(() => String, {nullable:false}) - domainName!: string; + @Field(() => String, {nullable:true}) + domainName!: string | null; - @Field(() => String, {nullable:false}) - displayName!: string; + @Field(() => String, {nullable:true}) + displayName!: string | null; @Field(() => String, {nullable:true}) logo!: string | null; diff --git a/server/src/core/auth/auth.resolver.ts b/server/src/core/auth/auth.resolver.ts index fad6a05dc..a09c2ef46 100644 --- a/server/src/core/auth/auth.resolver.ts +++ b/server/src/core/auth/auth.resolver.ts @@ -1,5 +1,5 @@ -import { Args, Mutation, Resolver, Query} from '@nestjs/graphql'; -import { AuthTokens, ClientConfig} from './dto/token.entity'; +import { Args, Mutation, Resolver, Query } from '@nestjs/graphql'; +import { AuthTokens, ClientConfig } from './dto/token.entity'; import { TokenService } from './services/token.service'; import { RefreshTokenInput } from './dto/refresh-token.input'; import { BadRequestException } from '@nestjs/common'; @@ -74,4 +74,4 @@ export class AuthResolver { return Promise.resolve(clientConfig); } -} \ No newline at end of file +} diff --git a/server/src/core/auth/dto/challenge.input.ts b/server/src/core/auth/dto/challenge.input.ts index 8c6dc82f0..6a00b2eb6 100644 --- a/server/src/core/auth/dto/challenge.input.ts +++ b/server/src/core/auth/dto/challenge.input.ts @@ -1,5 +1,12 @@ import { ArgsType, Field } from '@nestjs/graphql'; -import { IsEmail, IsNotEmpty, IsString } from 'class-validator'; +import { + IsEmail, + IsNotEmpty, + IsString, + Matches, + MinLength, +} from 'class-validator'; +import { PASSWORD_REGEX } from '../auth.util'; @ArgsType() export class ChallengeInput { @@ -11,5 +18,7 @@ export class ChallengeInput { @Field(() => String) @IsNotEmpty() @IsString() + @MinLength(8) + @Matches(PASSWORD_REGEX, { message: 'password too weak' }) password: string; } diff --git a/server/src/core/auth/dto/register.input.ts b/server/src/core/auth/dto/register.input.ts deleted file mode 100644 index afb9b8983..000000000 --- a/server/src/core/auth/dto/register.input.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - IsEmail, - IsNotEmpty, - IsOptional, - IsString, - Matches, - MinLength, -} from 'class-validator'; -import { PASSWORD_REGEX } from '../auth.util'; -import { ArgsType, Field } from '@nestjs/graphql'; - -@ArgsType() -export class RegisterInput { - @Field(() => String) - @IsNotEmpty() - @IsEmail() - email: string; - - @Field(() => String) - @IsNotEmpty() - @IsString() - @MinLength(8) - @Matches(PASSWORD_REGEX, { message: 'password too weak' }) - password: string; - - @Field(() => String, { - deprecationReason: 'Deprecated, please use firstName and lastName instead', - nullable: true, - }) - @IsOptional() - @IsString() - displayName?: string; - - @Field(() => String) - @IsNotEmpty() - @IsString() - firstName: string; - - @Field(() => String) - @IsNotEmpty() - @IsString() - lastName: string; -} diff --git a/server/src/core/auth/dto/token.entity.ts b/server/src/core/auth/dto/token.entity.ts index 3bae3169d..2f7156e1c 100644 --- a/server/src/core/auth/dto/token.entity.ts +++ b/server/src/core/auth/dto/token.entity.ts @@ -31,4 +31,4 @@ export class ClientConfig { @Field(() => Boolean) prefill_login_with_seed: boolean; -} \ No newline at end of file +} diff --git a/server/src/core/auth/services/auth.service.ts b/server/src/core/auth/services/auth.service.ts index c5a2114b5..e2a7abfdb 100644 --- a/server/src/core/auth/services/auth.service.ts +++ b/server/src/core/auth/services/auth.service.ts @@ -7,7 +7,6 @@ import { import { ChallengeInput } from '../dto/challenge.input'; import { UserService } from 'src/core/user/user.service'; import { assert } from 'src/utils/assert'; -import { RegisterInput } from '../dto/register.input'; import { PASSWORD_REGEX, compareHash, hashPassword } from '../auth.util'; import { Verify } from '../dto/verify.entity'; import { TokenService } from './token.service'; @@ -26,42 +25,31 @@ export class AuthService { private readonly userService: UserService, ) {} - async register(registerInput: RegisterInput) { - const existingUser = await this.userService.findUnique({ - where: { - email: registerInput.email, - }, - }); - - assert(!existingUser, 'This user already exist', NotFoundException); + async challenge(challengeInput: ChallengeInput) { assert( - PASSWORD_REGEX.test(registerInput.password), + PASSWORD_REGEX.test(challengeInput.password), 'Password too weak', BadRequestException, ); - const passwordHash = await hashPassword(registerInput.password); - - const user = await this.userService.createUser({ - data: { - firstName: registerInput.firstName, - lastName: registerInput.lastName, - email: registerInput.email, - passwordHash, - locale: 'en', - }, - }); - - return user; - } - - async challenge(challengeInput: ChallengeInput) { - const user = await this.userService.findUnique({ + let user = await this.userService.findUnique({ where: { email: challengeInput.email, }, }); + if (!user) { + const passwordHash = await hashPassword(challengeInput.password); + + user = await this.userService.createUser({ + data: { + email: challengeInput.email, + passwordHash, + locale: 'en', + }, + } as Prisma.UserCreateArgs); + } + assert(user, "This user doesn't exist", NotFoundException); assert(user.passwordHash, 'Incorrect login method', ForbiddenException); diff --git a/server/src/core/comment/resolvers/comment-thread.resolver.ts b/server/src/core/comment/resolvers/comment-thread.resolver.ts index 53b982eb1..5c36029d2 100644 --- a/server/src/core/comment/resolvers/comment-thread.resolver.ts +++ b/server/src/core/comment/resolvers/comment-thread.resolver.ts @@ -9,7 +9,6 @@ import { CreateOneCommentThreadGuard } from '../../../guards/create-one-comment- import { FindManyCommentThreadArgs } from '../../../core/@generated/comment-thread/find-many-comment-thread.args'; import { CommentThreadService } from '../services/comment-thread.service'; import { UpdateOneCommentThreadArgs } from 'src/core/@generated/comment-thread/update-one-comment-thread.args'; -import { Prisma } from '@prisma/client'; import { PrismaSelector, PrismaSelect, @@ -27,6 +26,7 @@ import { AppAbility } from 'src/ability/ability.factory'; import { accessibleBy } from '@casl/prisma'; import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output'; import { DeleteManyCommentThreadArgs } from 'src/core/@generated/comment-thread/delete-many-comment-thread.args'; +import { Prisma } from '@prisma/client'; @UseGuards(JwtAuthGuard) @Resolver(() => CommentThread) @@ -75,7 +75,8 @@ export class CommentThreadResolver { prismaSelect: PrismaSelect<'CommentThread'>, ): Promise> { const updatedCommentThread = await this.commentThreadService.update({ - ...args, + where: args.where, + data: args.data, select: prismaSelect.value, } as Prisma.CommentThreadUpdateArgs); @@ -92,11 +93,15 @@ export class CommentThreadResolver { prismaSelect: PrismaSelect<'CommentThread'>, ): Promise[]> { const result = await this.commentThreadService.findMany({ - ...args, where: { ...args.where, AND: [accessibleBy(ability).CommentThread], }, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, select: prismaSelect.value, }); @@ -112,7 +117,7 @@ export class CommentThreadResolver { @Args() args: DeleteManyCommentThreadArgs, ): Promise { return this.commentThreadService.deleteMany({ - ...args, + where: args.where, }); } } diff --git a/server/src/core/comment/resolvers/comment.resolver.ts b/server/src/core/comment/resolvers/comment.resolver.ts index 385fb83dd..6db68b5a9 100644 --- a/server/src/core/comment/resolvers/comment.resolver.ts +++ b/server/src/core/comment/resolvers/comment.resolver.ts @@ -6,7 +6,6 @@ import { AuthWorkspace } from '../../../decorators/auth-workspace.decorator'; import { CreateOneCommentArgs } from '../../../core/@generated/comment/create-one-comment.args'; import { Comment } from '../../../core/@generated/comment/comment.model'; import { CreateOneCommentGuard } from '../../../guards/create-one-comment.guard'; -import { Prisma } from '@prisma/client'; import { CommentService } from '../services/comment.service'; import { PrismaSelector, @@ -17,6 +16,7 @@ import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; import { CreateCommentAbilityHandler } from 'src/ability/handlers/comment.ability-handler'; import { AuthUser } from 'src/decorators/auth-user.decorator'; import { User } from 'src/core/@generated/user/user.model'; +import { Prisma } from '@prisma/client'; @UseGuards(JwtAuthGuard) @Resolver(() => Comment) diff --git a/server/src/core/company/company.resolver.ts b/server/src/core/company/company.resolver.ts index 2c9474a2e..b000a6c57 100644 --- a/server/src/core/company/company.resolver.ts +++ b/server/src/core/company/company.resolver.ts @@ -8,8 +8,7 @@ import { UpdateOneCompanyArgs } from '../../core/@generated/company/update-one-c import { CreateOneCompanyArgs } from '../../core/@generated/company/create-one-company.args'; import { AffectedRows } from '../../core/@generated/prisma/affected-rows.output'; import { DeleteManyCompanyArgs } from '../../core/@generated/company/delete-many-company.args'; -import { Workspace } from '@prisma/client'; -import { Prisma } from '@prisma/client'; +import { Prisma, Workspace } from '@prisma/client'; import { UpdateOneGuard } from '../../guards/update-one.guard'; import { DeleteManyGuard } from '../../guards/delete-many.guard'; import { CreateOneGuard } from '../../guards/create-one.guard'; @@ -45,12 +44,16 @@ export class CompanyResolver { prismaSelect: PrismaSelect<'Company'>, ): Promise[]> { return this.companyService.findMany({ - ...args, where: args.where ? { AND: [args.where, accessibleBy(ability).Company], } : accessibleBy(ability).Company, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, select: prismaSelect.value, }); } @@ -71,7 +74,8 @@ export class CompanyResolver { } return this.companyService.update({ - ...args, + where: args.where, + data: args.data, select: prismaSelect.value, } as Prisma.CompanyUpdateArgs); } @@ -86,7 +90,7 @@ export class CompanyResolver { @Args() args: DeleteManyCompanyArgs, ): Promise { return this.companyService.deleteMany({ - ...args, + where: args.where, }); } diff --git a/server/src/core/person/person.resolver.ts b/server/src/core/person/person.resolver.ts index c812bf44f..94e8cff25 100644 --- a/server/src/core/person/person.resolver.ts +++ b/server/src/core/person/person.resolver.ts @@ -9,7 +9,6 @@ import { AffectedRows } from '../../core/@generated/prisma/affected-rows.output' import { DeleteManyPersonArgs } from '../../core/@generated/person/delete-many-person.args'; import { Workspace } from '../../core/@generated/workspace/workspace.model'; import { AuthWorkspace } from '../../decorators/auth-workspace.decorator'; -import { Prisma } from '@prisma/client'; import { UpdateOneGuard } from '../../guards/update-one.guard'; import { DeleteManyGuard } from '../../guards/delete-many.guard'; import { CreateOneGuard } from '../../guards/create-one.guard'; @@ -29,6 +28,7 @@ import { import { UserAbility } from 'src/decorators/user-ability.decorator'; import { AppAbility } from 'src/ability/ability.factory'; import { accessibleBy } from '@casl/prisma'; +import { Prisma } from '@prisma/client'; @UseGuards(JwtAuthGuard) @Resolver(() => Person) @@ -47,12 +47,16 @@ export class PersonResolver { prismaSelect: PrismaSelect<'Person'>, ): Promise[]> { return this.personService.findMany({ - ...args, where: args.where ? { AND: [args.where, accessibleBy(ability).Person], } : accessibleBy(ability).Person, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, select: prismaSelect.value, }); } @@ -73,7 +77,8 @@ export class PersonResolver { } return this.personService.update({ - ...args, + where: args.where, + data: args.data, select: prismaSelect.value, } as Prisma.PersonUpdateArgs); } @@ -88,7 +93,7 @@ export class PersonResolver { @Args() args: DeleteManyPersonArgs, ): Promise { return this.personService.deleteMany({ - ...args, + where: args.where, }); } diff --git a/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts b/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts index fc01b4b4d..8e6ddf19c 100644 --- a/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts +++ b/server/src/core/pipeline/resolvers/pipeline-progress.resolver.ts @@ -7,7 +7,6 @@ import { AuthWorkspace } from '../../../decorators/auth-workspace.decorator'; import { FindManyPipelineProgressArgs } from '../../@generated/pipeline-progress/find-many-pipeline-progress.args'; import { PipelineProgress } from '../../@generated/pipeline-progress/pipeline-progress.model'; import { UpdateOnePipelineProgressArgs } from '../../@generated/pipeline-progress/update-one-pipeline-progress.args'; -import { Prisma } from '@prisma/client'; import { AffectedRows } from '../../@generated/prisma/affected-rows.output'; import { DeleteManyPipelineProgressArgs } from '../../@generated/pipeline-progress/delete-many-pipeline-progress.args'; import { CreateOnePipelineProgressArgs } from '../../@generated/pipeline-progress/create-one-pipeline-progress.args'; @@ -26,6 +25,7 @@ import { PrismaSelector, PrismaSelect, } from 'src/decorators/prisma-select.decorator'; +import { Prisma } from '@prisma/client'; @UseGuards(JwtAuthGuard) @Resolver(() => PipelineProgress) @@ -40,14 +40,21 @@ export class PipelineProgressResolver { async findManyPipelineProgress( @Args() args: FindManyPipelineProgressArgs, @UserAbility() ability: AppAbility, + @PrismaSelector({ modelName: 'PipelineProgress' }) + prismaSelect: PrismaSelect<'PipelineProgress'>, ): Promise[]> { return this.pipelineProgressService.findMany({ - ...args, where: args.where ? { AND: [args.where, accessibleBy(ability).PipelineProgress], } : accessibleBy(ability).PipelineProgress, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, + select: prismaSelect.value, }); } @@ -62,7 +69,8 @@ export class PipelineProgressResolver { prismaSelect: PrismaSelect<'PipelineProgress'>, ): Promise | null> { return this.pipelineProgressService.update({ - ...args, + where: args.where, + data: args.data, select: prismaSelect.value, } as Prisma.PipelineProgressUpdateArgs); } @@ -76,7 +84,7 @@ export class PipelineProgressResolver { @Args() args: DeleteManyPipelineProgressArgs, ): Promise { return this.pipelineProgressService.deleteMany({ - ...args, + where: args.where, }); } diff --git a/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts b/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts index 8b34b5763..88bde1b20 100644 --- a/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts +++ b/server/src/core/pipeline/resolvers/pipeline-stage.resolver.ts @@ -30,12 +30,16 @@ export class PipelineStageResolver { prismaSelect: PrismaSelect<'PipelineStage'>, ): Promise[]> { return this.pipelineStageService.findMany({ - ...args, where: args.where ? { AND: [args.where, accessibleBy(ability).PipelineStage], } : accessibleBy(ability).PipelineStage, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, select: prismaSelect.value, }); } diff --git a/server/src/core/user/user.module.ts b/server/src/core/user/user.module.ts index ff2d92b50..d804a712c 100644 --- a/server/src/core/user/user.module.ts +++ b/server/src/core/user/user.module.ts @@ -1,10 +1,9 @@ import { Module } from '@nestjs/common'; import { UserService } from './user.service'; import { UserResolver } from './user.resolver'; -import { WorkspaceModule } from '../workspace/workspace.module'; @Module({ - imports: [WorkspaceModule], + imports: [], providers: [UserService, UserResolver], exports: [UserService], }) diff --git a/server/src/core/user/user.resolver.ts b/server/src/core/user/user.resolver.ts index 097f749d1..823794506 100644 --- a/server/src/core/user/user.resolver.ts +++ b/server/src/core/user/user.resolver.ts @@ -1,4 +1,11 @@ -import { Args, Resolver, Query, ResolveField, Parent } from '@nestjs/graphql'; +import { + Args, + Resolver, + Query, + ResolveField, + Parent, + Mutation, +} from '@nestjs/graphql'; import { UserService } from './user.service'; import { FindManyUserArgs } from 'src/core/@generated/user/find-many-user.args'; import { User } from 'src/core/@generated/user/user.model'; @@ -11,16 +18,40 @@ import { } from 'src/decorators/prisma-select.decorator'; import { AbilityGuard } from 'src/guards/ability.guard'; import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; -import { ReadUserAbilityHandler } from 'src/ability/handlers/user.ability-handler'; +import { + ReadUserAbilityHandler, + UpdateUserAbilityHandler, +} from 'src/ability/handlers/user.ability-handler'; import { UserAbility } from 'src/decorators/user-ability.decorator'; import { AppAbility } from 'src/ability/ability.factory'; import { accessibleBy } from '@casl/prisma'; +import { AuthUser } from 'src/decorators/auth-user.decorator'; +import { assert } from 'src/utils/assert'; +import { UpdateOneUserArgs } from '../@generated/user/update-one-user.args'; +import { Prisma } from '@prisma/client'; @UseGuards(JwtAuthGuard) @Resolver(() => User) export class UserResolver { constructor(private readonly userService: UserService) {} + @Query(() => User) + async currentUser( + @AuthUser() { id }: User, + @PrismaSelector({ modelName: 'User' }) + prismaSelect: PrismaSelect<'User'>, + ) { + const user = await this.userService.findUnique({ + where: { + id, + }, + select: prismaSelect.value, + }); + assert(user, 'User not found'); + + return user; + } + @UseFilters(ExceptionFilter) @Query(() => [User], { nullable: false, @@ -34,16 +65,44 @@ export class UserResolver { prismaSelect: PrismaSelect<'User'>, ): Promise[]> { return await this.userService.findMany({ - ...args, where: args.where ? { AND: [args.where, accessibleBy(ability).User], } : accessibleBy(ability).User, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, select: prismaSelect.value, }); } + @Mutation(() => User) + @UseGuards(AbilityGuard) + @CheckAbilities(UpdateUserAbilityHandler) + async updateUser( + @Args() args: UpdateOneUserArgs, + @AuthUser() { id }: User, + @PrismaSelector({ modelName: 'User' }) + prismaSelect: PrismaSelect<'User'>, + ) { + const user = await this.userService.findUnique({ + where: { + id, + }, + select: prismaSelect.value, + }); + assert(user, 'User not found'); + + return this.userService.update({ + where: args.where, + data: args.data, + select: prismaSelect.value, + } as Prisma.UserUpdateArgs); + } + @ResolveField(() => String, { nullable: false, }) diff --git a/server/src/core/user/user.service.spec.ts b/server/src/core/user/user.service.spec.ts index 9be9bf74f..94fa79a48 100644 --- a/server/src/core/user/user.service.spec.ts +++ b/server/src/core/user/user.service.spec.ts @@ -2,8 +2,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UserService } from './user.service'; import { PrismaService } from 'src/database/prisma.service'; import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; -import { WorkspaceService } from '../workspace/services/workspace.service'; -import { WorkspaceMemberService } from '../workspace/services/workspace-member.service'; describe('UserService', () => { let service: UserService; @@ -16,14 +14,6 @@ describe('UserService', () => { provide: PrismaService, useValue: prismaMock, }, - { - provide: WorkspaceService, - useValue: {}, - }, - { - provide: WorkspaceMemberService, - useValue: {}, - }, ], }).compile(); diff --git a/server/src/core/user/user.service.ts b/server/src/core/user/user.service.ts index b2e315a05..ddc609515 100644 --- a/server/src/core/user/user.service.ts +++ b/server/src/core/user/user.service.ts @@ -1,10 +1,5 @@ -import { - BadRequestException, - ForbiddenException, - Injectable, -} from '@nestjs/common'; +import { BadRequestException, Injectable } from '@nestjs/common'; import { PrismaService } from 'src/database/prisma.service'; -import { WorkspaceService } from 'src/core/workspace/services/workspace.service'; import { Prisma } from '@prisma/client'; import { assert } from 'src/utils/assert'; @@ -15,10 +10,7 @@ export type UserPayload = { @Injectable() export class UserService { - constructor( - private readonly prismaService: PrismaService, - private readonly workspaceService: WorkspaceService, - ) {} + constructor(private readonly prismaService: PrismaService) {} // Find findFirst = this.prismaService.user.findFirst; @@ -56,22 +48,6 @@ export class UserService { args: Prisma.SelectSubset, ): Promise> { assert(args.data.email, 'email is missing', BadRequestException); - assert(args.data.firstName, 'firstName is missing', BadRequestException); - assert(args.data.lastName, 'lastName is missing', BadRequestException); - - const emailDomain = args.data.email.split('@')[1]; - - assert(emailDomain, 'Email is malformed', BadRequestException); - - const workspace = await this.workspaceService.findUnique({ - where: { domainName: emailDomain }, - }); - - assert( - workspace, - 'User email domain does not match an existing workspace', - ForbiddenException, - ); const user = await this.prismaService.user.upsert({ where: { @@ -79,10 +55,12 @@ export class UserService { }, create: { ...(args.data as Prisma.UserCreateInput), + // Assign the user to a new workspace by default workspaceMember: { - connectOrCreate: { - where: { id: workspace.id }, - create: { workspaceId: workspace.id }, + create: { + workspace: { + create: {}, + }, }, }, locale: 'en', @@ -90,7 +68,7 @@ export class UserService { update: {}, ...(args.select ? { select: args.select } : {}), ...(args.include ? { include: args.include } : {}), - }); + } as Prisma.UserUpsertArgs); return user as Prisma.UserGetPayload; } diff --git a/server/src/core/workspace/resolvers/workspace.resolver.spec.ts b/server/src/core/workspace/resolvers/workspace.resolver.spec.ts new file mode 100644 index 000000000..1c72f7d6e --- /dev/null +++ b/server/src/core/workspace/resolvers/workspace.resolver.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { WorkspaceResolver } from './workspace.resolver'; +import { WorkspaceService } from '../services/workspace.service'; + +describe('WorkspaceMemberResolver', () => { + let resolver: WorkspaceResolver; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + WorkspaceResolver, + { provide: WorkspaceService, useValue: {} }, + ], + }).compile(); + + resolver = module.get(WorkspaceResolver); + }); + + it('should be defined', () => { + expect(resolver).toBeDefined(); + }); +}); diff --git a/server/src/core/workspace/resolvers/workspace.resolver.ts b/server/src/core/workspace/resolvers/workspace.resolver.ts new file mode 100644 index 000000000..fcc480e69 --- /dev/null +++ b/server/src/core/workspace/resolvers/workspace.resolver.ts @@ -0,0 +1,36 @@ +import { Args, Mutation, Resolver } from '@nestjs/graphql'; +import { UseGuards } from '@nestjs/common'; +import { Workspace } from 'src/core/@generated/workspace/workspace.model'; +import { WorkspaceService } from '../services/workspace.service'; +import { + PrismaSelect, + PrismaSelector, +} from 'src/decorators/prisma-select.decorator'; +import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator'; +import { WorkspaceUpdateInput } from 'src/core/@generated/workspace/workspace-update.input'; +import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; +import { Prisma } from '@prisma/client'; + +@UseGuards(JwtAuthGuard) +@Resolver(() => Workspace) +export class WorkspaceResolver { + constructor(private readonly workspaceService: WorkspaceService) {} + + @Mutation(() => Workspace) + async updateWorkspace( + @Args('data') data: WorkspaceUpdateInput, + @AuthWorkspace() workspace: Workspace, + @PrismaSelector({ modelName: 'Workspace' }) + prismaSelect: PrismaSelect<'Workspace'>, + ) { + return this.workspaceService.update({ + where: { + id: workspace.id, + }, + data: { + ...data, + }, + select: prismaSelect.value, + } as Prisma.WorkspaceUpdateArgs); + } +} diff --git a/server/src/core/workspace/workspace.module.ts b/server/src/core/workspace/workspace.module.ts index fd60a4b9c..423004b0a 100644 --- a/server/src/core/workspace/workspace.module.ts +++ b/server/src/core/workspace/workspace.module.ts @@ -1,9 +1,16 @@ import { Module } from '@nestjs/common'; import { WorkspaceService } from './services/workspace.service'; import { WorkspaceMemberService } from './services/workspace-member.service'; +import { WorkspaceMemberResolver } from './resolvers/workspace-member.resolver'; +import { WorkspaceResolver } from './resolvers/workspace.resolver'; @Module({ - providers: [WorkspaceService, WorkspaceMemberService], + providers: [ + WorkspaceService, + WorkspaceMemberService, + WorkspaceMemberResolver, + WorkspaceResolver, + ], exports: [WorkspaceService, WorkspaceMemberService], }) export class WorkspaceModule {} diff --git a/server/src/database/migrations/20230706073120_alter_table_workspace_remove_unique_domain_name_all_fields_optional/migration.sql b/server/src/database/migrations/20230706073120_alter_table_workspace_remove_unique_domain_name_all_fields_optional/migration.sql new file mode 100644 index 000000000..2402ca54a --- /dev/null +++ b/server/src/database/migrations/20230706073120_alter_table_workspace_remove_unique_domain_name_all_fields_optional/migration.sql @@ -0,0 +1,6 @@ +-- DropIndex +DROP INDEX "workspaces_domainName_key"; + +-- AlterTable +ALTER TABLE "workspaces" ALTER COLUMN "domainName" DROP NOT NULL, +ALTER COLUMN "displayName" DROP NOT NULL; diff --git a/server/src/database/migrations/20230706073151_alter_table_user_first_name_last_name_optional/migration.sql b/server/src/database/migrations/20230706073151_alter_table_user_first_name_last_name_optional/migration.sql new file mode 100644 index 000000000..e943e4209 --- /dev/null +++ b/server/src/database/migrations/20230706073151_alter_table_user_first_name_last_name_optional/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "users" ALTER COLUMN "firstName" DROP NOT NULL, +ALTER COLUMN "lastName" DROP NOT NULL; diff --git a/server/src/database/prisma.service.ts b/server/src/database/prisma.service.ts index 14280c605..401f75736 100644 --- a/server/src/database/prisma.service.ts +++ b/server/src/database/prisma.service.ts @@ -1,6 +1,14 @@ -import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common'; +import { + INestApplication, + Injectable, + Logger, + OnModuleInit, +} from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; +import { createPrismaQueryEventHandler } from 'prisma-query-log'; +import { EnvironmentService } from 'src/integrations/environment/environment.service'; +// TODO: Check if this is still needed if (!global.prisma) { global.prisma = new PrismaClient(); } @@ -8,6 +16,36 @@ export default global.prisma; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { + private readonly logger = new Logger(PrismaService.name); + + constructor(private readonly environmentService: EnvironmentService) { + const debugMode = environmentService.getDebugMode(); + super({ + errorFormat: 'minimal', + log: debugMode + ? [ + { + level: 'query', + emit: 'event', + }, + ] + : undefined, + }); + + if (debugMode) { + const logHandler = createPrismaQueryEventHandler({ + logger: (query: string) => { + this.logger.log(query, 'PrismaClient'); + }, + format: false, + colorQuery: '\u001B[96m', + colorParameter: '\u001B[90m', + }); + + this.$on('query' as any, logHandler); + } + } + async onModuleInit() { await this.$connect(); } diff --git a/server/src/database/schema.prisma b/server/src/database/schema.prisma index 32d5aab92..e77532d4c 100644 --- a/server/src/database/schema.prisma +++ b/server/src/database/schema.prisma @@ -135,9 +135,11 @@ model User { /// @Validator.IsOptional() id String @id @default(uuid()) /// @Validator.IsString() - firstName String + /// @Validator.IsOptional() + firstName String? /// @Validator.IsString() - lastName String + /// @Validator.IsOptional() + lastName String? /// @Validator.IsEmail() email String @unique /// @Validator.IsBoolean() @@ -185,9 +187,11 @@ model Workspace { /// @Validator.IsOptional() id String @id @default(uuid()) /// @Validator.IsString() - domainName String @unique + /// @Validator.IsOptional() + domainName String? /// @Validator.IsString() - displayName String + /// @Validator.IsOptional() + displayName String? /// @Validator.IsString() /// @Validator.IsOptional() logo String? diff --git a/server/src/database/seeds/users.ts b/server/src/database/seeds/users.ts index 205e81c66..818bcc93c 100644 --- a/server/src/database/seeds/users.ts +++ b/server/src/database/seeds/users.ts @@ -9,7 +9,7 @@ export const seedUsers = async (prisma: PrismaClient) => { lastName: 'Apple', email: 'tim@apple.dev', passwordHash: - '$2a$10$p2Pqc80JZX6bx/PkZJkC9OA/AasSHM7PMBk7mR3PCM0XSeKwDtwNa', // applecar2025 + '$2b$10$66d.6DuQExxnrfI9rMqOg.U1XIYpagr6Lv05uoWLYbYmtK0HDIvS6', // Applecar2025 locale: 'en', avatarUrl: 'data:image/png;base64,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', diff --git a/server/src/database/seeds/workspaces.ts b/server/src/database/seeds/workspaces.ts index 258283849..7f3caf637 100644 --- a/server/src/database/seeds/workspaces.ts +++ b/server/src/database/seeds/workspaces.ts @@ -1,7 +1,7 @@ import { PrismaClient } from '@prisma/client'; export const seedWorkspaces = async (prisma: PrismaClient) => { await prisma.workspace.upsert({ - where: { domainName: 'twenty.com' }, + where: { id: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419' }, update: {}, create: { id: 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419', @@ -10,8 +10,9 @@ export const seedWorkspaces = async (prisma: PrismaClient) => { logo: 'data:image/png;base64,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', }, }); + await prisma.workspace.upsert({ - where: { domainName: 'dev.twenty.com' }, + where: { id: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420' }, update: {}, create: { id: 'twenty-dev-7ed9d212-1c25-4d02-bf25-6aeccf7ea420', diff --git a/server/src/integrations/environment/environment.module-definition.ts b/server/src/integrations/environment/environment.module-definition.ts index 242e2ef3c..588556499 100644 --- a/server/src/integrations/environment/environment.module-definition.ts +++ b/server/src/integrations/environment/environment.module-definition.ts @@ -2,7 +2,7 @@ import { ConfigurableModuleBuilder } from '@nestjs/common'; export const { ConfigurableModuleClass, MODULE_OPTIONS_TOKEN } = new ConfigurableModuleBuilder({ - moduleName: 'Environment', + moduleName: 'Prisma', }) .setClassMethodName('forRoot') .build(); diff --git a/server/src/integrations/environment/environment.service.ts b/server/src/integrations/environment/environment.service.ts index 57be8a7b8..0e4f84003 100644 --- a/server/src/integrations/environment/environment.service.ts +++ b/server/src/integrations/environment/environment.service.ts @@ -8,6 +8,10 @@ import { StorageType } from './interfaces/storage.interface'; export class EnvironmentService { constructor(private configService: ConfigService) {} + getDebugMode(): boolean | undefined { + return this.configService.get('DEBUG_MODE')!; + } + getPGDatabaseUrl(): string { return this.configService.get('PG_DATABASE_URL')!; } diff --git a/server/src/integrations/environment/environment.validation.ts b/server/src/integrations/environment/environment.validation.ts index 1ef2f5e4e..18740e499 100644 --- a/server/src/integrations/environment/environment.validation.ts +++ b/server/src/integrations/environment/environment.validation.ts @@ -1,4 +1,4 @@ -import { plainToClass, Transform } from 'class-transformer'; +import { plainToClass } from 'class-transformer'; import { IsEnum, IsOptional, @@ -16,6 +16,12 @@ import { IsAWSRegion } from './decorators/is-aws-region.decorator'; import { CastToBoolean } from './decorators/cast-to-boolean.decorator'; export class EnvironmentVariables { + // Stage + @CastToBoolean() + @IsOptional() + @IsBoolean() + DEBUG_MODE?: boolean; + // Database @IsUrl({ protocols: ['postgres'], require_tld: false }) PG_DATABASE_URL: string; diff --git a/server/src/integrations/integrations.module.ts b/server/src/integrations/integrations.module.ts index d6b260435..30809754e 100644 --- a/server/src/integrations/integrations.module.ts +++ b/server/src/integrations/integrations.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Global, Module } from '@nestjs/common'; import { fromNodeProviderChain } from '@aws-sdk/credential-providers'; import { EnvironmentModule } from './environment/environment.module'; import { EnvironmentService } from './environment/environment.service'; diff --git a/server/yarn.lock b/server/yarn.lock index 69a62222e..a6c2295f9 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -2554,6 +2554,11 @@ "@smithy/types" "^1.1.0" tslib "^2.5.0" +"@sqltools/formatter@^1.2.3": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.5.tgz#3abc203c79b8c3e90fd6c156a0c62d5403520e12" + integrity sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw== + "@ts-morph/common@~0.17.0": version "0.17.0" resolved "https://registry.npmjs.org/@ts-morph/common/-/common-0.17.0.tgz" @@ -7037,6 +7042,13 @@ prisma-nestjs-graphql@^18.0.2: pupa "2.X" ts-morph ">=11 <=16" +prisma-query-log@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/prisma-query-log/-/prisma-query-log-3.2.0.tgz#6e620a7196456075b1eaddb7cb10b86cb7be2ab4" + integrity sha512-Em7u3eedHZR6JJSzEMDEwoyS9zy2MsdQLrKxkfTbLdJF2LwfMetRVDBtkGQdcxM4ntT3wFWGBi/zNR5Q107Jgw== + dependencies: + "@sqltools/formatter" "^1.2.3" + prisma@^4.13.0: version "4.15.0" resolved "https://registry.npmjs.org/prisma/-/prisma-4.15.0.tgz"