Skip to content

Commit

Permalink
Merge pull request #2256 from HS-90/editComments
Browse files Browse the repository at this point in the history
Edit Comments GraphQL query and resolver
  • Loading branch information
HS-90 authored Sep 5, 2022
2 parents aa2d4b6 + 11414cf commit 100107e
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 51 deletions.
209 changes: 158 additions & 51 deletions graphql/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export type Mutation = {
deleteComment?: Maybe<Comment>
deleteExercise: Exercise
deleteModule: Module
editComment?: Maybe<Comment>
flagExercise?: Maybe<Exercise>
login?: Maybe<AuthResponse>
logout?: Maybe<AuthResponse>
Expand Down Expand Up @@ -226,6 +227,11 @@ export type MutationDeleteModuleArgs = {
id: Scalars['Int']
}

export type MutationEditCommentArgs = {
content: Scalars['String']
id: Scalars['Int']
}

export type MutationFlagExerciseArgs = {
flagReason: Scalars['String']
id: Scalars['Int']
Expand Down Expand Up @@ -421,6 +427,57 @@ export type UserLesson = {
userId?: Maybe<Scalars['String']>
}

export type LessonAndChallengeInfoFragment = {
__typename?: 'Lesson'
id: number
docUrl?: string | null
githubUrl?: string | null
videoUrl?: string | null
chatUrl?: string | null
order: number
description: string
title: string
challenges: Array<{
__typename?: 'Challenge'
id: number
description: string
lessonId: number
title: string
order: number
}>
}

export type SubmissionsInfoFragment = {
__typename?: 'Submission'
id: number
status: SubmissionStatus
diff?: string | null
comment?: string | null
challengeId: number
lessonId: number
createdAt?: string | null
updatedAt: string
challenge: { __typename?: 'Challenge'; title: string; description: string }
user: { __typename?: 'User'; id: number; username: string }
reviewer?: {
__typename?: 'User'
id: number
username: string
name: string
} | null
comments?: Array<{
__typename?: 'Comment'
id: number
content: string
submissionId: number
createdAt: string
authorId: number
line?: number | null
fileName?: string | null
author?: { __typename?: 'User'; username: string; name: string } | null
}> | null
}

export type AcceptSubmissionMutationVariables = Exact<{
submissionId: Scalars['Int']
comment: Scalars['String']
Expand Down Expand Up @@ -659,57 +716,6 @@ export type FlagExerciseMutation = {
flagExercise?: { __typename?: 'Exercise'; id: number } | null
}

export type LessonAndChallengeInfoFragment = {
__typename?: 'Lesson'
id: number
docUrl?: string | null
githubUrl?: string | null
videoUrl?: string | null
chatUrl?: string | null
order: number
description: string
title: string
challenges: Array<{
__typename?: 'Challenge'
id: number
description: string
lessonId: number
title: string
order: number
}>
}

export type SubmissionsInfoFragment = {
__typename?: 'Submission'
id: number
status: SubmissionStatus
diff?: string | null
comment?: string | null
challengeId: number
lessonId: number
createdAt?: string | null
updatedAt: string
challenge: { __typename?: 'Challenge'; title: string; description: string }
user: { __typename?: 'User'; id: number; username: string }
reviewer?: {
__typename?: 'User'
id: number
username: string
name: string
} | null
comments?: Array<{
__typename?: 'Comment'
id: number
content: string
submissionId: number
createdAt: string
authorId: number
line?: number | null
fileName?: string | null
author?: { __typename?: 'User'; username: string; name: string } | null
}> | null
}

export type GetAppQueryVariables = Exact<{ [key: string]: never }>

export type GetAppQuery = {
Expand Down Expand Up @@ -1229,6 +1235,16 @@ export type UserInfoQuery = {
} | null
}

export type EditCommentMutationVariables = Exact<{
id: Scalars['Int']
content: Scalars['String']
}>

export type EditCommentMutation = {
__typename?: 'Mutation'
editComment?: { __typename?: 'Comment'; id: number; content: string } | null
}

export type WithIndex<TObject> = TObject & Record<string, any>
export type ResolversObject<TObject> = WithIndex<TObject>

Expand Down Expand Up @@ -1606,6 +1622,12 @@ export type MutationResolvers<
ContextType,
RequireFields<MutationDeleteModuleArgs, 'id'>
>
editComment?: Resolver<
Maybe<ResolversTypes['Comment']>,
ParentType,
ContextType,
RequireFields<MutationEditCommentArgs, 'content' | 'id'>
>
flagExercise?: Resolver<
Maybe<ResolversTypes['Exercise']>,
ParentType,
Expand Down Expand Up @@ -5212,6 +5234,89 @@ export type UserInfoQueryResult = Apollo.QueryResult<
UserInfoQuery,
UserInfoQueryVariables
>
export const EditCommentDocument = gql`
mutation editComment($id: Int!, $content: String!) {
editComment(id: $id, content: $content) {
id
content
}
}
`
export type EditCommentMutationFn = Apollo.MutationFunction<
EditCommentMutation,
EditCommentMutationVariables
>
export type EditCommentProps<
TChildProps = {},
TDataName extends string = 'mutate'
> = {
[key in TDataName]: Apollo.MutationFunction<
EditCommentMutation,
EditCommentMutationVariables
>
} & TChildProps
export function withEditComment<
TProps,
TChildProps = {},
TDataName extends string = 'mutate'
>(
operationOptions?: ApolloReactHoc.OperationOption<
TProps,
EditCommentMutation,
EditCommentMutationVariables,
EditCommentProps<TChildProps, TDataName>
>
) {
return ApolloReactHoc.withMutation<
TProps,
EditCommentMutation,
EditCommentMutationVariables,
EditCommentProps<TChildProps, TDataName>
>(EditCommentDocument, {
alias: 'editComment',
...operationOptions
})
}

/**
* __useEditCommentMutation__
*
* To run a mutation, you first call `useEditCommentMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useEditCommentMutation` 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 [editCommentMutation, { data, loading, error }] = useEditCommentMutation({
* variables: {
* id: // value for 'id'
* content: // value for 'content'
* },
* });
*/
export function useEditCommentMutation(
baseOptions?: Apollo.MutationHookOptions<
EditCommentMutation,
EditCommentMutationVariables
>
) {
const options = { ...defaultOptions, ...baseOptions }
return Apollo.useMutation<EditCommentMutation, EditCommentMutationVariables>(
EditCommentDocument,
options
)
}
export type EditCommentMutationHookResult = ReturnType<
typeof useEditCommentMutation
>
export type EditCommentMutationResult =
Apollo.MutationResult<EditCommentMutation>
export type EditCommentMutationOptions = Apollo.BaseMutationOptions<
EditCommentMutation,
EditCommentMutationVariables
>
export type AlertKeySpecifier = (
| 'id'
| 'text'
Expand Down Expand Up @@ -5365,6 +5470,7 @@ export type MutationKeySpecifier = (
| 'deleteComment'
| 'deleteExercise'
| 'deleteModule'
| 'editComment'
| 'flagExercise'
| 'login'
| 'logout'
Expand Down Expand Up @@ -5395,6 +5501,7 @@ export type MutationFieldPolicy = {
deleteComment?: FieldPolicy<any> | FieldReadFunction<any>
deleteExercise?: FieldPolicy<any> | FieldReadFunction<any>
deleteModule?: FieldPolicy<any> | FieldReadFunction<any>
editComment?: FieldPolicy<any> | FieldReadFunction<any>
flagExercise?: FieldPolicy<any> | FieldReadFunction<any>
login?: FieldPolicy<any> | FieldReadFunction<any>
logout?: FieldPolicy<any> | FieldReadFunction<any>
Expand Down
12 changes: 12 additions & 0 deletions graphql/queries/editComment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { gql } from '@apollo/client'

const EDIT_COMMENT = gql`
mutation editComment($id: Int!, $content: String!) {
editComment(id: $id, content: $content) {
id
content
}
}
`

export default EDIT_COMMENT
2 changes: 2 additions & 0 deletions graphql/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { createLesson, updateLesson } from './resolvers/lessonsController'
import { getPreviousSubmissions } from './resolvers/getPreviousSubmissions'
import { deleteComment } from './resolvers/deleteComment'
import { unlinkDiscord } from './resolvers/unlinkDiscord'
import { editComment } from './resolvers/editComment'
import {
addModule,
modules,
Expand Down Expand Up @@ -77,6 +78,7 @@ export default {
updateModule,
deleteModule,
addComment,
editComment,
deleteComment,
flagExercise,
removeExerciseFlag,
Expand Down
46 changes: 46 additions & 0 deletions graphql/resolvers/editComment.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import prismaMock from '../../__tests__/utils/prismaMock'
import { editComment } from './editComment'

const mockEditComment = {
id: 2,
content: 'i edited this comment'
}

describe('Edit comments resolver', () => {
test('should invoke prismaMock update', () => {
expect.assertions(1)
prismaMock.comment.update.mockResolvedValue({
id: 2,
authorId: 1
})
prismaMock.comment.findUnique.mockResolvedValue({
authorId: 1
})
expect(
editComment({}, mockEditComment, { req: { user: { id: 1 } } })
).resolves.toEqual({
authorId: 1,
id: 2
})
})

test('should throw error if no user.id in context', () => {
expect.assertions(1)
expect(editComment({}, mockEditComment, { req: {} })).rejects.toThrow(
'No user'
)
})

test('should throw error if user.id does not match author.id', () => {
expect.assertions(1)
expect(
editComment(
{},
{
authorId: 2
},
{ req: { user: { id: 1 } } }
)
).rejects.toThrow('Comment is not by the user')
})
})
31 changes: 31 additions & 0 deletions graphql/resolvers/editComment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import prisma from '../../prisma'
import { MutationEditCommentArgs } from '../index'
import { Context } from '../../@types/helpers'
import type { Comment } from '@prisma/client'
import { withUserContainer } from '../../containers/withUserContainer'
import _ from 'lodash'

export const editComment = withUserContainer<
Promise<Comment>,
MutationEditCommentArgs
>(async (_parent: void, args: MutationEditCommentArgs, ctx: Context) => {
const { id, content } = args
const { req } = ctx
const authorId = _.get(req, 'user.id')

const comment = await prisma.comment.findUnique({
where: {
id
}
})

if (_.get(comment, 'authorId') !== authorId)
throw new Error('Comment is not by the user')

return prisma.comment.update({
where: {
id
},
data: { content }
})
})
1 change: 1 addition & 0 deletions graphql/typeDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export default gql`
content: String!
): Comment
deleteComment(id: Int!): Comment
editComment(id: Int!, content: String!): Comment
addModule(
lessonId: Int!
name: String!
Expand Down

1 comment on commit 100107e

@vercel
Copy link

@vercel vercel bot commented on 100107e Sep 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.