mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added Best Comment to top of API output (#21374)
ref PLG-220 - Added the ability to move the Best comment to the first entry when order=best is passed as params.
This commit is contained in:
parent
1b468f333b
commit
1e8bb253bf
3 changed files with 108 additions and 0 deletions
|
@ -202,6 +202,21 @@ const Comment = ghostBookshelf.Model.extend({
|
|||
return options;
|
||||
},
|
||||
|
||||
async findMostLikedComment(options = {}) {
|
||||
let query = ghostBookshelf.knex('comments')
|
||||
.select('comments.*')
|
||||
.count('comment_likes.id as count__likes') // Counting likes for sorting
|
||||
.leftJoin('comment_likes', 'comments.id', 'comment_likes.comment_id')
|
||||
.groupBy('comments.id') // Group by comment ID to aggregate likes count
|
||||
.orderBy('count__likes', 'desc') // Order by likes in descending order (most likes first)
|
||||
.limit(1); // Limit to just 1 result
|
||||
// Execute the query and get the result
|
||||
const result = await query.first(); // Fetch the single top comment
|
||||
const id = result && result.id;
|
||||
// Fetch the comment model by ID
|
||||
return this.findOne({id}, options);
|
||||
},
|
||||
|
||||
async findPage(options) {
|
||||
const {withRelated} = this.defaultRelations('findPage', options);
|
||||
|
||||
|
@ -218,6 +233,16 @@ const Comment = ghostBookshelf.Model.extend({
|
|||
await model.load(relationsToLoadIndividually, _.omit(options, 'withRelated'));
|
||||
}
|
||||
|
||||
// if options.order === 'best', we findMostLikedComment
|
||||
// then we remove it from the result set and add it as the first element
|
||||
if (options.order === 'best') {
|
||||
const mostLikedComment = await this.findMostLikedComment(options);
|
||||
if (mostLikedComment) {
|
||||
result.data = result.data.filter(comment => comment.id !== mostLikedComment.id);
|
||||
result.data.unshift(mostLikedComment);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
|
|
|
@ -3314,6 +3314,55 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated can show most liked comment first when order param = best 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6df/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated can show most liked comment first when order param = best 2: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Egon Spengler",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "published",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated can show most liked comment first when order param = best 3: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "367",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when not authenticated Can browse all comments of a post (legacy) 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
|
|
|
@ -510,6 +510,40 @@ describe('Comments API', function () {
|
|||
should.not.exist(response.body.comments[0].unsubscribe_url);
|
||||
});
|
||||
|
||||
it('can show most liked comment first when order param = best', async function () {
|
||||
await setupBrowseCommentsData();
|
||||
const data = await membersAgent
|
||||
.get(`/api/comments/post/${postId}`);
|
||||
|
||||
await dbFns.addLike({
|
||||
comment_id: data.body.comments[1].id,
|
||||
member_id: loggedInMember.id
|
||||
});
|
||||
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/?order=best`)
|
||||
.expectStatus(200);
|
||||
|
||||
should(data2.body.comments[0].id).eql(data.body.comments[1].id);
|
||||
});
|
||||
|
||||
it('does not most liked comment first when order param and keeps normal order', async function () {
|
||||
await setupBrowseCommentsData();
|
||||
const data = await membersAgent
|
||||
.get(`/api/comments/post/${postId}`);
|
||||
|
||||
await dbFns.addLike({
|
||||
comment_id: data.body.comments[1].id,
|
||||
member_id: loggedInMember.id
|
||||
});
|
||||
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/`)
|
||||
.expectStatus(200);
|
||||
|
||||
should(data2.body.comments[0].id).not.eql(data.body.comments[1].id);
|
||||
});
|
||||
|
||||
it('Can reply to your own comment', async function () {
|
||||
// Should not update last_seen_at or last_commented_at when both are already set to a value on the same day
|
||||
const timezone = settingsCache.get('timezone');
|
||||
|
|
Loading…
Add table
Reference in a new issue