aboutsummaryrefslogtreecommitdiffstats
path: root/src/services/graphql
diff options
context:
space:
mode:
Diffstat (limited to 'src/services/graphql')
-rw-r--r--src/services/graphql/comments.query.ts37
-rw-r--r--src/services/graphql/comments.ts144
2 files changed, 128 insertions, 53 deletions
diff --git a/src/services/graphql/comments.query.ts b/src/services/graphql/comments.query.ts
index ef93e89..5110db3 100644
--- a/src/services/graphql/comments.query.ts
+++ b/src/services/graphql/comments.query.ts
@@ -1,21 +1,32 @@
/**
* Query the comments data by post id.
*/
-export const commentsQuery = `query CommentsByPostId($contentId: ID!) {
- comments(where: {contentId: $contentId, order: ASC, orderby: COMMENT_DATE}) {
- nodes {
- approved
- author {
- node {
- gravatarUrl
- name
- url
+export const commentsQuery = `query CommentsByPostId($contentId: ID!, $first: Int = 10, $after: String = "") {
+ comments(
+ where: {contentId: $contentId}
+ first: $first
+ after: $after
+ ) {
+ edges {
+ cursor
+ node {
+ approved
+ author {
+ node {
+ gravatarUrl
+ name
+ url
+ }
}
+ content
+ databaseId
+ date
+ parentDatabaseId
}
- content
- databaseId
- date
- parentDatabaseId
+ }
+ pageInfo {
+ hasNextPage
+ endCursor
}
}
}`;
diff --git a/src/services/graphql/comments.ts b/src/services/graphql/comments.ts
index 86b6a35..41f80b3 100644
--- a/src/services/graphql/comments.ts
+++ b/src/services/graphql/comments.ts
@@ -1,46 +1,61 @@
-import { Comment } from '@ts/types/app';
+import { SingleComment } from '@ts/types/app';
import { GraphQLEdgesInput } from '@ts/types/graphql/generics';
import { SendCommentInput, SentComment } from '@ts/types/graphql/mutations';
import { ContentId } from '@ts/types/graphql/queries';
-import { RawComment } from '@ts/types/raw-data';
+import { RawComment, RawCommentsPage } from '@ts/types/raw-data';
import { getAuthorFromRawData } from '@utils/helpers/author';
import { fetchAPI } from './api';
import { sendCommentMutation } from './comments.mutation';
import { commentsQuery } from './comments.query';
-type FetchCommentsInput = ContentId &
- Pick<GraphQLEdgesInput, 'after' | 'first'>;
-
/**
- * Retrieve the comments list from GraphQL.
+ * Convert a comment from RawComment type to SingleComment type.
*
- * @param {FetchCommentsInput} variables - An object of variables.
- * @returns {Promise<RawComment[]>} The raw comments.
+ * @param {RawComment} comment - A raw comment.
+ * @returns {SingleComment} A formatted comment.
*/
-export const fetchComments = async (
- variables: FetchCommentsInput
-): Promise<RawComment[]> => {
- const response = await fetchAPI<RawComment, typeof commentsQuery>({
- query: commentsQuery,
- variables,
- });
+export const getCommentFromRawData = (comment: RawComment): SingleComment => {
+ const { author, databaseId, date, parentDatabaseId, ...data } = comment;
- return response.comments.nodes;
+ return {
+ id: databaseId,
+ meta: {
+ author: getAuthorFromRawData(author.node, 'comment'),
+ date,
+ },
+ parentId: parentDatabaseId === 0 ? undefined : parentDatabaseId,
+ replies: [],
+ ...data,
+ };
+};
+
+/**
+ * Convert an array of RawComment type to an array of SingleComment type.
+ *
+ * @param {RawComment[]} comments - The raw comments.
+ * @returns {SingleComment[]} The formatted comments.
+ */
+export const getCommentsFromRawData = (
+ comments: RawComment[]
+): SingleComment[] => {
+ return comments.map((comment) => getCommentFromRawData(comment));
};
/**
* Create a comments tree with replies.
*
- * @param {Comment[]} comments - A flatten comments list.
- * @returns {Comment[]} An array of comments with replies.
+ * @param {SingleComment[]} comments - A flatten comments list.
+ * @returns {SingleComment[]} An array of comments with replies.
*/
-export const buildCommentsTree = (comments: Comment[]): Comment[] => {
+export const buildCommentsTree = (
+ comments: SingleComment[]
+): SingleComment[] => {
type CommentsHashTable = {
- [key: string]: Comment;
+ [key: string]: SingleComment;
};
const hashTable: CommentsHashTable = Object.create(null);
- const commentsTree: Comment[] = [];
+ const commentsTree: SingleComment[] = [];
comments.forEach(
(comment) => (hashTable[comment.id] = { ...comment, replies: [] })
@@ -57,36 +72,85 @@ export const buildCommentsTree = (comments: Comment[]): Comment[] => {
return commentsTree;
};
+type FetchCommentsInput = ContentId &
+ Pick<GraphQLEdgesInput, 'after' | 'first'>;
+
/**
- * Convert a comment from RawComment to Comment type.
+ * Retrieve a raw comments page from GraphQL.
*
- * @param {RawComment} comment - A raw comment.
- * @returns {Comment} A formatted comment.
+ * @param {FetchCommentsInput} variables - An object of variables.
+ * @returns {Promise<RawCommentsPage>} A raw comments page.
*/
-export const getCommentFromRawData = (comment: RawComment): Comment => {
- const { author, databaseId, date, parentDatabaseId, ...data } = comment;
+export const fetchRawComments = async (
+ variables: FetchCommentsInput
+): Promise<RawCommentsPage> => {
+ const response = await fetchAPI<RawComment, typeof commentsQuery>({
+ query: commentsQuery,
+ variables,
+ });
return {
- id: databaseId,
- meta: {
- author: getAuthorFromRawData(author.node, 'comment'),
- date,
- },
- parentId: parentDatabaseId,
- replies: [],
- ...data,
+ comments: response.comments.edges.map((edge) => edge.node),
+ hasNextPage: response.comments.pageInfo.hasNextPage,
+ endCursor: response.comments.pageInfo.endCursor,
};
};
/**
- * Retrieve a comments list by post id.
+ * Fetch recursively all the comments on a post.
+ *
+ * @param {FetchCommentsInput} variables - An object of query variables.
+ * @param {RawCommentsPage[]} pages - An accumulator to keep track of pages.
+ * @returns {Promise<RawCommentsPage[]>} The raw comments pages.
+ */
+export const fetchAllRawCommentsPages = async (
+ variables: FetchCommentsInput,
+ pages: RawCommentsPage[] = []
+): Promise<RawCommentsPage[]> => {
+ return fetchRawComments(variables).then((page) => {
+ pages.push(page);
+
+ if (page.hasNextPage) {
+ return fetchAllRawCommentsPages(
+ { ...variables, after: page.endCursor },
+ pages
+ );
+ } else {
+ return pages;
+ }
+ });
+};
+
+/**
+ * Method to compare two comments dates and sort them from older to newest.
+ *
+ * @param {SingleComment} a - A comment.
+ * @param {SingleComment} b - Another comment.
+ * @returns {number} The difference between dates.
+ */
+export const compareCommentsDate = (
+ a: SingleComment,
+ b: SingleComment
+): number => {
+ return +new Date(a.meta.date) - +new Date(b.meta.date);
+};
+
+/**
+ * Retrieve all the comments on a post.
*
* @param {number} id - A post id.
- * @returns {Promise<Comment[]>} The comments list.
+ * @returns {Promise<SingleComment[]>} The comments list.
*/
-export const getPostComments = async (id: number): Promise<Comment[]> => {
- const rawComments = await fetchComments({ contentId: id });
- const comments = rawComments.map((comment) => getCommentFromRawData(comment));
+export const getAllComments = async ({
+ contentId,
+}: {
+ contentId: number;
+}): Promise<SingleComment[]> => {
+ const pages = await fetchAllRawCommentsPages({ contentId });
+ const comments = pages
+ .map((page) => getCommentsFromRawData(page.comments))
+ .flat()
+ .sort(compareCommentsDate);
return buildCommentsTree(comments);
};
@@ -95,7 +159,7 @@ export const getPostComments = async (id: number): Promise<Comment[]> => {
* Send a comment using GraphQL API.
*
* @param {SendCommentVars} data - The comment data.
- * @returns {Promise<SentEmail>} The mutation response.
+ * @returns {Promise<SentComment>} The mutation response.
*/
export const sendComment = async (
data: SendCommentInput