diff --git a/static/js/index.js b/static/js/index.js index 4996cc46..4ec8d772 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -653,6 +653,8 @@ EpComments.prototype.setYofComments = function () { const padInner = padOuter.find('iframe[name="ace_inner"]'); const inlineComments = this.getFirstOcurrenceOfCommentIds(); const commentsToBeShown = []; + let minTopOffset = 0; + const spacingBetweenComments = 30; $.each(inlineComments, function () { // classname is the ID of the comment @@ -663,10 +665,13 @@ EpComments.prototype.setYofComments = function () { let topOffset = this.offsetTop; topOffset += parseInt(padInner.css('padding-top').split('px')[0]); topOffset += parseInt($(this).css('padding-top').split('px')[0]); + const commentHeight = commentEle.outerHeight() || 0; + const adjustedTopOffset = Math.max(topOffset, minTopOffset); + minTopOffset = adjustedTopOffset + commentHeight + spacingBetweenComments; if (commentId) { // adjust outer comment... - commentBoxes.adjustTopOf(commentId[1], topOffset); + commentBoxes.adjustTopOf(commentId[1], adjustedTopOffset); // ... and adjust icons too commentIcons.adjustTopOf(commentId[1], topOffset); diff --git a/static/tests/frontend-new/specs/multipleCommentsOneLine.spec.ts b/static/tests/frontend-new/specs/multipleCommentsOneLine.spec.ts new file mode 100644 index 00000000..31bc6616 --- /dev/null +++ b/static/tests/frontend-new/specs/multipleCommentsOneLine.spec.ts @@ -0,0 +1,40 @@ +import {expect, test} from '@playwright/test'; +import {getPadOuter} from 'ep_etherpad-lite/tests/frontend-new/helper/padHelper'; +import { + aNewCommentsPad, + addCommentToLine, + chooseToShowComments, + displayCommentAsIcon, + enlargeScreen, + setPadLines, +} from '../helper/comments'; + +test.describe('ep_comments_page - Multiple comments on one line', () => { + test('stacks sidebar comments so each one is visible', async ({page}) => { + test.setTimeout(60_000); + await aNewCommentsPad(page); + if (await displayCommentAsIcon(page)) test.skip(); + await enlargeScreen(page); + await chooseToShowComments(page, true); + await setPadLines(page, ['This line has multiple comments']); + + await addCommentToLine(page, 0, 'First comment'); + await addCommentToLine(page, 0, 'Second comment'); + + const outer = await getPadOuter(page); + const sidebarComments = outer.locator('#comments .sidebar-comment'); + await expect(sidebarComments).toHaveCount(2); + + const positions = await outer.evaluate(() => { + const comments = Array.from(document.querySelectorAll('#comments .sidebar-comment')); + return comments.map((comment) => { + const rect = comment.getBoundingClientRect(); + return {top: rect.top, height: rect.height}; + }); + }); + expect(positions).toHaveLength(2); + const sortedByTop = positions.sort((a, b) => a.top - b.top); + expect(sortedByTop[1].top).toBeGreaterThanOrEqual( + sortedByTop[0].top + sortedByTop[0].height); + }); +});