Merge branch 'feature/kevin/flagging' of github.com:MITx/mitx into feature/kevin/flagging

This commit is contained in:
marco
2012-12-06 16:43:19 -05:00
10 changed files with 75 additions and 46 deletions

View File

@@ -10,7 +10,7 @@ urlpatterns = patterns('django_comment_client.base.views',
url(r'threads/(?P<thread_id>[\w\-]+)/reply$', 'create_comment', name='create_comment'),
url(r'threads/(?P<thread_id>[\w\-]+)/delete', 'delete_thread', name='delete_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/upvote$', 'vote_for_thread', {'value': 'up'}, name='upvote_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/flagAbuse$', 'flag_abuse_for_thread', {'value': 'up'}, name='flag_abuse_for_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/flagAbuse$', 'flag_abuse_for_thread', name='flag_abuse_for_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/unFlagAbuse$', 'un_flag_abuse_for_thread', name='un_flag_abuse_for_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/downvote$', 'vote_for_thread', name='downvote_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/unvote$', 'undo_vote_for_thread', name='undo_vote_for_thread'),
@@ -25,8 +25,8 @@ urlpatterns = patterns('django_comment_client.base.views',
url(r'comments/(?P<comment_id>[\w\-]+)/upvote$', 'vote_for_comment', {'value': 'up'}, name='upvote_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/downvote$', 'vote_for_comment', {'value': 'down'}, name='downvote_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/unvote$', 'undo_vote_for_comment', name='undo_vote_for_comment'),
url(r'threads/(?P<comment_id>[\w\-]+)/flagAbuse$', 'flag_abuse_for_comment', name='flag_abuse_for_comment'),
url(r'threads/(?P<comment_id>[\w\-]+)/unFlagAbuse$', 'un_flag_abuse_for_comment', name='un_flag_abuse_for_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/flagAbuse$', 'flag_abuse_for_comment', name='flag_abuse_for_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/unFlagAbuse$', 'un_flag_abuse_for_comment', name='un_flag_abuse_for_comment'),
url(r'(?P<commentable_id>[\w\-]+)/threads/create$', 'create_thread', name='create_thread'),
# TODO should we search within the board?

View File

@@ -238,28 +238,28 @@ def vote_for_thread(request, course_id, thread_id, value):
@require_POST
@login_required
@permitted
def flag_abuse_for_thread(request, course_id, thread_id, value):
def flag_abuse_for_thread(request, course_id, thread_id):
user = cc.User.from_django_user(request.user)
thread = cc.Thread.find(thread_id)
thread.flagAbuse(user,thread, value)
thread.flagAbuse(user,thread)
return JsonResponse(utils.safe_content(thread.to_dict()))
def un_flag_abuse_for_thread(request, course_id, thread_id, value):
def un_flag_abuse_for_thread(request, course_id, thread_id):
user = cc.User.from_django_user(request.user)
thread = cc.Thread.find(thread_id)
thread.unFlagAbuse(user,thread, value)
thread.unFlagAbuse(user,thread)
return JsonResponse(utils.safe_content(thread.to_dict()))
def flag_abuse_for_comment(request, course_id, comment_id, value):
def flag_abuse_for_comment(request, course_id, comment_id):
user = cc.User.from_django_user(request.user)
comment = cc.Comment.find(thread_id)
comment.flagAbuse(user,comment, value)
comment = cc.Comment.find(comment_id)
comment.flagAbuse(user,comment)
return JsonResponse(utils.safe_content(comment.to_dict()))
def un_flag_abuse_for_comment(request, course_id, comment_id, value):
def un_flag_abuse_for_comment(request, course_id, comment_id):
user = cc.User.from_django_user(request.user)
comment = cc.Comment.find(thread_id)
comment.unFlagAbuse(user,comment, value)
comment = cc.Comment.find(comment_id)
comment.unFlagAbuse(user,comment)
return JsonResponse(utils.safe_content(comment.to_dict()))
@require_POST

View File

@@ -72,7 +72,6 @@ def inline_discussion(request, course_id, discussion_id):
"""
Renders JSON for DiscussionModules
"""
course = get_course_with_access(request.user, course_id, 'load')
try:
@@ -161,26 +160,26 @@ def forum_form_discussion(request, course_id):
@login_required
def single_thread(request, course_id, discussion_id, thread_id):
course = get_course_with_access(request.user, course_id, 'load')
cc_user = cc.User.from_django_user(request.user)
user_info = cc_user.to_dict()
try:
thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id)
thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id)
except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError) as err:
log.error("Error loading single thread.")
raise Http404
log.error("Error loading single thread.")
raise Http404
if request.is_ajax():
courseware_context = get_courseware_context(thread, course)
annotated_content_info = utils.get_annotated_content_infos(course_id, thread, request.user, user_info=user_info)
context = {'thread': thread.to_dict(), 'course_id': course_id}
# TODO: Remove completely or switch back to server side rendering
# html = render_to_string('discussion/_ajax_single_thread.html', context)
content = utils.safe_content(thread.to_dict())
log.debug("*************************")
log.debug(content)
if courseware_context:
content.update(courseware_context)
return utils.JsonResponse({

View File

@@ -41,22 +41,22 @@ class Comment(models.Model):
else:
return super(Comment, cls).url(action, params)
def flagAbuse(self, user, voteable, value):
def flagAbuse(self, user, voteable):
if voteable.type == 'thread':
url = _url_for_flag_abuse_thread(voteable.id)
elif voteable.type == 'comment':
url = _url_for_flag_comment(voteable.id)
url = _url_for_flag_abuse_comment(voteable.id)
else:
raise CommentClientError("Can only flag/unflag threads or comments")
params = {'user_id': user.id}
request = perform_request('put', url, params)
voteable.update_attributes(request)
def unFlagAbuse(self, user, voteable, value):
def unFlagAbuse(self, user, voteable):
if voteable.type == 'thread':
url = _url_for_unflag_abuse_thread(voteable.id)
elif voteable.type == 'comment':
url = _url_for_unflag_comment(voteable.id)
url = _url_for_unflag_abuse_comment(voteable.id)
else:
raise CommentClientError("Can flag/unflag for threads or comments")
params = {'user_id': user.id}
@@ -70,7 +70,7 @@ def _url_for_comment(comment_id):
return "{prefix}/comments/{comment_id}".format(prefix=settings.PREFIX, comment_id=comment_id)
def _url_for_flag_abuse_comment(comment_id):
return "{prefix}/threads/{comment_id}/abuse_flags".format(prefix=settings.PREFIX, thread_id=thread_id)
return "{prefix}/comments/{comment_id}/abuse_flags".format(prefix=settings.PREFIX, comment_id=comment_id)
def _url_for_unflag_abuse_thread(comment_id):
return "{prefix}/threads/{comment_id}/abuse_unflags".format(prefix=settings.PREFIX, thread_id=thread_id)
def _url_for_unflag_abuse_comment(comment_id):
return "{prefix}/comments/{comment_id}/abuse_unflags".format(prefix=settings.PREFIX, comment_id=comment_id)

View File

@@ -26,6 +26,7 @@ class Thread(models.Model):
@classmethod
def search(cls, query_params, *args, **kwargs):
default_params = {'page': 1,
'per_page': 20,
'course_id': query_params['course_id'],
@@ -65,15 +66,20 @@ class Thread(models.Model):
# that subclasses don't need to override for this.
def _retrieve(self, *args, **kwargs):
url = self.url(action='get', params=self.attributes)
request_params = {
'recursive': kwargs.get('recursive'),
'user_id': kwargs.get('user_id'),
'mark_as_read': kwargs.get('mark_as_read', True),
}
def flagAbuse(self, user, voteable, value):
# user_id may be none, in which case it shouldn't be part of the
# request.
request_params = strip_none(request_params)
response = perform_request('get', url, request_params)
self.update_attributes(**response)
def flagAbuse(self, user, voteable):
if voteable.type == 'thread':
url = _url_for_flag_abuse_thread(voteable.id)
elif voteable.type == 'comment':
@@ -84,7 +90,7 @@ class Thread(models.Model):
request = perform_request('put', url, params)
voteable.update_attributes(request)
def unFlagAbuse(self, user, voteable, value):
def unFlagAbuse(self, user, voteable):
if voteable.type == 'thread':
url = _url_for_unflag_abuse_thread(voteable.id)
elif voteable.type == 'comment':

View File

@@ -50,6 +50,8 @@ class @DiscussionUtil
delete_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/delete"
flagAbuse_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/flagAbuse"
unFlagAbuse_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/unFlagAbuse"
flagAbuse_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/flagAbuse"
unFlagAbuse_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/unFlagAbuse"
upvote_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/upvote"
downvote_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/downvote"
undo_vote_for_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/unvote"

View File

@@ -72,17 +72,7 @@ if Backbone?
toggleFollowing: (event) ->
$elem = $(event.target)
url = nullunFlagAbuse: ->
url = @model.urlFor("unFlagAbuse")
DiscussionUtil.safeAjax
$elem: @$(".discussion-flag-abuse")
url: url
type: "POST"
success: (response, textStatus) =>
if textStatus == 'success'
temp_array = _.clone(@model.get('abuse_flaggers'));
temp_array.pop(window.user.id)
@model.set('abuse_flaggers', temp_array)
url = null
if not @model.get('subscribed')
@model.follow()
url = @model.urlFor("follow")
@@ -92,7 +82,7 @@ if Backbone?
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
type: "POST"
vote: ->
window.user.vote(@model)

View File

@@ -1,7 +1,14 @@
if Backbone?
class @ResponseCommentShowView extends DiscussionContentView
events:
"click .discussion-flag-abuse": "toggleFlagAbuse"
tagName: "li"
initialize: ->
super()
@model.on "change", @updateModelDetails
render: ->
@template = _.template($("#response-comment-show-template").html())
@@ -11,6 +18,7 @@ if Backbone?
@initLocal()
@delegateEvents()
@renderAttrs()
@renderFlagged()
@markAsStaff()
@$el.find(".timeago").timeago()
@convertMath()
@@ -36,4 +44,15 @@ if Backbone?
@$el.find("a.profile-link").after('<span class="community-ta-label">Community&nbsp;&nbsp;TA</span>')
renderFlagged: =>
if window.user.id in @model.get("abuse_flaggers")
@$("[data-role=thread-flag]").addClass("flagged")
@$("[data-role=thread-flag]").removeClass("notflagged")
else
@$("[data-role=thread-flag]").removeClass("flagged")
@$("[data-role=thread-flag]").addClass("notflagged")
updateModelDetails: =>
@renderFlagged()

View File

@@ -24,6 +24,7 @@ if Backbone?
if window.user.voted(@model)
@$(".vote-btn").addClass("is-cast")
@renderAttrs()
@renderFlagged()
@$el.find(".posted-details").timeago()
@convertMath()
@markAsStaff()
@@ -94,3 +95,17 @@ if Backbone?
url: url
data: data
type: "POST"
renderFlagged: =>
if window.user.id in @model.get("abuse_flaggers")
@$("[data-role=thread-flag]").addClass("flagged")
@$("[data-role=thread-flag]").removeClass("notflagged")
@$(".discussion-flag-abuse .flag-label").html("Misuse Reported")
else
@$("[data-role=thread-flag]").removeClass("flagged")
@$("[data-role=thread-flag]").addClass("notflagged")
@$(".discussion-flag-abuse .flag-label").html("Report Misuse")
updateModelDetails: =>
@renderFlagged()

View File

@@ -44,7 +44,6 @@
</header>
<div class="post-body">${'<%- body %>'}</div>
<div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="flag">
<i class="icon"></i><span class="flag-label">Report Misuse</span></div>
@@ -111,7 +110,6 @@
<p class="posted-details" title="${'<%- created_at %>'}">${'<%- created_at %>'}</p>
</header>
<div class="response-local"><div class="response-body">${"<%- body %>"}</div>
<div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="flag">
<i class="icon"></i><span class="flag-label">Report Misuse</span></div>
</div>
@@ -138,7 +136,7 @@
<div id="comment_${'<%- id %>'}">
<div class="response-body">${'<%- body %>'}</div>
<div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="flag">
<i class="icon"></i><span class="flag-label">Report Misuse</span></div>
<i class="icon"></i><span class="flag-label"></span></div>
<p class="posted-details">&ndash;posted <span class="timeago" title="${'<%- created_at %>'}">${'<%- created_at %>'}</span> by
${"<% if (obj.username) { %>"}
<a href="${'<%- user_url %>'}" class="profile-link">${'<%- username %>'}</a>