mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-06 22:40:14 -05:00
Fixed sorting by best Comment with pagination (#21506)
ref PLG-220 - Added an `orderAttributes` override method to be able to pass `count__likes` to the `findPage` DB helper. - Unknowingly, without that override method in the model, it would strip all 'non-default' queries. - Adding that means we could remove our custom database queries and use the regular `findPage` helper that also handles pagination.
This commit is contained in:
parent
8f9a89c1a5
commit
6742b20215
2 changed files with 54 additions and 37 deletions
|
@ -94,6 +94,12 @@ const Comment = ghostBookshelf.Model.extend({
|
|||
}
|
||||
},
|
||||
|
||||
orderAttributes: function orderAttributes() {
|
||||
let keys = ghostBookshelf.Model.prototype.orderAttributes.call(this, arguments);
|
||||
keys.push('count__likes');
|
||||
return keys;
|
||||
},
|
||||
|
||||
onCreated: function onCreated(model, options) {
|
||||
ghostBookshelf.Model.prototype.onCreated.apply(this, arguments);
|
||||
|
||||
|
@ -202,31 +208,14 @@ 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);
|
||||
|
||||
const relationsToLoadIndividually = [
|
||||
'replies',
|
||||
'replies.member',
|
||||
'replies.count.likes',
|
||||
'replies.count.liked'
|
||||
].filter(relation => withRelated.includes(relation));
|
||||
|
||||
const result = await ghostBookshelf.Model.findPage.call(this, options);
|
||||
|
||||
for (const model of result.data) {
|
||||
|
|
|
@ -510,38 +510,66 @@ 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}`);
|
||||
it('can show most liked comment first when order param = best followed by most recent', async function () {
|
||||
// await setupBrowseCommentsData();
|
||||
// add another comment
|
||||
await dbFns.addComment({
|
||||
html: 'This is the newest comment',
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
created_at: new Date('2024-08-18')
|
||||
});
|
||||
|
||||
const secondBest = await dbFns.addComment({
|
||||
member_id: fixtureManager.get('members', 0).id,
|
||||
html: 'This will be the second best comment',
|
||||
created_at: new Date('2022-01-01')
|
||||
});
|
||||
|
||||
await dbFns.addComment({
|
||||
member_id: fixtureManager.get('members', 1).id,
|
||||
created_at: new Date('2023-01-01')
|
||||
});
|
||||
|
||||
const bestComment = await dbFns.addComment({
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
html: 'This will be the best comment',
|
||||
created_at: new Date('2021-01-01')
|
||||
});
|
||||
|
||||
const oldestComment = await dbFns.addComment({
|
||||
member_id: fixtureManager.get('members', 1).id,
|
||||
html: 'ancient comment',
|
||||
created_at: new Date('2019-01-01')
|
||||
});
|
||||
|
||||
await dbFns.addLike({
|
||||
comment_id: data.body.comments[1].id,
|
||||
comment_id: secondBest.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,
|
||||
comment_id: bestComment.id,
|
||||
member_id: loggedInMember.id
|
||||
});
|
||||
|
||||
await dbFns.addLike({
|
||||
comment_id: bestComment.id,
|
||||
member_id: fixtureManager.get('members', 0).id
|
||||
});
|
||||
|
||||
await dbFns.addLike({
|
||||
comment_id: bestComment.id,
|
||||
member_id: fixtureManager.get('members', 1).id
|
||||
});
|
||||
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/`)
|
||||
.get(`/api/comments/post/${postId}/?page=1&order=count__likes%20desc%2C%20created_at%20desc`)
|
||||
.expectStatus(200);
|
||||
|
||||
should(data2.body.comments[0].id).not.eql(data.body.comments[1].id);
|
||||
// get the LAST comment from data2
|
||||
let lastComment = data2.body.comments[data2.body.comments.length - 1];
|
||||
|
||||
should(lastComment.id).eql(oldestComment.id);
|
||||
});
|
||||
|
||||
it('Can reply to your own comment', async function () {
|
||||
|
|
Loading…
Reference in a new issue