diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 099b74127..d7a4b46b0 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "ms-vscode-remote.remote-containers", "ms-vscode.makefile-tools", - "dbaeumer.vscode-eslint" + "dbaeumer.vscode-eslint", + "Prisma.prisma" ] } \ No newline at end of file diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index b5fe5c385..3c44a3eab 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -101,11 +101,28 @@ export type CommentThreadCreateNestedOneWithoutCommentsInput = { connect?: InputMaybe; }; +export type CommentThreadOrderByWithRelationInput = { + commentThreadTargets?: InputMaybe; + comments?: InputMaybe; + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + id?: InputMaybe; + updatedAt?: InputMaybe; +}; + export type CommentThreadRelationFilter = { is?: InputMaybe; isNot?: InputMaybe; }; +export enum CommentThreadScalarFieldEnum { + CreatedAt = 'createdAt', + DeletedAt = 'deletedAt', + Id = 'id', + UpdatedAt = 'updatedAt', + WorkspaceId = 'workspaceId' +} + export type CommentThreadTarget = { __typename?: 'CommentThreadTarget'; commentThread: CommentThread; @@ -142,6 +159,10 @@ export type CommentThreadTargetListRelationFilter = { some?: InputMaybe; }; +export type CommentThreadTargetOrderByRelationAggregateInput = { + _count?: InputMaybe; +}; + export type CommentThreadTargetWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -808,6 +829,7 @@ export type PipelineWhereUniqueInput = { export type Query = { __typename?: 'Query'; + findManyCommentThreads: Array; findManyCompany: Array; findManyPerson: Array; findManyPipeline: Array; @@ -816,6 +838,16 @@ export type Query = { }; +export type QueryFindManyCommentThreadsArgs = { + cursor?: InputMaybe; + distinct?: InputMaybe>; + orderBy?: InputMaybe>; + skip?: InputMaybe; + take?: InputMaybe; + where?: InputMaybe; +}; + + export type QueryFindManyCompanyArgs = { cursor?: InputMaybe; distinct?: InputMaybe>; @@ -1063,6 +1095,13 @@ export type GetPeopleCountsQueryVariables = Exact<{ export type GetPeopleCountsQuery = { __typename?: 'Query', people: Array<{ __typename?: 'Person', commentsCount: number }> }; +export type GetCommentThreadsByTargetsQueryVariables = Exact<{ + commentThreadTargetIds: Array | Scalars['String']; +}>; + + +export type GetCommentThreadsByTargetsQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: any, updatedAt: any, author: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } }> | null }> }; + export type GetCompaniesQueryVariables = Exact<{ orderBy?: InputMaybe | CompanyOrderByWithRelationInput>; where?: InputMaybe; @@ -1258,6 +1297,54 @@ export function useGetPeopleCountsLazyQuery(baseOptions?: Apollo.LazyQueryHookOp export type GetPeopleCountsQueryHookResult = ReturnType; export type GetPeopleCountsLazyQueryHookResult = ReturnType; export type GetPeopleCountsQueryResult = Apollo.QueryResult; +export const GetCommentThreadsByTargetsDocument = gql` + query GetCommentThreadsByTargets($commentThreadTargetIds: [String!]!) { + findManyCommentThreads( + where: {commentThreadTargets: {some: {commentableId: {in: $commentThreadTargetIds}}}} + ) { + id + comments { + id + body + createdAt + updatedAt + author { + id + displayName + avatarUrl + } + } + } +} + `; + +/** + * __useGetCommentThreadsByTargetsQuery__ + * + * To run a query within a React component, call `useGetCommentThreadsByTargetsQuery` and pass it any options that fit your needs. + * When your component renders, `useGetCommentThreadsByTargetsQuery` 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 } = useGetCommentThreadsByTargetsQuery({ + * variables: { + * commentThreadTargetIds: // value for 'commentThreadTargetIds' + * }, + * }); + */ +export function useGetCommentThreadsByTargetsQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetCommentThreadsByTargetsDocument, options); + } +export function useGetCommentThreadsByTargetsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetCommentThreadsByTargetsDocument, options); + } +export type GetCommentThreadsByTargetsQueryHookResult = ReturnType; +export type GetCommentThreadsByTargetsLazyQueryHookResult = ReturnType; +export type GetCommentThreadsByTargetsQueryResult = Apollo.QueryResult; export const GetCompaniesDocument = gql` query GetCompanies($orderBy: [CompanyOrderByWithRelationInput!], $where: CompanyWhereInput) { companies: findManyCompany(orderBy: $orderBy, where: $where) { diff --git a/front/src/modules/comments/components/comments/CommentThread.tsx b/front/src/modules/comments/components/comments/CommentThread.tsx new file mode 100644 index 000000000..df6eca6ae --- /dev/null +++ b/front/src/modules/comments/components/comments/CommentThread.tsx @@ -0,0 +1,27 @@ +import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer'; + +import { CommentTextInput } from './CommentTextInput'; + +type OwnProps = { + commentThread: CommentThreadForDrawer; +}; + +export function CommentThread({ commentThread }: OwnProps) { + function handleSendComment(text: string) { + console.log(text); + } + + return ( +
+ {commentThread.comments?.map((comment) => ( +
+
+ {comment.author?.displayName} - {comment.createdAt} +
+
{comment.body}
+
+ ))} + +
+ ); +} diff --git a/front/src/modules/comments/components/comments/RightDrawerComments.tsx b/front/src/modules/comments/components/comments/RightDrawerComments.tsx index 00a92862d..6bb17746e 100644 --- a/front/src/modules/comments/components/comments/RightDrawerComments.tsx +++ b/front/src/modules/comments/components/comments/RightDrawerComments.tsx @@ -1,30 +1,36 @@ import { useRecoilState } from 'recoil'; +import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer'; import { RightDrawerBody } from '@/ui/layout/right-drawer/components/RightDrawerBody'; import { RightDrawerPage } from '@/ui/layout/right-drawer/components/RightDrawerPage'; import { RightDrawerTopBar } from '@/ui/layout/right-drawer/components/RightDrawerTopBar'; +import { useGetCommentThreadsByTargetsQuery } from '~/generated/graphql'; import { commentableEntityArrayState } from '../../states/commentableEntityArrayState'; -import { CommentTextInput } from './CommentTextInput'; +import { CommentThread } from './CommentThread'; export function RightDrawerComments() { const [commentableEntityArray] = useRecoilState(commentableEntityArrayState); - function handleSendComment(text: string) { - console.log(text); - } + const { data: queryResult } = useGetCommentThreadsByTargetsQuery({ + variables: { + commentThreadTargetIds: commentableEntityArray.map( + (commentableEntity) => commentableEntity.id, + ), + }, + }); + + const commentThreads: CommentThreadForDrawer[] = + queryResult?.findManyCommentThreads ?? []; return ( - {commentableEntityArray.map((commentableEntity) => ( -
- {commentableEntity.type} - {commentableEntity.id} -
+ {commentThreads.map((commentThread) => ( + ))} -
); diff --git a/front/src/modules/comments/services/select.ts b/front/src/modules/comments/services/select.ts index 1ab1d820b..de08a0837 100644 --- a/front/src/modules/comments/services/select.ts +++ b/front/src/modules/comments/services/select.ts @@ -34,3 +34,28 @@ export const usePeopleCommentsCountQuery = (personId: string) => { }); return { ...rest, data: data?.people[0].commentsCount }; }; + +export const GET_COMMENT_THREADS_BY_TARGETS = gql` + query GetCommentThreadsByTargets($commentThreadTargetIds: [String!]!) { + findManyCommentThreads( + where: { + commentThreadTargets: { + some: { commentableId: { in: $commentThreadTargetIds } } + } + } + ) { + id + comments { + id + body + createdAt + updatedAt + author { + id + displayName + avatarUrl + } + } + } + } +`; diff --git a/front/src/modules/comments/types/CommentThreadForDrawer.ts b/front/src/modules/comments/types/CommentThreadForDrawer.ts new file mode 100644 index 000000000..79f969300 --- /dev/null +++ b/front/src/modules/comments/types/CommentThreadForDrawer.ts @@ -0,0 +1,4 @@ +import { GetCommentThreadsByTargetsQuery } from '~/generated/graphql'; + +export type CommentThreadForDrawer = + GetCommentThreadsByTargetsQuery['findManyCommentThreads'][0]; diff --git a/server/src/api/api.module.ts b/server/src/api/api.module.ts index a451aff9e..a33870630 100644 --- a/server/src/api/api.module.ts +++ b/server/src/api/api.module.ts @@ -23,6 +23,7 @@ import { CommentThreadRelationsResolver } from './resolvers/relations/comment-th import { PipelineRelationsResolver } from './resolvers/relations/pipeline-relations.resolver'; import { PipelineStageRelationsResolver } from './resolvers/relations/pipeline-stage-relations.resolver'; import { GraphQLError } from 'graphql'; +import { CommentRelationsResolver } from './resolvers/relations/comment-relations.resolver'; @Module({ imports: [ @@ -51,6 +52,7 @@ import { GraphQLError } from 'graphql'; PipelineStageResolver, CompanyRelationsResolver, + CommentRelationsResolver, PersonRelationsResolver, UserRelationsResolver, WorkspaceMemberRelationsResolver, diff --git a/server/src/api/resolvers/comment-thread.resolver.ts b/server/src/api/resolvers/comment-thread.resolver.ts index 26b2ba30c..031a098d8 100644 --- a/server/src/api/resolvers/comment-thread.resolver.ts +++ b/server/src/api/resolvers/comment-thread.resolver.ts @@ -1,4 +1,4 @@ -import { Resolver, Args, Mutation } from '@nestjs/graphql'; +import { Resolver, Args, Mutation, Query } from '@nestjs/graphql'; import { UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard'; import { PrismaService } from 'src/database/prisma.service'; @@ -7,11 +7,16 @@ import { AuthWorkspace } from './decorators/auth-workspace.decorator'; import { CommentThread } from '../@generated/comment-thread/comment-thread.model'; import { CreateOneCommentThreadArgs } from '../@generated/comment-thread/create-one-comment-thread.args'; import { CreateOneCommentThreadGuard } from './guards/create-one-comment-thread.guard'; +import { FindManyCommentThreadArgs } from '../@generated/comment-thread/find-many-comment-thread.args'; +import { ArgsService } from './services/args.service'; @UseGuards(JwtAuthGuard) @Resolver(() => CommentThread) export class CommentThreadResolver { - constructor(private readonly prismaService: PrismaService) {} + constructor( + private readonly prismaService: PrismaService, + private readonly argsService: ArgsService, + ) {} @UseGuards(CreateOneCommentThreadGuard) @Mutation(() => CommentThread, { @@ -35,4 +40,21 @@ export class CommentThreadResolver { }, }); } + + @Query(() => [CommentThread]) + async findManyCommentThreads( + @Args() args: FindManyCommentThreadArgs, + @AuthWorkspace() workspace: Workspace, + ) { + const preparedArgs = + await this.argsService.prepareFindManyArgs( + args, + workspace, + ); + const result = await this.prismaService.commentThread.findMany( + preparedArgs, + ); + + return result; + } } diff --git a/server/src/api/resolvers/relations/comment-relations.resolver.ts b/server/src/api/resolvers/relations/comment-relations.resolver.ts new file mode 100644 index 000000000..d65c900e3 --- /dev/null +++ b/server/src/api/resolvers/relations/comment-relations.resolver.ts @@ -0,0 +1,22 @@ +import * as TypeGraphQL from '@nestjs/graphql'; +import { PrismaService } from 'src/database/prisma.service'; +import { User } from 'src/api/@generated/user/user.model'; +import { Comment } from 'src/api/@generated/comment/comment.model'; + +@TypeGraphQL.Resolver(() => Comment) +export class CommentRelationsResolver { + constructor(private readonly prismaService: PrismaService) {} + + @TypeGraphQL.ResolveField(() => User, { + nullable: true, + }) + async author(@TypeGraphQL.Parent() comment: Comment): Promise { + return await this.prismaService.comment + .findFirst({ + where: { + id: comment.id, + }, + }) + .author({}); + } +}