change comment style

This commit is contained in:
Tuan-Dung Bui 2023-04-11 23:55:11 +07:00
parent 2bd0e41653
commit d7672cf81b
9 changed files with 272 additions and 124 deletions

View file

@ -1,5 +1,6 @@
import chat_box.views as chat
from django.urls import include, path
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
@ -468,6 +469,8 @@ urlpatterns = [
url(r"^comments/upvote/$", comment.upvote_comment, name="comment_upvote"),
url(r"^comments/downvote/$", comment.downvote_comment, name="comment_downvote"),
url(r"^comments/hide/$", comment.comment_hide, name="comment_hide"),
url(r"^comments/reply/$", comment.get_reply, name="comment_reply"),
url(r"^comments/showmore/$", comment.get_showmore, name="comment_show_more"),
url(
r"^comments/(?P<id>\d+)/",
include(

View file

@ -162,14 +162,14 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
def get_context_data(self, **kwargs):
context = super(CommentedDetailView, self).get_context_data(**kwargs)
queryset = self.object.comments
context["replies"] = len(queryset.filter(parent=None))
queryset = (
queryset.filter(parent=None)[:10].select_related("author__user")
.defer("author__about")
.annotate(revisions=Count("versions")).annotate(count_replies=Count("replies"))
)
context["has_comments"] = queryset.exists()
context["comment_lock"] = self.is_comment_locked()
queryset = (
queryset.select_related("author__user")
.defer("author__about")
.annotate(revisions=Count("versions"))
)
if self.request.user.is_authenticated:
profile = self.request.profile
queryset = queryset.annotate(
@ -184,6 +184,10 @@ class CommentedDetailView(TemplateResponseMixin, SingleObjectMixin, View):
).exists()
)
context["comment_list"] = queryset
context["comment_count"] = len(queryset)
# context["comment_count"] = len(queryset)
context["vote_hide_threshold"] = settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD
context["comment_root_id"] = 0
context["offset"] = 10
context["limit"] = 10
return context

View file

@ -56,6 +56,7 @@ class Comment(MPTTModel):
related_name="replies",
on_delete=CASCADE,
)
versions = VersionRelation()
class Meta:

View file

@ -1,8 +1,13 @@
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.auth.context_processors import PermWrapper
from django.core.exceptions import PermissionDenied
from django.db import IntegrityError, transaction
from django.db.models import F
from django.db.models import Q, F, Count, FilteredRelation
from django.db.models.functions import Coalesce
from django.db.models.expressions import F, Value
from django.forms.models import ModelForm
from django.http import (
Http404,
@ -15,11 +20,12 @@ from django.utils.translation import gettext as _
from django.views.decorators.http import require_POST
from django.views.generic import DetailView, UpdateView
from django.urls import reverse_lazy
from django.template import loader
from reversion import revisions
from reversion.models import Version
from judge.dblock import LockModel
from judge.models import Comment, CommentVote, Notification
from judge.models import Comment, CommentVote, Notification, BlogPost
from judge.utils.views import TitleMixin
from judge.widgets import MathJaxPagedownWidget, HeavyPreviewPageDownWidget
from judge.comments import add_mention_notifications, del_mention_notifications
@ -34,6 +40,11 @@ __all__ = [
@login_required
# def get_more_reply(request, id):
# queryset = Comment.get_pk(id)
def vote_comment(request, delta):
if abs(delta) != 1:
return HttpResponseBadRequest(
@ -97,10 +108,67 @@ def vote_comment(request, delta):
def upvote_comment(request):
return vote_comment(request, 1)
def downvote_comment(request):
return vote_comment(request, -1)
def get_comment(request, limit=10):
try:
comment_id = int(request.GET["id"])
page_id = int(request.GET["page"])
except ValueError:
return HttpResponseBadRequest()
else:
if comment_id and not Comment.objects.filter(id=comment_id).exists():
raise Http404()
if not BlogPost.objects.filter(id=page_id).exists():
raise Http404()
offset = 0
if "offset" in request.GET:
offset = int(request.GET["offset"])
comment_root_id = 0
if (comment_id):
comment_obj = Comment.objects.get(pk=comment_id)
comment_root_id = comment_obj.id
else:
comment_obj = None
page_obj = BlogPost.objects.get(pk=page_id)
queryset = page_obj.comments
replies = len(queryset.filter(parent=comment_obj))
queryset = (
queryset.filter(parent=comment_obj)[offset:offset+limit].select_related("author__user")
.defer("author__about")
.annotate(revisions=Count("versions")).annotate(count_replies=Count("replies"))
)
if request.user.is_authenticated:
profile = request.profile
queryset = queryset.annotate(
my_vote=FilteredRelation(
"votes", condition=Q(votes__voter_id=profile.id)
),
).annotate(vote_score=Coalesce(F("my_vote__score"), Value(0)))
comment_html = loader.render_to_string(
"comments/content-list.html",
{
"request": request,
"comment_root_id": comment_root_id,
"comment_list": queryset,
"vote_hide_threshold" : settings.DMOJ_COMMENT_VOTE_HIDE_THRESHOLD,
"perms": PermWrapper(request.user),
"object": page_obj,
"offset": offset + min(len(queryset), limit),
"replies": replies,
"limit": limit
}
)
return HttpResponse(comment_html)
def get_showmore(request):
return get_comment(request)
def get_reply(request):
return get_comment(request)
class CommentMixin(object):
model = Comment

View file

@ -121,6 +121,18 @@ a {
margin: -50px 23px 10px -40px;
padding-top: 50px;
}
.show_more_reply {
font-weight: bold;
display: block;
margin: 16px 40px;
}
.show_more_comment {
font-weight: bold;
display: block;
margin: 0 -40px;
}
}
.no-comments-message {

View file

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

View file

@ -0,0 +1,121 @@
{% set logged_in = request.user.is_authenticated %}
{% set profile = request.profile if logged_in else None %}
{% for node in mptt_tree(comment_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>
{% with author=node.author, user=node.author.user %}
<a href="{{ url('user_page', user.username) }}" class="user">
<img src="{{ gravatar(author, 135) }}" class="gravatar">
</a>
{% endwith %}
</div>
<div class="detail">
<div class="header">
{{ link_user(node.author) }}&nbsp;
{{ relative_time(node.time, abs=_('commented on {time}'), rel=_('commented {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>
<!-- {{ node.count_replies }}
{{node.revisions - 1}} -->
{% if node.revisions == 1 %}
{% set real_replies = node.count_replies - node.revisions + 1 %}
{% else %}
{% set real_replies = node.count_replies - node.revisions + 2 %}
{% endif %}
{% if real_replies > 1 %}
<a href="javascript:comment_reply({{ node.id }}, {{ object.id }})" class="show_more_reply"> {{ real_replies }} {{ _(' Replies ') }} </a>
{% elif real_replies %}
<a href="javascript:comment_reply({{ node.id }}, {{ object.id }})" class="show_more_reply"> {{ real_replies }} {{ _(' Reply ') }} </a>
{% endif %}
</li>
<ul id="comment-{{ node.id }}-reply" class="reply-comment" hidden></ul>
<ul id="comment-{{ node.id }}-children" class="comments"> </ul>
{% endfor %}
{% if replies - offset > 0 %}
<a href="javascript:comment_show_more({{ comment_root_id }}, {{ object.id }}, {{ offset }} )" class="show_more_comment"> {{ replies - offset }} Replies More</a>
{% endif %}

View file

@ -37,118 +37,8 @@
</div>
{% endif %}
{% if has_comments %}
<ul class="comments top-level-comments new-comments">
{% set logged_in = request.user.is_authenticated %}
{% set profile = request.profile if logged_in else None %}
{% for node in mptt_tree(comment_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>
{% with author=node.author, user=node.author.user %}
<a href="{{ url('user_page', user.username) }}" class="user">
<img src="{{ gravatar(author, 135) }}" class="gravatar">
</a>
{% endwith %}
</div>
<div class="detail">
<div class="header">
{{ link_user(node.author) }}&nbsp;
{{ relative_time(node.time, abs=_('commented on {time}'), rel=_('commented {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 %}
<ul class="comments top-level-comments new-comments" id="comment-0">
{% include "comments/content-list.html" %}
</ul>
{% elif not comment_lock %}
<p class="no-comments-message">{{ _('There are no comments at the moment.') }}</p>

View file

@ -120,6 +120,55 @@
});
}
window.comment_reply = function (id, page) {
ajax_get_reply('{{ url('comment_reply') }}', id, page);
}
function ajax_get_reply(url, id, page) {
return $.ajax({
url: url,
type: 'GET',
data: {
id: id,
page: page,
},
success: function(data) {
var $comment = $("#comment-" + id + "-children");
var $comment_show_btn = $("#comment-" + id + " .show_more_reply");
console.log($comment_show_btn);
$comment_show_btn.hide();
$comment.append(data);
}
})
}
window.comment_show_more = function (id, page, offset) {
ajax_comment_show_more('{{ url('comment_show_more') }}', id, page, offset);
}
function ajax_comment_show_more(url, id, page, offset) {
return $.ajax({
url: url,
type: 'GET',
data: {
id: id,
page: page,
offset: offset,
},
success: function(data) {
var $comment_show_btn = $("#comment-" + id + " .show_more_comment");
$comment_show_btn.hide();
if (id == 0) {
var $comment = $("#comment-" + id);
$comment.append(data);
} else {
var $comment = $("#comment-" + id + "-children");
$comment.append(data);
}
}
})
}
var get_$votes = function (id) {
var $comment = $('#comment-' + id);
return {