summaryrefslogtreecommitdiffstats
path: root/src/services
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-05-15 17:45:41 +0200
committerArmand Philippot <git@armandphilippot.com>2022-05-15 19:06:42 +0200
commitc95cce04393080a52a54191cff7be8fec68af4b0 (patch)
tree1022bc574c8fc8e657be922b26c1cf16cbfd9071 /src/services
parent235fe67d770f83131c9ec10b99012319440db690 (diff)
chore: add Article pages
Diffstat (limited to 'src/services')
-rw-r--r--src/services/graphql/api.ts52
-rw-r--r--src/services/graphql/comments.mutation.ts30
-rw-r--r--src/services/graphql/comments.ts102
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;
+};