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;
|
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) {
|
async findPage(options) {
|
||||||
const {withRelated} = this.defaultRelations('findPage', options);
|
const {withRelated} = this.defaultRelations('findPage', options);
|
||||||
|
|
||||||
|
@ -218,6 +233,16 @@ const Comment = ghostBookshelf.Model.extend({
|
||||||
await model.load(relationsToLoadIndividually, _.omit(options, 'withRelated'));
|
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;
|
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`] = `
|
exports[`Comments API when commenting enabled for all when not authenticated Can browse all comments of a post (legacy) 1: [body] 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"comments": Array [
|
"comments": Array [
|
||||||
|
|
|
@ -510,6 +510,40 @@ describe('Comments API', function () {
|
||||||
should.not.exist(response.body.comments[0].unsubscribe_url);
|
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 () {
|
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
|
// 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');
|
const timezone = settingsCache.get('timezone');
|
||||||
|
|
Loading…
Add table
Reference in a new issue