Browse Source

Compress fully-removed comment chains

When a chain of comments has been fully removed, this will display a
single marker like "Removed by admin: 8 comments by 2 users" instead of
individual "Comment removed by site admin" markers for each one.
merge-requests/85/head
Deimos 5 years ago
parent
commit
3a0e7fc3fa
  1. 34
      tildes/tildes/models/comment/comment_tree.py
  2. 11
      tildes/tildes/templates/macros/comments.jinja2

34
tildes/tildes/models/comment/comment_tree.py

@ -3,6 +3,7 @@
"""Contains the CommentTree and CommentInTree classes.""" """Contains the CommentTree and CommentInTree classes."""
from collections import Counter
from datetime import datetime from datetime import datetime
from typing import Iterator, List, Optional, Sequence, Tuple from typing import Iterator, List, Optional, Sequence, Tuple
@ -51,6 +52,8 @@ class CommentTree:
self.tree = self._prune_empty_branches(self.tree) self.tree = self._prune_empty_branches(self.tree)
self._add_removed_markers()
self._count_children() self._count_children()
def _count_children(self) -> None: def _count_children(self) -> None:
@ -131,6 +134,37 @@ class CommentTree:
return pruned_tree return pruned_tree
def _add_removed_markers(self) -> None:
"""Add markers to chains of removed comments with more info.
When displaying a comment tree, these markers should be displayed to users
that can't view the removed comment, and stop recursing down the branch.
"""
# work backwards so all replies are always processed first
for comment in reversed(self.comments):
if not comment.is_removed:
continue
# we can only compress when all descendants are also removed - checking
# for this attr works because it's only added after passing this check
if not all(
hasattr(reply, "removed_comments_by_user") for reply in comment.replies
):
continue
comment.removed_comments_by_user = Counter({comment.user: 1})
# add all the descendants' counts onto this comment's
for reply in comment.replies:
comment.removed_comments_by_user += reply.removed_comments_by_user
num_comments = sum(comment.removed_comments_by_user.values())
num_users = len(comment.removed_comments_by_user)
if num_comments > 1:
comment.removed_marker = (
f"Removed by admin: {num_comments} comments by {num_users} users"
)
def __iter__(self) -> Iterator[Comment]: def __iter__(self) -> Iterator[Comment]:
"""Iterate over the (top-level) Comments in the tree.""" """Iterate over the (top-level) Comments in the tree."""
for comment in self.tree: for comment in self.tree:

11
tildes/tildes/templates/macros/comments.jinja2

@ -30,9 +30,10 @@
> >
{{ render_comment_contents(comment, is_individual_comment) }} {{ render_comment_contents(comment, is_individual_comment) }}
{% if comment.replies is defined and comment.replies %}
{# Recursively display reply comments, unless we hit a "removed marker" #}
{% if comment.replies and
(request.has_permission("view", comment) or not comment.removed_marker) %}
<ol class="comment-tree comment-tree-replies"> <ol class="comment-tree comment-tree-replies">
{# Recursively display reply comments #}
{{ loop(comment.replies) }} {{ loop(comment.replies) }}
</ol> </ol>
{% endif %} {% endif %}
@ -74,7 +75,11 @@
{% if comment.is_deleted %} {% if comment.is_deleted %}
<div class="is-comment-deleted">Comment deleted by author</div> <div class="is-comment-deleted">Comment deleted by author</div>
{% elif comment.is_removed %} {% elif comment.is_removed %}
<div class="is-comment-removed">Comment removed by site admin</div>
{% if comment.removed_marker %}
<div class="is-comment-removed">{{ comment.removed_marker }}</div>
{% else %}
<div class="is-comment-removed">Comment removed by site admin</div>
{% endif %}
{% endif %} {% endif %}
{% endif %} {% endif %}

Loading…
Cancel
Save