diff options
Diffstat (limited to 'src/services')
| -rw-r--r-- | src/services/graphql/api.ts | 52 | ||||
| -rw-r--r-- | src/services/graphql/comments.mutation.ts | 30 | ||||
| -rw-r--r-- | src/services/graphql/comments.ts | 102 | 
3 files changed, 183 insertions, 1 deletions
| diff --git a/src/services/graphql/api.ts b/src/services/graphql/api.ts index 171ab23..9f68ddc 100644 --- a/src/services/graphql/api.ts +++ b/src/services/graphql/api.ts @@ -6,6 +6,7 @@ import {    articlesSlugQuery,    totalArticlesQuery,  } from './articles.query'; +import { sendCommentMutation } from './comments.mutation';  import { commentsQuery } from './comments.query';  import { sendMailMutation } from './contact.mutation';  import { @@ -21,7 +22,7 @@ import {    totalTopicsQuery,  } from './topics.query'; -export type Mutations = typeof sendMailMutation; +export type Mutations = typeof sendMailMutation | typeof sendCommentMutation;  export type Queries =    | typeof articlesQuery @@ -51,6 +52,10 @@ export type CommentsResponse<T> = {    comments: T;  }; +export type SendCommentResponse<T> = { +  createComment: T; +}; +  export type SendMailResponse<T> = {    sendEmail: T;  }; @@ -101,6 +106,7 @@ export type ResponseMap<T> = {    [articlesQuery]: ArticlesResponse<EdgesResponse<T>>;    [articlesSlugQuery]: ArticlesResponse<EdgesResponse<T>>;    [commentsQuery]: CommentsResponse<NodesResponse<T>>; +  [sendCommentMutation]: SendCommentResponse<T>;    [sendMailMutation]: SendMailResponse<T>;    [thematicBySlugQuery]: ThematicResponse<T>;    [thematicsListQuery]: ThematicsResponse<EdgesResponse<T>>; @@ -154,10 +160,53 @@ export type SearchVar = {    search?: string;  }; +export type SendCommentVars = { +  /** +   * The author name. +   */ +  author: string; +  /** +   * The author e-mail address. +   */ +  authorEmail: string; +  /** +   * The author website. +   */ +  authorUrl: string; +  /** +   * A mutation id. +   */ +  clientMutationId: string; +  /** +   * A post or page id. +   */ +  commentOn: number; +  /** +   * The comment body. +   */ +  content: string; +  /** +   * The comment parent. +   */ +  parent?: number; +}; +  export type SendMailVars = { +  /** +   * The mail body. +   */    body: string; +  /** +   * A mutation id. +   */    clientMutationId: string; +  /** +   * The reply to e-mail address. +   */    replyTo: string; +  /** +   * The mail subject. +   */    subject: string;  }; @@ -167,6 +216,7 @@ export type VariablesMap = {    [articlesQuery]: EdgesVars;    [articlesSlugQuery]: EdgesVars;    [commentsQuery]: ByContentIdVar; +  [sendCommentMutation]: SendCommentVars;    [sendMailMutation]: SendMailVars;    [thematicBySlugQuery]: BySlugVar;    [thematicsListQuery]: EdgesVars; diff --git a/src/services/graphql/comments.mutation.ts b/src/services/graphql/comments.mutation.ts new file mode 100644 index 0000000..f52c7e9 --- /dev/null +++ b/src/services/graphql/comments.mutation.ts @@ -0,0 +1,30 @@ +/** + * Send comment mutation. + */ +export const sendCommentMutation = `mutation CreateComment( +  $author: String! +  $authorEmail: String! +  $authorUrl: String! +  $content: String! +  $parent: ID = null +  $commentOn: Int! +  $clientMutationId: String! +) { +  createComment( +    input: { +      author: $author +      authorEmail: $authorEmail +      authorUrl: $authorUrl +      content: $content +      parent: $parent +      commentOn: $commentOn +      clientMutationId: $clientMutationId +    } +  ) { +    clientMutationId +    success +    comment { +      approved +    } +  } +}`; diff --git a/src/services/graphql/comments.ts b/src/services/graphql/comments.ts new file mode 100644 index 0000000..28ddfd0 --- /dev/null +++ b/src/services/graphql/comments.ts @@ -0,0 +1,102 @@ +import { Comment } from '@ts/types/app'; +import { RawComment } from '@ts/types/raw-data'; +import { getAuthorFromRawData } from '@utils/helpers/author'; +import { fetchAPI, getAPIUrl, SendCommentVars } from './api'; +import { sendCommentMutation } from './comments.mutation'; +import { commentsQuery } from './comments.query'; + +/** + * Create a comments tree with replies. + * + * @param {Comment[]} comments - A flatten comments list. + * @returns {Comment[]} An array of comments with replies. + */ +export const buildCommentsTree = (comments: Comment[]): Comment[] => { +  type CommentsHashTable = { +    [key: string]: Comment; +  }; + +  const hashTable: CommentsHashTable = Object.create(null); +  const commentsTree: Comment[] = []; + +  comments.forEach( +    (comment) => (hashTable[comment.id] = { ...comment, replies: [] }) +  ); + +  comments.forEach((comment) => { +    if (!comment.parentId) { +      commentsTree.push(hashTable[comment.id]); +    } else { +      hashTable[comment.parentId].replies.push(hashTable[comment.id]); +    } +  }); + +  return commentsTree; +}; + +/** + * Convert a comment from RawComment to Comment type. + * + * @param {RawComment} comment - A raw comment. + * @returns {Comment} A formatted comment. + */ +export const getCommentFromRawData = (comment: RawComment): Comment => { +  const { author, databaseId, date, parentDatabaseId, ...data } = comment; + +  return { +    id: databaseId, +    meta: { +      author: getAuthorFromRawData(author.node, 'comment'), +      date, +    }, +    parentId: parentDatabaseId, +    replies: [], +    ...data, +  }; +}; + +/** + * Retrieve a comments list by post id. + * + * @param {number} id - A post id. + * @returns {Promise<Comment[]>} The comments list. + */ +export const getPostComments = async (id: number): Promise<Comment[]> => { +  const response = await fetchAPI<RawComment, typeof commentsQuery>({ +    api: getAPIUrl(), +    query: commentsQuery, +    variables: { contentId: id }, +  }); + +  const comments = response.comments.nodes.map((comment) => +    getCommentFromRawData(comment) +  ); + +  return buildCommentsTree(comments); +}; + +export type SentComment = { +  clientMutationId: string; +  success: boolean; +  comment: { +    approved: boolean; +  } | null; +}; + +/** + * Send a comment using GraphQL API. + * + * @param {SendCommentVars} data - The comment data. + * @returns {Promise<SentEmail>} The mutation response. + */ +export const sendComment = async ( +  data: SendCommentVars +): Promise<SentComment> => { +  const response = await fetchAPI<SentComment, typeof sendCommentMutation>({ +    api: getAPIUrl(), +    query: sendCommentMutation, +    variables: { ...data }, +  }); + +  return response.createComment; +}; | 
