try comment show with link

This commit is contained in:
Tuan-Dung Bui 2023-05-16 15:03:26 +07:00
parent 49a186f72f
commit d1f9c12c2d
8 changed files with 264 additions and 60 deletions

View file

@ -151,46 +151,86 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
return self.render_to_response(context) return self.render_to_response(context)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
pre_query = None
if "comment-id" in request.GET:
comment_id = int(request.GET["comment-id"])
comment_obj = Comment.objects.get(pk=comment_id)
pre_query = comment_obj
while comment_obj is not None:
pre_query = comment_obj
comment_obj = comment_obj.parent
self.object = self.get_object() self.object = self.get_object()
return self.render_to_response( return self.render_to_response(
self.get_context_data( self.get_context_data(
object=self.object, object=self.object,
pre_query=pre_query,
comment_form=CommentForm(request, initial={"parent": None}), comment_form=CommentForm(request, initial={"parent": None}),
) )
) )
def get_context_data(self, **kwargs): def get_context_data(self, pre_query=None, **kwargs):
context = super(CommentedDetailView, self).get_context_data(**kwargs) context = super(CommentedDetailView, self).get_context_data(**kwargs)
queryset = self.object.comments queryset = self.object.comments
queryset = queryset.filter(parent=None, hidden=False) queryset = queryset.filter(parent=None, hidden=False)
queryset_all = None
comment_count = len(queryset) comment_count = len(queryset)
queryset = ( if (pre_query != None):
queryset.select_related("author__user") queryset_all = pre_query.get_descendants(include_self=True)
.defer("author__about") queryset_all = (
.annotate( queryset_all.select_related("author__user")
count_replies=Count("replies", distinct=True), .filter(hidden=False)
revisions=Count("versions", distinct=True), .defer("author__about")
)[:10] .annotate(revisions=Count("versions", distinct=True))
) )
context["has_comments"] = queryset.exists() else:
context["comment_lock"] = self.is_comment_locked() queryset = (
queryset.select_related("author__user")
.defer("author__about")
.filter(hidden=False)
.annotate(
count_replies=Count("replies", distinct=True),
revisions=Count("versions", distinct=True),
)[:10]
)
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
profile = self.request.profile profile = self.request.profile
queryset = queryset.annotate( if (pre_query != None):
my_vote=FilteredRelation( queryset_all = queryset_all.annotate(
"votes", condition=Q(votes__voter_id=profile.id) my_vote=FilteredRelation(
), "votes", condition=Q(votes__voter_id=profile.id)
).annotate(vote_score=Coalesce(F("my_vote__score"), Value(0))) ),
).annotate(vote_score=Coalesce(F("my_vote__score"), Value(0)))
else:
queryset = queryset.annotate(
my_vote=FilteredRelation(
"votes", condition=Q(votes__voter_id=profile.id)
),
).annotate(vote_score=Coalesce(F("my_vote__score"), Value(0)))
context["is_new_user"] = ( context["is_new_user"] = (
not self.request.user.is_staff not self.request.user.is_staff
and not profile.submission_set.filter( and not profile.submission_set.filter(
points=F("problem__points") points=F("problem__points")
).exists() ).exists()
) )
context["has_comments"] = queryset.exists()
context["comment_lock"] = self.is_comment_locked()
context["comment_list"] = queryset context["comment_list"] = queryset
context["comment_all_list"] = queryset_all
context["vote_hide_threshold"] = settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD context["vote_hide_threshold"] = settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD
context["comment_root_id"] = 0 if queryset.exists():
context["offset"] = 10 context["comment_root_id"] = queryset[0].id
else:
context["comment_root_id"] = 0
context["comment_parrent_none"] = 1
if (pre_query != None):
context["offset"] = 0
else:
context["offset"] = 10
context["limit"] = 10 context["limit"] = 10
context["comment_count"] = comment_count context["comment_count"] = comment_count
return context return context

View file

@ -151,7 +151,7 @@ class Comment(MPTTModel):
) )
def get_absolute_url(self): def get_absolute_url(self):
return "%s#comment-%d" % (self.link, self.id) return "%s?comment-id=%d#comment-%d" % (self.link, self.id, self.id)
class CommentVote(models.Model): class CommentVote(models.Model):

View file

@ -116,14 +116,12 @@ def downvote_comment(request):
def get_comments(request, limit=10): def get_comments(request, limit=10):
try: try:
comment_id = int(request.GET["id"]) comment_id = int(request.GET["id"])
page_id = int(request.GET["page"]) parrent_none = int(request.GET["parrent_none"])
except ValueError: except ValueError:
return HttpResponseBadRequest() return HttpResponseBadRequest()
else: else:
if comment_id and not Comment.objects.filter(id=comment_id).exists(): if comment_id and not Comment.objects.filter(id=comment_id).exists():
raise Http404() raise Http404()
if not BlogPost.objects.filter(id=page_id).exists():
raise Http404()
offset = 0 offset = 0
if "offset" in request.GET: if "offset" in request.GET:
offset = int(request.GET["offset"]) offset = int(request.GET["offset"])
@ -133,13 +131,14 @@ def get_comments(request, limit=10):
comment_root_id = comment_obj.id comment_root_id = comment_obj.id
else: else:
comment_obj = None comment_obj = None
page_obj = BlogPost.objects.get(pk=page_id) queryset = comment_obj.linked_object.comments
queryset = page_obj.comments if parrent_none:
queryset = queryset.filter(parent=comment_obj, hidden=False) queryset = queryset.filter(parent=None, hidden=False)
else:
queryset = queryset.filter(parent=comment_obj, hidden=False)
comment_count = len(queryset) comment_count = len(queryset)
queryset = ( queryset = (
queryset queryset.select_related("author__user")
.select_related("author__user")
.defer("author__about") .defer("author__about")
.annotate( .annotate(
count_replies=Count("replies", distinct=True), count_replies=Count("replies", distinct=True),
@ -162,10 +161,10 @@ def get_comments(request, limit=10):
"comment_list": queryset, "comment_list": queryset,
"vote_hide_threshold" : settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD, "vote_hide_threshold" : settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD,
"perms": PermWrapper(request.user), "perms": PermWrapper(request.user),
"object": page_obj,
"offset": offset + min(len(queryset), limit), "offset": offset + min(len(queryset), limit),
"limit": limit, "limit": limit,
"comment_count": comment_count "comment_count": comment_count,
"comment_parrent_none": parrent_none,
} }
) )

View file

@ -129,14 +129,24 @@ a {
.show_more_reply { .show_more_reply {
font-weight: bold; font-weight: bold;
display: block; display: flex;
margin: 16px 40px; margin: 16px 40px;
align-items: center;
svg {
margin-right: 4px;
}
} }
.show_more_comment { .show_more_comment {
font-weight: bold; font-weight: bold;
display: block; display: flex;
margin: 16px -40px; margin: 16px -40px;
align-items: center;
svg {
margin-right: 4px;
}
} }
} }

View file

@ -27,9 +27,9 @@
<span class="actionbar-text"> <span class="actionbar-text">
{{_("Comment")}} {{_("Comment")}}
</span> </span>
{% if replies %} {% if comment_count %}
<span style="margin-left: 0.2em"> <span style="margin-left: 0.2em">
({{replies}}) ({{ comment_count }})
</span> </span>
{% endif %} {% endif %}
</span> </span>

View file

@ -1,5 +1,3 @@
{% set logged_in = request.user.is_authenticated %}
{% set profile = request.profile if logged_in else None %}
{% for node in mptt_tree(comment_list) recursive %} {% for node in mptt_tree(comment_list) recursive %}
<li id="comment-{{ node.id }}" data-revision="{{ node.revisions - 1 }}" data-max-revision="{{ node.revisions - 1 }}" <li id="comment-{{ node.id }}" data-revision="{{ node.revisions - 1 }}" data-max-revision="{{ node.revisions - 1 }}"
data-revision-ajax="{{ url('comment_revision_ajax', node.id) }}" class="comment"> data-revision-ajax="{{ url('comment_revision_ajax', node.id) }}" class="comment">
@ -99,18 +97,41 @@
</div> </div>
{% if node.count_replies > 1 %} {% if node.count_replies > 1 %}
<a href="javascript:comment_get_replies({{ node.id }}, {{ object.id }})" class="show_more_reply"> {{ node.count_replies }} {{ <a href="javascript:comment_get_replies({{ node.id }}, 0)" class="show_more_reply">
_(' Replies ') }} </a> <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-forward" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 11l4 4l-4 4m4 -4h-11a4 4 0 0 1 0 -8h1"></path>
</svg>
{{ node.count_replies }} {{_(' replies ') }} </a>
{% elif node.count_replies %} {% elif node.count_replies %}
<a href="javascript:comment_get_replies({{ node.id }}, {{ object.id }})" class="show_more_reply"> {{ node.count_replies }} {{ <a href="javascript:comment_get_replies({{ node.id }}, 0)" class="show_more_reply">
_(' Reply ') }} </a> <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-arrow-forward" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M15 11l4 4l-4 4m4 -4h-11a4 4 0 0 1 0 -8h1"></path>
</svg>
{{ node.count_replies }} {{_(' reply ') }} </a>
{% endif %} {% endif %}
</li> </li>
<ul id="comment-{{ node.id }}-reply" class="reply-comment" hidden></ul> <ul id="comment-{{ node.id }}-reply" class="reply-comment" hidden></ul>
<ul id="comment-{{ node.id }}-children" class="comments"> </ul> <ul id="comment-{{ node.id }}-children" class="comments"> </ul>
{% endfor %} {% endfor %}
{% if comment_count - offset > 0 %}
<a href="javascript:comment_show_more({{ comment_root_id }}, {{ object.id }}, {{ offset }} )" class="show_more_comment">
{{ comment_count - offset }} replies more</a> {% set comment_more = comment_count - offset %}
{% if comment_more == 1 %}
<a href="javascript:comment_show_more({{ comment_root_id }}, {{ comment_parrent_none }}, {{ offset }} )" class="show_more_comment">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-down" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M6 9l6 6l6 -6"></path>
</svg>
{{ comment_count - offset }} comment more</a>
{% elif comment_more > 1 %}
<a href="javascript:comment_show_more({{ comment_root_id }}, {{ comment_parrent_none }}, {{ offset }} )" class="show_more_comment">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-down" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M6 9l6 6l6 -6"></path>
</svg>
{{ comment_count - offset }} comments more</a>
{% endif %} {% endif %}

View file

@ -36,9 +36,142 @@
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
{% if has_comments %} {% if has_comments or comment_all_list %}
<ul class="comments top-level-comments new-comments" id="comment-0"> <ul class="comments top-level-comments new-comments" id="comment-0">
{% set logged_in = request.user.is_authenticated %}
{% set profile = request.profile if logged_in else None %}
{% if comment_all_list %}
{% for node in mptt_tree(comment_all_list) recursive %}
<li id="comment-{{ node.id }}" data-revision="{{ node.revisions - 1 }}"
data-max-revision="{{ node.revisions - 1 }}"
data-revision-ajax="{{ url('comment_revision_ajax', node.id) }}" class="comment">
<div class="comment-display{% if node.score <= vote_hide_threshold %} bad-comment{% endif %}">
<div class="info">
<div class="vote">
{% if logged_in %}
<a href="javascript:comment_upvote({{ node.id }})"
class="upvote-link fa fa-chevron-up fa-fw{% if node.vote_score == 1 %} voted{% endif %}"></a>
{% else %}
<a href="javascript:alert('{{ _('Please login to vote')|escapejs }}')" title="{{ _('Please login to vote') }}"
class="upvote-link fa fa-chevron-up fa-fw"></a>
{% endif %}
<br>
<div class="comment-score">{{ node.score }}</div>
{% if logged_in %}
<a href="javascript:comment_downvote({{ node.id }})"
class="downvote-link fa fa-chevron-down fa-fw{% if node.vote_score == -1 %} voted{% endif %}"></a>
{% else %}
<a href="javascript:alert('{{ _('Please login to vote')|escapejs }}')" title="{{ _('Please login to vote') }}"
class="downvote-link fa fa-chevron-down fa-fw"></a>
{% endif %}
</div>
</div>
<div class="detail">
<div class="header">
{% with author=node.author, user=node.author.user %}
<a href="{{ url('user_page', user.username) }}" class="user comment-img">
<img src="{{ gravatar(author, 135) }}" class="gravatar">
</a>
{% endwith %}
{{ link_user(node.author) }},&nbsp;
{{ relative_time(node.time, abs=_('{time}'), rel=_('{time}')) }}
<span class="comment-spacer"></span>
<span class="comment-operation">
{% if node.revisions > 1 %}
<span class="comment-edits">
<a href="javascript:show_revision({{ node.id }}, -1)"
class="previous-revision">&larr;</a>
<span class="comment-edit-text">
{% if node.revisions > 2 %}
{% trans edits=node.revisions - 1 %}edit {{ edits }}{% endtrans %}
{% else %}
{{ _('edited') }}
{% endif %}
</span>
<a href="javascript:show_revision({{ node.id }}, 1)" style="visibility: hidden"
class="next-revision">&rarr;</a>
</span>
{% else %}
<span class="comment-edits"></span>
{% endif %}
<a href="#comment-{{ node.id }}" title="{{ _('Link') }}" class="comment-link">
<i class="fa fa-link fa-fw"></i>
</a>
{% if logged_in and not comment_lock %}
{% set can_edit = node.author.id == profile.id and not profile.mute %}
{% if can_edit %}
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}"
href="{{ url('comment_edit', node.id) }}"
title="{{ _('Edit') }}" class="edit-link">
<i class="fa fa-pencil fa-fw"></i>
</a>
{% else %}
<a href="javascript:reply_comment({{ node.id }})"
title="{{ _('Reply') }}">
<i class="fa fa-reply fa-fw"></i>
</a>
{% endif %}
{% if perms.judge.change_comment %}
{% if can_edit %}
<a href="javascript:reply_comment({{ node.id }})"
title="{{ _('Reply') }}"><i class="fa fa-reply fa-fw"></i></a>
{% else %}
<a data-featherlight="{{ url('comment_edit_ajax', node.id) }}"
href="{{ url('comment_edit', node.id) }}" title="{{ _('Edit') }}"
class="edit-link"><i class="fa fa-pencil fa-fw"></i></a>
{% endif %}
<a href="javascript:" title="{{ _('Hide') }}" data-id="{{ node.id }}"
class="hide-comment"><i class="fa fa-trash fa-fw"></i></a>
<a href="{{ url('admin:judge_comment_change', node.id) }}"
title="{{ _('Admin') }}"><i class="fa fa-cog fa-fw"></i></a>
{% endif %}
{% endif %}
</span>
</div>
<div class="content content-description">
<div class="comment-body"{% if node.score <= vote_hide_threshold %} style="display:none"{% endif %}>
{{ node.body|markdown(lazy_load=True)|reference|str|safe }}
</div>
{% if node.score <= vote_hide_threshold %}
<div class="comment-body bad-comment-body">
<p>
{% trans id=node.id %}This comment is hidden due to too much negative feedback. Click <a href="javascript:comment_show_content({{ id }})">here</a> to view it.{% endtrans %}
</p>
</div>
{% endif %}
</div>
</div>
</div>
</li>
<ul id="comment-{{ node.id }}-reply" class="reply-comment" hidden></ul>
{% with children=node.get_children() %}
{% if children %}
<ul id="comment-{{ node.id }}-children" class="comments">{{ loop(children) }}</ul>
{% endif %}
{% endwith %}
{% endfor %}
{% set comment_more = comment_count - offset %}
{% if comment_more == 1 %}
<a href="javascript:comment_show_more({{ comment_root_id }}, {{ comment_parrent_none }}, {{ offset }} )" class="show_more_comment">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-down" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M6 9l6 6l6 -6"></path>
</svg>
{{ comment_count - offset }} comment more
</a>
{% elif comment_more > 1 %}
<a href="javascript:comment_show_more({{ comment_root_id }}, {{ comment_parrent_none }}, {{ offset }} )" class="show_more_comment">
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-down" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M6 9l6 6l6 -6"></path>
</svg>
{{ comment_count - offset }} comments more
</a>
{% endif %}
{% else %}
{% include "comments/content-list.html" %} {% include "comments/content-list.html" %}
{% endif %}
</ul> </ul>
{% elif not comment_lock %} {% elif not comment_lock %}
<p class="no-comments-message">{{ _('There are no comments at the moment.') }}</p> <p class="no-comments-message">{{ _('There are no comments at the moment.') }}</p>

View file

@ -120,21 +120,21 @@
}); });
} }
window.comment_get_replies = function (id, page) { window.comment_get_replies = function (id, parrent_none) {
var $comment_show_btn = $("#comment-" + id + " .show_more_reply"); var $comment_show_btn = $("#comment-" + id + " .show_more_reply");
$comment_show_btn.hide(); $comment_show_btn.hide();
var $comment = $("#comment-" + id + "-children"); var $comment = $("#comment-" + id + "-children");
$comment.append("<p class='loading'> Loading... </p>"); $comment.append("<p class='loading'> Loading... </p>");
ajax_get_reply('{{ url('comment_get_replies') }}', id, page); ajax_get_reply('{{ url('comment_get_replies') }}', id, parrent_none);
} }
function ajax_get_reply(url, id, page) { function ajax_get_reply(url, id, parrent_none) {
return $.ajax({ return $.ajax({
url: url, url: url,
type: 'GET', type: 'GET',
data: { data: {
id: id, id: id,
page: page, parrent_none: parrent_none,
}, },
success: function(data) { success: function(data) {
var $comment_loading = $("#comment-" + id + "-children .loading"); var $comment_loading = $("#comment-" + id + "-children .loading");
@ -145,11 +145,12 @@
}) })
} }
window.comment_show_more = function (id, page, offset) { window.comment_show_more = function (id, parrent_none, offset) {
if (id == 0) { console.log(parrent_none)
var $comment_show_btn = $("#comment-" + id + " .show_more_comment"); if (parrent_none == 1) {
var $comment_show_btn = $("#comment-0" + " .show_more_comment");
$comment_show_btn.hide(); $comment_show_btn.hide();
var $comment = $("#comment-" + id); var $comment = $("#comment-0");
$comment.append("<p class='loading'> Loading... </p>"); $comment.append("<p class='loading'> Loading... </p>");
} else { } else {
var $comment_show_btn = $("#comment-" + id + "-children" + " .show_more_comment"); var $comment_show_btn = $("#comment-" + id + "-children" + " .show_more_comment");
@ -157,23 +158,23 @@
var $comment = $("#comment-" + id + "-children"); var $comment = $("#comment-" + id + "-children");
$comment.append("<p class='loading'> Loading... </p>"); $comment.append("<p class='loading'> Loading... </p>");
} }
ajax_comment_show_more('{{ url('comment_show_more') }}', id, page, offset); ajax_comment_show_more('{{ url('comment_show_more') }}', id, parrent_none, offset);
} }
function ajax_comment_show_more(url, id, page, offset) { function ajax_comment_show_more(url, id, parrent_none, offset) {
return $.ajax({ return $.ajax({
url: url, url: url,
type: 'GET', type: 'GET',
data: { data: {
id: id, id: id,
page: page, parrent_none: parrent_none,
offset: offset, offset: offset,
}, },
success: function(data) { success: function(data) {
if (id == 0) { if (parrent_none == 1) {
var $comment_loading = $("#comment-" + id + " .loading"); var $comment_loading = $("#comment-0" + " .loading");
$comment_loading.hide(); $comment_loading.hide();
var $comment = $("#comment-" + id); var $comment = $("#comment-0");
$comment.append(data); $comment.append(data);
} else { } else {
var $comment_loading = $("#comment-" + id + "-children .loading"); var $comment_loading = $("#comment-" + id + "-children .loading");