0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2024-12-30 22:34:01 -05:00

Fixed incorrect pagination after deleting top level comment

closes https://linear.app/ghost/issue/PLG-304

- added a refresh of the comments list when a top-level comment with no replies is deleted so the pagination resets and replies aren't missed when loading more due to a shift in the underlying paginated data
This commit is contained in:
Kevin Ansfield 2024-12-12 17:33:47 +00:00
parent 962939b99a
commit 137ea89a7b
3 changed files with 34 additions and 3 deletions

View file

@ -271,7 +271,7 @@ async function unlikeComment({state, api, data: comment}: {state: EditableAppCon
};
}
async function deleteComment({state, api, data: comment}: {state: EditableAppContext, api: GhostApi, data: {id: string}}) {
async function deleteComment({state, api, data: comment, dispatchAction}: {state: EditableAppContext, api: GhostApi, data: {id: string}, dispatchAction: DispatchActionType}) {
await api.comments.edit({
comment: {
id: comment.id,
@ -279,6 +279,14 @@ async function deleteComment({state, api, data: comment}: {state: EditableAppCon
}
});
// If we're deleting a top-level comment with no replies we refresh the
// whole comments section to maintain correct pagination
const commentToDelete = state.comments.find(c => c.id === comment.id);
if (commentToDelete && (!commentToDelete.replies || commentToDelete.replies.length === 0)) {
dispatchAction('setOrder', {order: state.order});
return null;
}
return {
comments: state.comments.map((topLevelComment) => {
// If the comment has replies we want to keep it so the replies are

View file

@ -433,6 +433,22 @@ test.describe('Actions', async () => {
await expect(frame.getByTestId('replies-line')).toBeVisible();
});
test('Resets comments list after deleting a top-level comment', async ({page}) => {
const loggedInMember = buildMember();
mockedApi.setMember(loggedInMember);
// We have a page limit of 20, this will show the load more button
mockedApi.addComments(21, {member: loggedInMember});
const {frame} = await initializeTest(page);
await expect(frame.getByTestId('pagination-component')).toBeVisible();
const commentToDelete = frame.getByTestId('comment-component').nth(0);
await deleteComment(page, frame, commentToDelete);
// more button should have disappeared because the list was reloaded
await expect(frame.getByTestId('pagination-component')).not.toBeVisible();
});
test.describe('Sorting', () => {
test('Renders Sorting Form dropdown', async ({page}) => {
mockedApi.addComment({

View file

@ -330,7 +330,7 @@ export class MockedApi {
});
},
async getComment(route) {
async getOrDeleteComment(route) {
await this.#delayResponse();
const url = new URL(route.request().url());
const commentId = url.pathname.split('/').reverse()[1];
@ -344,6 +344,13 @@ export class MockedApi {
order: ''
}))
});
if (route.request().method() === 'PUT' && JSON.parse(route.request().postData()).comments?.[0]?.status === 'deleted') {
const comment = findCommentById(this.comments, commentId);
if (comment) {
comment.status = 'deleted';
}
}
},
async likeComment(route) {
@ -523,7 +530,7 @@ export class MockedApi {
await page.route(`${path}/members/api/member/`, this.requestHandlers.getMember.bind(this));
await page.route(`${path}/members/api/comments/*`, this.requestHandlers.addComment.bind(this));
await page.route(`${path}/members/api/comments/post/*/*`, this.requestHandlers.browseComments.bind(this));
await page.route(`${path}/members/api/comments/*/`, this.requestHandlers.getComment.bind(this));
await page.route(`${path}/members/api/comments/*/`, this.requestHandlers.getOrDeleteComment.bind(this));
await page.route(`${path}/members/api/comments/*/like/`, this.requestHandlers.likeComment.bind(this));
await page.route(`${path}/members/api/comments/*/replies/*`, this.requestHandlers.getReplies.bind(this));
await page.route(`${path}/members/api/comments/counts/*`, this.requestHandlers.getCommentCounts.bind(this));