0
Fork 0
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:
Ronald Langeveld 2024-11-04 09:50:53 +09:00 committed by GitHub
parent 8f9a89c1a5
commit 6742b20215
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 37 deletions

View file

@ -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) {

View file

@ -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 () {