Added collapsed hidden comments to author's article/podcast episode view (#14018)
* Handling hiding/collapsing hidden comments client side * Updated comment quality text * Added placeholder for comments against podcast episodes * Added logic for encompassing co-author-ids in articles * Removed rspecs validating non-presence of hidden comments in dom * Fixed hiding flow on comments page for a commentable * Fixed e2e specs * Addressed feedback on e2e tests
This commit is contained in:
parent
71e90a41f5
commit
4cb48768f9
11 changed files with 153 additions and 37 deletions
|
|
@ -197,6 +197,8 @@ function initializeCommentsPage() {
|
|||
}
|
||||
}
|
||||
listenForDetailsToggle();
|
||||
|
||||
handleHiddenComments(commentableType);
|
||||
}
|
||||
|
||||
function toggleCodeOfConduct() {
|
||||
|
|
@ -554,24 +556,27 @@ function handleImageUpload(event, randomIdNumber) {
|
|||
}
|
||||
}
|
||||
|
||||
function updateItemSummaryHtml(item) {
|
||||
var itemSummaryContent = item.getElementsByClassName("js-collapse-comment-content")[0];
|
||||
var usernames = item.getElementsByClassName("js-comment-username");
|
||||
var number = "";
|
||||
if (usernames.length > 1) {
|
||||
number = " + " + (usernames.length - 1) + " replies"
|
||||
}
|
||||
var itemUsername = usernames[0].textContent + number
|
||||
if (item.open) {
|
||||
itemSummaryContent.innerHTML = "";
|
||||
} else {
|
||||
itemSummaryContent.innerHTML = itemUsername;
|
||||
}
|
||||
}
|
||||
|
||||
function listenForDetailsToggle() {
|
||||
var detailItems = document.querySelectorAll(".js-comment-wrapper");
|
||||
for (var i = 0; i < detailItems.length; i++) {
|
||||
detailItems[i].addEventListener("toggle", event => {
|
||||
var item = event.target;
|
||||
var itemSummaryContent = item.getElementsByClassName("js-collapse-comment-content")[0];
|
||||
var usernames = item.getElementsByClassName("js-comment-username");
|
||||
var number = "";
|
||||
if (usernames.length > 1) {
|
||||
number = " + " + (usernames.length - 1) + " replies"
|
||||
}
|
||||
var itemUsername = usernames[0].textContent + number
|
||||
if (item.open) {
|
||||
itemSummaryContent.innerHTML = "";
|
||||
} else {
|
||||
itemSummaryContent.innerHTML = itemUsername;
|
||||
}
|
||||
item.getElementsByTagName("SUMMARY")[0].blur();
|
||||
updateItemSummaryHtml(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -589,3 +594,55 @@ function updateCommentsCount() {
|
|||
commentsCountDiv.dataset.commentsCount = commentsCountData;
|
||||
commentsCountDiv.innerHTML = `(${commentsCountData})`
|
||||
}
|
||||
|
||||
function handleHiddenComments(commentableType){
|
||||
const currentUser = userData();
|
||||
const commentableAuthorIds = [];
|
||||
let coAuthorIds = '';
|
||||
if(commentableType === "Article"){
|
||||
const articleContainer = document.querySelector('#article-show-container');
|
||||
if(articleContainer){
|
||||
commentableAuthorIds.push(articleContainer?.dataset?.authorId);
|
||||
coAuthorIds = articleContainer?.dataset?.coAuthorIds;
|
||||
if(coAuthorIds){
|
||||
coAuthorIds.split(',').forEach(coAuthorId => {
|
||||
commentableAuthorIds.push(coAuthorId);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
const commentsContainer = document.querySelector('#comments-container');
|
||||
if(commentsContainer){
|
||||
commentableAuthorIds.push(commentsContainer?.dataset?.commentableAuthorId);
|
||||
coAuthorIds = commentsContainer?.dataset?.commentableCoAuthorIds;
|
||||
if(coAuthorIds){
|
||||
coAuthorIds.split(',').forEach(coAuthorId => {
|
||||
commentableAuthorIds.push(coAuthorId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(commentableType === "PodcastEpisode"){
|
||||
const podCastEpisodeContainer = document.querySelector('.podcast-episode-container');
|
||||
if(podCastEpisodeContainer){
|
||||
commentableAuthorIds.push(podCastEpisodeContainer.dataset.creatorId);
|
||||
}
|
||||
}
|
||||
if (commentableAuthorIds.includes(currentUser?.id?.toString())){
|
||||
collapseCommentsHiddenByCommentableUser();
|
||||
}
|
||||
else {
|
||||
document.querySelectorAll('.comment-hidden-by-commentable-user, .details-comment-hidden-by-commentable-user').forEach(element => {
|
||||
element.classList.add('hidden');
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function collapseCommentsHiddenByCommentableUser() {
|
||||
document.querySelectorAll(".js-comment-wrapper.details-comment-hidden-by-commentable-user").forEach(item => {
|
||||
if (item.querySelectorAll('.comment-form').length === 0){
|
||||
item.open = false;
|
||||
updateItemSummaryHtml(item);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@
|
|||
id="article-show-container"
|
||||
data-article-id="<%= @article.id %>"
|
||||
data-author-id="<%= @article.user_id %>"
|
||||
data-co-author-ids="<%= @article.co_author_ids.join(",") %>"
|
||||
data-path="<%= @article.path %>"
|
||||
data-published="<%= @article.published? %>"
|
||||
data-pin-path="<%= stories_feed_pinned_article_path %>"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<% if comment && comment.user && !should_be_hidden?(comment, @root_comment) %>
|
||||
<% if comment && comment.user %>
|
||||
<% if comment.depth < 3 %>
|
||||
<details class="comment-wrapper js-comment-wrapper comment-wrapper--deep-<%= comment.depth %> <%= comment_class(comment, is_view_root: is_view_root) %>" open>
|
||||
<details class="comment-wrapper js-comment-wrapper comment-wrapper--deep-<%= comment.depth %> <%= comment_class(comment, is_view_root: is_view_root) %> <%= should_be_hidden?(comment, @root_comment) ? "details-comment-hidden-by-commentable-user" : "" %>" open>
|
||||
<summary>
|
||||
<span class="<% if comment.depth > 0 %>mx-0<% else %>m:mx-1<% end %> inline-block align-middle">
|
||||
<%= inline_svg_tag("collapse.svg", aria: true, class: "crayons-icon expanded", title: t("views.comments.collapse")) %>
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
<%= comment_class(comment, is_view_root: is_view_root) %>
|
||||
comment--deep-<%= comment.depth %>
|
||||
<%= "comment--too-deep" if comment.depth > 3 %>
|
||||
<%= should_be_hidden?(comment, @root_comment) ? "comment-hidden-by-commentable-user" : "" %>
|
||||
"
|
||||
data-comment-id="<%= comment.id %>"
|
||||
data-path="<%= commentable&.path %>/comments/<%= comment.id_code_generated %>"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
<% if comment.hidden_by_commentable_user %>
|
||||
<div class="low-quality-comment-marker comment__quality-marker">
|
||||
<%= inline_svg_tag("info.svg", aria: true, class: "crayons-icon mr-2", title: t("views.comments.quality.hidden.icon")) %>
|
||||
<%= t("views.comments.quality.hidden.text") %>
|
||||
<% if @root_comment %>
|
||||
<%= t("views.comments.quality.hidden.text.visible_in_permalink") %>
|
||||
<% else %>
|
||||
<%= t("views.comments.quality.hidden.text.accessible_via_permalink") %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -124,7 +124,9 @@
|
|||
class="crayons-card text-padding min-w-0 z-elevate"
|
||||
id="comments-container"
|
||||
data-commentable-id="<%= @commentable&.id %>"
|
||||
data-commentable-type="<%= @commentable&.class&.name %>">
|
||||
data-commentable-type="<%= @commentable&.class&.name %>"
|
||||
data-commentable-author-id="<%= @commentable&.user_id %>"
|
||||
data-commentable-co-author-ids="<%= @commentable&.co_author_ids&.join(",") %>">
|
||||
|
||||
<% unless @root_comment %>
|
||||
<%= render "form",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
<% end %>
|
||||
|
||||
<main id="main-content" class="podcast-episode-container" data-meta="<%= @episode.decorate.mobile_player_metadata.to_json %>">
|
||||
<main id="main-content" class="podcast-episode-container" data-meta="<%= @episode.decorate.mobile_player_metadata.to_json %>" data-creator-id="<%= @podcast.creator_id %>">
|
||||
<div class="hero">
|
||||
<div class="title" style="background:#<%= @podcast.main_color_hex %>">
|
||||
<h2>
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@ en:
|
|||
conduct: View Code of Conduct
|
||||
hidden:
|
||||
icon: Info
|
||||
text: Comment hidden by post author - thread only visible in this permalink
|
||||
text:
|
||||
visible_in_permalink: Comment hidden by post author - thread only visible in this permalink
|
||||
accessible_via_permalink: Comment hidden by post author - thread only accessible via permalink
|
||||
write:
|
||||
errors:
|
||||
one: '1 error prohibited this comment from being saved:'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
describe('Hiding/unhiding comments on an article', () => {
|
||||
beforeEach(() => {
|
||||
cy.testSetup();
|
||||
cy.fixture('users/adminUser.json').as('user');
|
||||
|
||||
cy.get('@user').then((user) => {
|
||||
cy.loginAndVisit(user, '/admin_mcadmin/test-article-slug');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Admin visits the article authored by them', () => {
|
||||
it('Hides a comment and then unhides it from the same screen', () => {
|
||||
cy.findByRole('button', { name: 'Toggle dropdown menu' }).click();
|
||||
cy.findByRole('link', { name: "Hide Admin McAdmin's comment" }).click();
|
||||
cy.findByRole('button', { name: 'Toggle dropdown menu' }).should(
|
||||
'not.be.visible',
|
||||
);
|
||||
cy.findByRole('img', { name: 'Expand' }).click();
|
||||
cy.findByRole('button', { name: 'Toggle dropdown menu' }).click();
|
||||
cy.findByRole('link', { name: "Unhide Admin McAdmin's comment" }).click();
|
||||
cy.findByRole('img', { name: 'Expand' }).should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -50,4 +50,14 @@ describe('View article discussion', () => {
|
|||
.first()
|
||||
.findByRole('button', { name: 'Edit profile' });
|
||||
});
|
||||
|
||||
it('does not see hidden comments on an article not authored by them', () => {
|
||||
cy.visit('/admin_mcadmin/test-article-with-hidden-comments-slug');
|
||||
cy.findByText(/Some comments have been hidden by the post's author/).should(
|
||||
'exist',
|
||||
);
|
||||
cy.findByRole('button', { name: 'Toggle dropdown menu' }).should(
|
||||
'not.exist',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -71,12 +71,6 @@ RSpec.describe "Comments", type: :request do
|
|||
expect(response.body).to include(CGI.escapeHTML(comment.title(150)))
|
||||
expect(response.body).to include(child.processed_html)
|
||||
end
|
||||
|
||||
it "does not display the comment if it is hidden" do
|
||||
child.update(hidden_by_commentable_user: true)
|
||||
get comment.path
|
||||
expect(response.body).not_to include child.processed_html
|
||||
end
|
||||
end
|
||||
|
||||
context "when the comment is two levels nested and hidden" do # child of a child
|
||||
|
|
@ -139,23 +133,11 @@ RSpec.describe "Comments", type: :request do
|
|||
expect(response.body).not_to include(third_level_child.processed_html)
|
||||
end
|
||||
|
||||
it "does not show the hidden comment's children in the article's comments section" do
|
||||
fourth_level_child
|
||||
get "#{article.path}/comments"
|
||||
expect(response.body).not_to include(fourth_level_child.processed_html)
|
||||
end
|
||||
|
||||
it "does not show the hidden comment in its parent's permalink" do
|
||||
get second_level_child.path
|
||||
expect(response.body).not_to include(third_level_child.processed_html)
|
||||
end
|
||||
|
||||
it "does not show the hidden comment's child in its parent's permalink" do
|
||||
fourth_level_child
|
||||
get second_level_child.path
|
||||
expect(response.body).not_to include(fourth_level_child.processed_html)
|
||||
end
|
||||
|
||||
it "shows the comment in the permalink" do
|
||||
get third_level_child.path
|
||||
expect(response.body).to include(third_level_child.processed_html)
|
||||
|
|
|
|||
|
|
@ -375,6 +375,39 @@ end
|
|||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(Article, "slug", "test-article-with-hidden-comments-slug") do
|
||||
markdown = <<~MARKDOWN
|
||||
---
|
||||
title: Test article with hidden comments
|
||||
published: true
|
||||
cover_image: #{Faker::Company.logo}
|
||||
---
|
||||
#{Faker::Hipster.paragraph(sentence_count: 2)}
|
||||
#{Faker::Markdown.random}
|
||||
#{Faker::Hipster.paragraph(sentence_count: 2)}
|
||||
MARKDOWN
|
||||
article = Article.create!(
|
||||
body_markdown: markdown,
|
||||
featured: true,
|
||||
show_comments: true,
|
||||
user_id: admin_user.id,
|
||||
slug: "test-article-with-hidden-comments-slug",
|
||||
any_comments_hidden: true,
|
||||
)
|
||||
|
||||
comment_attributes = {
|
||||
body_markdown: Faker::Hipster.paragraph(sentence_count: 1),
|
||||
user_id: admin_user.id,
|
||||
commentable_id: article.id,
|
||||
commentable_type: "Article",
|
||||
hidden_by_commentable_user: true
|
||||
}
|
||||
|
||||
Comment.create!(comment_attributes)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
|
||||
seeder.create_if_doesnt_exist(Article, "title", "Organization test article") do
|
||||
markdown = <<~MARKDOWN
|
||||
---
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue