Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 87 additions & 5 deletions apps/admin-x-framework/src/api/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export type Comment = {
html: string | null;
status: 'published' | 'hidden' | 'deleted';
pinned: boolean;
liked?: boolean;
disliked?: boolean;
created_at: string;
updated_at: string;
post_id: string;
Expand All @@ -32,6 +34,7 @@ export type Comment = {
replies?: number;
direct_replies?: number;
likes?: number;
dislikes?: number;
reports?: number;
};
// Optional nested replies for tree structures
Expand All @@ -51,6 +54,17 @@ export type CommentLike = {
id: string;
comment_id: string;
member_id: string;
score: number;
created_at: string;
updated_at: string;
member?: Member;
};

export type CommentDislike = {
id: string;
comment_id: string;
member_id: string;
score: number;
created_at: string;
updated_at: string;
member?: Member;
Expand All @@ -62,6 +76,42 @@ export interface CommentsResponseType {
}

const dataType = 'CommentsResponseType';
const commentDislikeIncludes = 'count.dislikes';
const commentDislikeMemberIncludes = 'count.dislikes,disliked';

export const adminCommentIncludes = (dislikesEnabled: boolean) => [
'member',
'post',
'count.replies',
'count.direct_replies',
'count.likes',
...(dislikesEnabled ? [commentDislikeIncludes] : []),
'count.reports',
'parent',
'in_reply_to'
].join(',');

export const memberCommentIncludes = (dislikesEnabled: boolean) => [
'member',
'post',
'count.replies',
'count.direct_replies',
'count.likes',
...(dislikesEnabled ? [commentDislikeMemberIncludes] : []),
'parent',
'in_reply_to'
].join(',');

export const memberThreadCommentIncludes = (dislikesEnabled: boolean) => [
'member',
'post',
'count.direct_replies',
'count.likes',
...(dislikesEnabled ? [commentDislikeIncludes] : []),
'count.reports',
'parent',
'in_reply_to'
].join(',');

const useBrowseCommentsQuery = createInfiniteQuery<CommentsResponseType>({
dataType,
Expand Down Expand Up @@ -176,14 +226,25 @@ export const useCommentReplies = createQueryWithId<CommentsResponseType>({
}
});

export const useReadComment = createQueryWithId<CommentsResponseType>({
const useReadCommentQuery = createQueryWithId<CommentsResponseType>({
dataType,
path: (id: string) => `/comments/${id}/`,
defaultSearchParams: {
include: 'member,post,count.replies,count.direct_replies,count.likes,count.reports,parent,in_reply_to'
include: adminCommentIncludes(false)
}
});

export const useReadComment = (commentId: string, options?: Parameters<typeof useReadCommentQuery>[1] & {dislikesEnabled?: boolean}) => {
const {dislikesEnabled = false, searchParams, ...queryOptions} = options || {};
return useReadCommentQuery(commentId, {
...queryOptions,
searchParams: {
include: adminCommentIncludes(dislikesEnabled),
...searchParams
}
});
};

export interface CommentReportsResponseType {
meta?: Meta;
comment_reports: CommentReport[];
Expand Down Expand Up @@ -217,18 +278,39 @@ export const useBrowseCommentLikes = (commentId: string, options?: {enabled?: bo
return useBrowseCommentLikesQuery(commentId, {...options});
};

export interface CommentDislikesResponseType {
meta?: Meta;
comment_dislikes: CommentDislike[];
}

const useBrowseCommentDislikesQuery = createQueryWithId<CommentDislikesResponseType>({
dataType: 'CommentDislikesResponseType',
path: id => `/comments/${id}/dislikes/`,
defaultSearchParams: {
include: 'member',
limit: '100',
order: 'created_at desc'
}
});

export const useBrowseCommentDislikes = (commentId: string, options?: {enabled?: boolean}) => {
return useBrowseCommentDislikesQuery(commentId, {...options});
};

/**
* Fetches direct replies for a thread view.
* - For top-level comments: returns comments where parent_id matches AND in_reply_to_id is null
* - For nested comments: returns comments where in_reply_to_id matches
*/
export const useThreadComments = (commentId: string, options?: {enabled?: boolean}) => {
export const useThreadComments = (commentId: string, options?: {enabled?: boolean; dislikesEnabled?: boolean}) => {
const {dislikesEnabled = false, ...queryOptions} = options || {};

return useBrowseComments({
...options,
...queryOptions,
searchParams: {
filter: `(parent_id:${commentId}+in_reply_to_id:null),in_reply_to_id:${commentId}`,
order: 'created_at asc',
include: 'member,post,count.direct_replies,count.likes,count.reports,parent,in_reply_to',
include: memberThreadCommentIncludes(dislikesEnabled),
limit: '100'
}
});
Expand Down
3 changes: 3 additions & 0 deletions apps/admin-x-framework/src/utils/api/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {useFramework} from '../../providers/framework-provider';
import {RequestOptions, apiUrl, useFetchApi} from './fetch-api';

export interface Meta {
capabilities?: {
dislikes?: boolean;
};
pagination: {
page: number;
limit: number | 'all';
Expand Down
2 changes: 1 addition & 1 deletion apps/comments-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tryghost/comments-ui",
"version": "1.4.20",
"version": "1.5.0",
"license": "MIT",
"repository": "https://github.com/TryGhost/Ghost",
"author": "Ghost Foundation",
Expand Down
Loading
Loading