diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-05-15 17:45:41 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-05-15 19:06:42 +0200 |
| commit | c95cce04393080a52a54191cff7be8fec68af4b0 (patch) | |
| tree | 1022bc574c8fc8e657be922b26c1cf16cbfd9071 /src/services | |
| parent | 235fe67d770f83131c9ec10b99012319440db690 (diff) | |
chore: add Article pages
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; +}; |
