Commit fdf92d68 by Rocky Duan

more refactoring; enabled partial re-rendering for votes, endorse, and closed

parent 72e6588b
...@@ -51,7 +51,8 @@ def ajax_content_response(request, course_id, content, template_name): ...@@ -51,7 +51,8 @@ def ajax_content_response(request, course_id, content, template_name):
'content': content, 'content': content,
} }
html = render_to_string(template_name, context) html = render_to_string(template_name, context)
annotated_content_info = utils.get_annotated_content_info(course_id, content, request.user) user_info = cc.User.from_django_user(request.user).to_dict()
annotated_content_info = utils.get_annotated_content_info(course_id, content, request.user, user_info)
return JsonResponse({ return JsonResponse({
'html': html, 'html': html,
'content': content, 'content': content,
......
...@@ -15,7 +15,6 @@ from django_comment_client.permissions import check_permissions_by_view ...@@ -15,7 +15,6 @@ from django_comment_client.permissions import check_permissions_by_view
from django_comment_client.utils import merge_dict, extract, strip_none from django_comment_client.utils import merge_dict, extract, strip_none
import json import json
import dateutil
import django_comment_client.utils as utils import django_comment_client.utils as utils
import comment_client as cc import comment_client as cc
...@@ -64,14 +63,17 @@ def render_discussion(request, course_id, threads, *args, **kwargs): ...@@ -64,14 +63,17 @@ def render_discussion(request, course_id, threads, *args, **kwargs):
'user': (lambda: reverse('django_comment_client.forum.views.user_profile', args=[course_id, user_id])), 'user': (lambda: reverse('django_comment_client.forum.views.user_profile', args=[course_id, user_id])),
}[discussion_type]() }[discussion_type]()
annotated_content_infos = map(lambda x: utils.get_annotated_content_infos(course_id, x, request.user), threads) user_info = cc.User.from_django_user(request.user).to_dict()
annotated_content_info = reduce(merge_dict, annotated_content_infos, {})
def infogetter(thread):
return utils.get_annotated_content_infos(course_id, thread, request.user, user_info)
annotated_content_info = reduce(merge_dict, map(infogetter, threads), {})
context = { context = {
'threads': threads, 'threads': threads,
'discussion_id': discussion_id, 'discussion_id': discussion_id,
'user_id': user_id, 'user_id': user_id,
'user_info': json.dumps(cc.User.from_django_user(request.user).to_dict()),
'course_id': course_id, 'course_id': course_id,
'request': request, 'request': request,
'performed_search': _should_perform_search(request), 'performed_search': _should_perform_search(request),
...@@ -166,12 +168,13 @@ def render_single_thread(request, discussion_id, course_id, thread_id): ...@@ -166,12 +168,13 @@ def render_single_thread(request, discussion_id, course_id, thread_id):
thread = cc.Thread.find(thread_id).retrieve(recursive=True).to_dict() thread = cc.Thread.find(thread_id).retrieve(recursive=True).to_dict()
annotated_content_info = utils.get_annotated_content_infos(course_id, thread=thread, user=request.user) user_info = cc.User.from_django_user(request.user).to_dict()
annotated_content_info = utils.get_annotated_content_infos(course_id, thread=thread, user=request.user, user_info=user_info)
context = { context = {
'discussion_id': discussion_id, 'discussion_id': discussion_id,
'thread': thread, 'thread': thread,
'user_info': json.dumps(cc.User.from_django_user(request.user).to_dict()),
'annotated_content_info': json.dumps(annotated_content_info), 'annotated_content_info': json.dumps(annotated_content_info),
'course_id': course_id, 'course_id': course_id,
'request': request, 'request': request,
...@@ -183,8 +186,9 @@ def single_thread(request, course_id, discussion_id, thread_id): ...@@ -183,8 +186,9 @@ def single_thread(request, course_id, discussion_id, thread_id):
if request.is_ajax(): if request.is_ajax():
user_info = cc.User.from_django_user(request.user).to_dict()
thread = cc.Thread.find(thread_id).retrieve(recursive=True) thread = cc.Thread.find(thread_id).retrieve(recursive=True)
annotated_content_info = utils.get_annotated_content_infos(course_id, thread, request.user) 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} context = {'thread': thread.to_dict(), 'course_id': course_id}
html = render_to_string('discussion/_ajax_single_thread.html', context) html = render_to_string('discussion/_ajax_single_thread.html', context)
......
...@@ -160,23 +160,32 @@ class QueryCountDebugMiddleware(object): ...@@ -160,23 +160,32 @@ class QueryCountDebugMiddleware(object):
logging.info('%s queries run, total %s seconds' % (len(connection.queries), total_time)) logging.info('%s queries run, total %s seconds' % (len(connection.queries), total_time))
return response return response
def get_annotated_content_info(course_id, content, user): def get_annotated_content_info(course_id, content, user, user_info):
voted = ''
if content['id'] in user_info['upvoted_ids']:
voted = 'up'
elif content['id'] in user_info['downvoted_ids']:
voted = 'down'
return { return {
'editable': check_permissions_by_view(user, course_id, content, "update_thread" if content['type'] == 'thread' else "update_comment"), 'voted': voted,
'can_reply': check_permissions_by_view(user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_comment"), 'subscribed': content['id'] in user_info['subscribed_thread_ids'],
'can_endorse': check_permissions_by_view(user, course_id, content, "endorse_comment") if content['type'] == 'comment' else False, 'ability': {
'can_delete': check_permissions_by_view(user, course_id, content, "delete_thread" if content['type'] == 'thread' else "delete_comment"), 'editable': check_permissions_by_view(user, course_id, content, "update_thread" if content['type'] == 'thread' else "update_comment"),
'can_openclose': check_permissions_by_view(user, course_id, content, "openclose_thread") if content['type'] == 'thread' else False, 'can_reply': check_permissions_by_view(user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_comment"),
'can_vote': check_permissions_by_view(user, course_id, content, "vote_for_thread" if content['type'] == 'thread' else "vote_for_comment"), 'can_endorse': check_permissions_by_view(user, course_id, content, "endorse_comment") if content['type'] == 'comment' else False,
'can_delete': check_permissions_by_view(user, course_id, content, "delete_thread" if content['type'] == 'thread' else "delete_comment"),
'can_openclose': check_permissions_by_view(user, course_id, content, "openclose_thread") if content['type'] == 'thread' else False,
'can_vote': check_permissions_by_view(user, course_id, content, "vote_for_thread" if content['type'] == 'thread' else "vote_for_comment"),
},
} }
def get_annotated_content_infos(course_id, thread, user): def get_annotated_content_infos(course_id, thread, user, user_info):
infos = {} infos = {}
def _annotate(content): def annotate(content):
infos[str(content['id'])] = get_annotated_content_info(course_id, content, user) infos[str(content['id'])] = get_annotated_content_info(course_id, content, user, user_info)
for child in content.get('children', []): for child in content.get('children', []):
_annotate(child) annotate(child)
_annotate(thread) annotate(thread)
return infos return infos
def render_mustache(template_name, dictionary, *args, **kwargs): def render_mustache(template_name, dictionary, *args, **kwargs):
......
...@@ -9,60 +9,107 @@ class @Content extends Backbone.Model ...@@ -9,60 +9,107 @@ class @Content extends Backbone.Model
can_delete: '.admin-delete' can_delete: '.admin-delete'
can_openclose: '.admin-openclose' can_openclose: '.admin-openclose'
isUpvoted: -> urlMappers: {}
DiscussionUtil.isUpvoted @id
isDownvoted: -> urlFor: (name) ->
DiscussionUtil.isDownvoted @id @urlMappers[name].apply(@)
can: (action) -> can: (action) ->
DiscussionUtil.getContentInfo @id, action DiscussionUtil.getContentInfo @id, action
thread_id: -> updateInfo: (info) ->
if @get('type') == "comment" then @get('thread_id') else @id @set('ability', info.ability)
@set('voted', info.voted)
@set('subscribed', info.subscribed)
addComment: (comment) ->
@get('children').push comment
model = new Comment $.extend {}, comment, { thread: @get('thread') }
@get('comments').add model
model
resetComments: (children) ->
@set 'children', []
@set 'comments', new Comments()
for comment in (children || [])
@addComment comment
initialize: -> initialize: ->
@set('comments', new Comments()) DiscussionUtil.addContent @id, @
if @get('children') @resetComments(@get('children'))
@get('comments').reset @get('children'), {silent: false}
class @ContentView extends Backbone.View class @ContentView extends Backbone.View
$: (selector) -> $: (selector) ->
@$local.find(selector) @$local.find(selector)
discussionContent: -> partial:
endorsed: (endorsed) ->
if endorsed
@$el.addClass("endorsed")
else
@$el.removeClass("endorsed")
closed: (closed) -> # we should just re-render the whole thread, or update according to new abilities
if closed
@$el.addClass("closed")
@$(".admin-openclose").text "Re-open Thread"
else
@$el.removeClass("closed")
@$(".admin-openclose").text "Close Thread"
voted: (voted) ->
@$(".discussion-vote-up").removeClass("voted") if voted != "up"
@$(".discussion-vote-down").removeClass("voted") if voted != "down"
@$(".discussion-vote-#{voted}").addClass("voted") if voted in ["up", "down"]
votes_point: (votes_point) ->
@$(".discussion-votes-point").html(votes_point)
subscribed: (subscribed) -> #later
ability: (ability) ->
for action, elemSelector of @model.actions
if not ability[action]
@$(elemSelector).remove()
$discussionContent: ->
@_discussionContent ||= @$el.children(".discussion-content") @_discussionContent ||= @$el.children(".discussion-content")
$showComments: ->
@_showComments ||= @$(".discussion-show-comments")
updateShowComments: ->
if @showed
@$showComments().html @$showComments().html().replace "Show", "Hide"
else
@$showComments().html @$showComments().html().replace "Hide", "Show"
retrieved: ->
@$showComments().hasClass("retrieved")
hideSingleThread: (event) -> hideSingleThread: (event) ->
$showComments = @$(".discussion-show-comments")
@$el.children(".comments").hide() @$el.children(".comments").hide()
@showed = false @showed = false
$showComments.html $showComments.html().replace "Hide", "Show" @updateShowComments()
showSingleThread: (event) -> showSingleThread: (event) ->
$showComments = @$(".discussion-show-comments") if @retrieved()
retrieved = not $showComments.hasClass("first-time") and @model.get("children") != undefined
if retrieved
@$el.children(".comments").show() @$el.children(".comments").show()
$showComments.html $showComments.html().replace "Show", "Hide"
@showed = true @showed = true
@updateShowComments()
else else
discussion_id = @model.discussion.id $elem = $.merge @$(".thread-title"), @$showComments()
url = DiscussionUtil.urlFor('retrieve_single_thread', discussion_id, @model.id) url = @model.urlFor('retrieve_single_thread')
DiscussionUtil.safeAjax DiscussionUtil.get $elem, url, (response, textStatus) =>
$elem: $.merge @$(".thread-title"), @$(".discussion-show-comments") @showed = true
url: url @updateShowComments()
type: "GET" @$showComments().addClass("retrieved")
dataType: 'json' @$el.children(".comments").replaceWith response.html
success: (response, textStatus) => @model.resetComments response.content.children
DiscussionUtil.bulkExtendContentInfo response['annotated_content_info'] @initCommentViews()
@showed = true DiscussionUtil.bulkUpdateContentInfo response.annotated_content_info
$showComments.html $showComments.html().replace "Show", "Hide"
@$el.append(response['html'])
@model.set('children', response.content.children)
@model.get('comments').reset response.content.children, {silent: false}
@initCommentViews()
toggleSingleThread: (event) -> toggleSingleThread: (event) ->
if @showed if @showed
...@@ -83,12 +130,11 @@ class @ContentView extends Backbone.View ...@@ -83,12 +130,11 @@ class @ContentView extends Backbone.View
if $replyView.length if $replyView.length
$replyView.show() $replyView.show()
else else
thread_id = @model.thread_id() view = {}
view = view.id = @model.id
id: @model.id view.showWatchCheckbox = not @model.get('thread').get('subscribed')
showWatchCheckbox: not DiscussionUtil.isSubscribed(thread_id, "thread")
html = Mustache.render DiscussionUtil.getTemplate('_reply'), view html = Mustache.render DiscussionUtil.getTemplate('_reply'), view
@discussionContent().append html @$discussionContent().append html
DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "reply-body" DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "reply-body"
@$(".discussion-submit-post").click $.proxy(@submitReply, @) @$(".discussion-submit-post").click $.proxy(@submitReply, @)
@$(".discussion-cancel-post").click $.proxy(@cancelReply, @) @$(".discussion-cancel-post").click $.proxy(@cancelReply, @)
...@@ -96,13 +142,7 @@ class @ContentView extends Backbone.View ...@@ -96,13 +142,7 @@ class @ContentView extends Backbone.View
@$(".discussion-edit").hide() @$(".discussion-edit").hide()
submitReply: (event) -> submitReply: (event) ->
if @model.get('type') == 'thread' url = @model.urlFor('reply')
url = DiscussionUtil.urlFor('create_comment', @model.id)
else if @model.get('type') == 'comment'
url = DiscussionUtil.urlFor('create_sub_comment', @model.id)
else
console.error "unrecognized model type #{@model.get('type')}"
return
body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "reply-body" body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "reply-body"
...@@ -122,19 +162,13 @@ class @ContentView extends Backbone.View ...@@ -122,19 +162,13 @@ class @ContentView extends Backbone.View
success: (response, textStatus) => success: (response, textStatus) =>
DiscussionUtil.clearFormErrors @$(".discussion-errors") DiscussionUtil.clearFormErrors @$(".discussion-errors")
$comment = $(response.html) $comment = $(response.html)
@$el.children(".comments").prepend($comment) @$el.children(".comments").prepend $comment
DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "reply-body", "" DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "reply-body", ""
#DiscussionUtil.setContentInfo response.content['id'], 'can_reply', true comment = @model.addComment response.content
#DiscussionUtil.setContentInfo response.content['id'], 'editable', true comment.updateInfo response.annotated_content_info
comment = new Comment(response.content)
DiscussionUtil.extendContentInfo comment.id, response['annotated_content_info']
@model.get('children').push(response.content)
@model.get('comments').add(comment)
commentView = new CommentView el: $comment[0], model: comment commentView = new CommentView el: $comment[0], model: comment
@$(".discussion-reply-new").hide() @cancelReply()
@$(".discussion-reply").show()
@$(".discussion-edit").show()
@discussionContent().attr("status", "normal")
cancelReply: -> cancelReply: ->
$replyView = @$(".discussion-reply-new") $replyView = @$(".discussion-reply-new")
if $replyView.length if $replyView.length
...@@ -143,77 +177,42 @@ class @ContentView extends Backbone.View ...@@ -143,77 +177,42 @@ class @ContentView extends Backbone.View
@$(".discussion-edit").show() @$(".discussion-edit").show()
unvote: (event) -> unvote: (event) ->
url = DiscussionUtil.urlFor("undo_vote_for_#{@model.get('type')}", @model.id) url = @model.urlFor('unvote')
DiscussionUtil.safeAjax $elem = @$(".discussion-vote")
$elem: @$(".discussion-vote") DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
url: url @model.set('voted', '')
type: "POST" @model.set('votes_point', response.votes.point)
dataType: "json"
success: (response, textStatus) => vote: (event, value) ->
if textStatus == "success" url = @model.urlFor("#{value}vote")
@$(".discussion-vote").removeClass("voted") $elem = @$(".discussion-vote")
@$(".discussion-votes-point").html response.votes.point DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
@model.set('voted', value)
vote: (event) -> @model.set('votes_point', response.votes.point)
toggleVote: (event) ->
$elem = $(event.target) $elem = $(event.target)
if $elem.hasClass("voted") value = $elem.attr("value")
if @model.get("voted") == value
@unvote(event) @unvote(event)
else else
value = $elem.attr("value") @vote(event, value)
url = Discussion.urlFor("#{value}vote_#{@model.get('type')}", @model.id)
DiscussionUtil.safeAjax toggleEndorse: (event) ->
$elem: @$(".discussion-vote") $elem = $(event.target)
url: url url = @model.urlFor('endorse')
type: "POST" endorsed = @model.get('endorsed')
dataType: "json" data = { endorsed: not endorsed }
success: (response, textStatus) => DiscussionUtil.post $elem, url, data, (response, textStatus) =>
if textStatus == "success" @model.set('endorsed', not endorsed)
@$(".discussion-vote").removeClass("voted")
@$(".discussion-vote-#{value}").addClass("voted") toggleClosed: (event) ->
@$(".discussion-votes-point").html response.votes.point $elem = $(event.target)
url = @model.urlFor('close')
endorse: (event) -> closed = @model.get('closed')
url = DiscussionUtil.urlFor('endorse_comment', @model.id) data = { closed: not closed }
endorsed = not @$el.hasClass("endorsed") DiscussionUtil.post $elem, url, data, (response, textStatus) =>
Discussion.safeAjax @model.set('closed', not closed)
$elem: $(event.target)
url: url
type: "POST"
dataType: "json"
data: {endorsed: endorsed}
success: (response, textStatus) =>
if textStatus == "success"
if endorsed
@$el.addClass("endorsed")
else
@$el.removeClass("endorsed")
close: (event) ->
url = DiscussionUtil.urlFor('openclose_thread', @model.id)
closed = undefined
text = $(event.target).text()
if text.match(/Close/)
closed = true
else if text.match(/[Oo]pen/)
closed = false
else
console.log "Unexpected text " + text + "for open/close thread."
Discussion.safeAjax
$elem: $(event.target)
url: url
type: "POST"
dataType: "json"
data: {closed: closed}
success: (response, textStatus) =>
if textStatus == "success"
if closed
@$el.addClass("closed")
$(event.target).text "Re-open Thread"
else
@$el.removeClass("closed")
$(event.target).text "Close Thread"
error: (response, textStatus, e) ->
console.log e
edit: -> edit: ->
$local(".discussion-content-wrapper").hide() $local(".discussion-content-wrapper").hide()
...@@ -227,7 +226,7 @@ class @ContentView extends Backbone.View ...@@ -227,7 +226,7 @@ class @ContentView extends Backbone.View
body: $local(".thread-raw-body").html() body: $local(".thread-raw-body").html()
tags: $local(".thread-raw-tags").html() tags: $local(".thread-raw-tags").html()
} }
@discussionContent().append Mustache.render Discussion.editThreadTemplate, view @$discussionContent().append Mustache.render Discussion.editThreadTemplate, view
Discussion.makeWmdEditor $content, $local, "thread-body-edit" Discussion.makeWmdEditor $content, $local, "thread-body-edit"
$local(".thread-tags-edit").tagsInput Discussion.tagsInputOptions() $local(".thread-tags-edit").tagsInput Discussion.tagsInputOptions()
$local(".discussion-submit-update").unbind("click").click -> handleSubmitEditThread(this) $local(".discussion-submit-update").unbind("click").click -> handleSubmitEditThread(this)
...@@ -247,7 +246,7 @@ class @ContentView extends Backbone.View ...@@ -247,7 +246,7 @@ class @ContentView extends Backbone.View
error: Discussion.formErrorHandler($local(".discussion-update-errors")) error: Discussion.formErrorHandler($local(".discussion-update-errors"))
success: (response, textStatus) -> success: (response, textStatus) ->
Discussion.clearFormErrors($local(".discussion-update-errors")) Discussion.clearFormErrors($local(".discussion-update-errors"))
@discussionContent().replaceWith(response.html) @$discussionContent().replaceWith(response.html)
Discussion.extendContentInfo response.content['id'], response['annotated_content_info'] Discussion.extendContentInfo response.content['id'], response['annotated_content_info']
Discussion.initializeContent($content) Discussion.initializeContent($content)
Discussion.bindContentEvents($content) Discussion.bindContentEvents($content)
...@@ -274,15 +273,15 @@ class @ContentView extends Backbone.View ...@@ -274,15 +273,15 @@ class @ContentView extends Backbone.View
console.log e console.log e
events: events:
"click .thread-title": "showSingleThread" "click .thread-title": "toggleSingleThread"
"click .discussion-show-comments": "showSingleThread" "click .discussion-show-comments": "toggleSingleThread"
"click .discussion-reply-thread": "reply" "click .discussion-reply-thread": "reply"
"click .discussion-reply-comment": "reply" "click .discussion-reply-comment": "reply"
"click .discussion-cancel-reply": "cancelReply" "click .discussion-cancel-reply": "cancelReply"
"click .discussion-vote-up": "vote" "click .discussion-vote-up": "toggleVote"
"click .discussion-vote-down": "vote" "click .discussion-vote-down": "toggleVote"
"click .admin-endorse": "endorse" "click .admin-endorse": "toggleEndorse"
"click .admin-openclose": "close" "click .admin-openclose": "toggleClosed"
"click .admin-edit": "edit" "click .admin-edit": "edit"
"click .admin-delete": "delete" "click .admin-delete": "delete"
...@@ -290,57 +289,65 @@ class @ContentView extends Backbone.View ...@@ -290,57 +289,65 @@ class @ContentView extends Backbone.View
@$local = @$el.children(".local") @$local = @$el.children(".local")
@$delegateElement = @$local @$delegateElement = @$local
initFollowThread: ->
$el.children(".discussion-content")
.find(".follow-wrapper")
.append(DiscussionUtil.subscriptionLink('thread', id))
initVote: ->
if @model.isUpvoted()
@$(".discussion-vote-up").addClass("voted")
else if @model.isDownvoted()
@$(".discussion-vote-down").addClass("voted")
initBody: -> initBody: ->
$contentBody = @$(".content-body") $contentBody = @$(".content-body")
$contentBody.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight $contentBody.html() $contentBody.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight $contentBody.html()
MathJax.Hub.Queue ["Typeset", MathJax.Hub, $contentBody.attr("id")] MathJax.Hub.Queue ["Typeset", MathJax.Hub, $contentBody.attr("id")]
initActions: ->
for action, elemSelector of @model.actions
if not @model.can action
@$(elemSelector).remove()
initTimeago: -> initTimeago: ->
@$("span.timeago").timeago() @$("span.timeago").timeago()
initPermalink: -> initPermalink: ->
@$(".discussion-permanent-link").attr "href", @model.permalink()
if @model.get('type') == 'thread' renderPartial: ->
discussion_id = @model.get('commentable_id') for attr, value of @model.changedAttributes()
permalink = Discussion.urlFor("permanent_link_thread", discussion_id, @model.id) if @partial[attr]
else @partial[attr].apply(@, [value])
thread_id = @model.get('thread_id')
discussion_id = @$el.parents(".thread").attr("_discussion_id")
permalink = Discussion.urlFor("permanent_link_comment", discussion_id, thread_id, @model.id)
@$(".discussion-permanent-link").attr "href", permalink initBindings: ->
@model.view = @
@model.bind('change', @renderPartial, @)
initialize: -> initialize: ->
@model.view = @ @initBindings()
@initLocal() @initLocal()
@initVote()
@initTimeago() @initTimeago()
@initBody() @initBody()
@initPermalink() @initPermalink()
@initActions()
@initCommentViews() @initCommentViews()
class @Thread extends @Content class @Thread extends @Content
urlMappers:
'retrieve_single_thread': -> DiscussionUtil.urlFor('retrieve_single_thread', @discussion.id, @id)
'reply': -> DiscussionUtil.urlFor('create_comment', @id)
'unvote': -> DiscussionUtil.urlFor("undo_vote_for_#{@get('type')}", @id)
'upvote': -> DiscussionUtil.urlFor("upvote_#{@get('type')}", @id)
'downvote': -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
'close': -> DiscussionUtil.urlFor('openclose_thread', @id)
initialize: ->
@set('thread', @)
super()
permalink: ->
discussion_id = @get('commentable_id')
return Discussion.urlFor("permanent_link_thread", discussion_id, @id)
class @ThreadView extends @ContentView class @ThreadView extends @ContentView
class @Comment extends @Content class @Comment extends @Content
urlMappers:
'reply': -> DiscussionUtil.urlFor('create_sub_comment', @id)
'unvote': -> DiscussionUtil.urlFor("undo_vote_for_#{@get('type')}", @id)
'upvote': -> DiscussionUtil.urlFor("upvote_#{@get('type')}", @id)
'downvote': -> DiscussionUtil.urlFor("downvote_#{@get('type')}", @id)
'endorse': -> DiscussionUtil.urlFor('endorse_comment', @id)
permalink: ->
thread_id = @get('thread').id
discussion_id = @get('thread').get('commentable_id')
return Discussion.urlFor("permanent_link_comment", discussion_id, thread_id, @id)
class @CommentView extends @ContentView class @CommentView extends @ContentView
......
class @Discussion extends Backbone.Collection class @Discussion extends Backbone.Collection
model: Thread model: Thread
initialize: -> initialize: ->
DiscussionUtil.addDiscussion @id, @
@bind "add", (item) => @bind "add", (item) =>
console.log item
item.discussion = @ item.discussion = @
find: (id) -> find: (id) ->
......
$ -> $ ->
window.$$contents = {}
window.$$discussions = {}
$(".discussion-module").each (index, elem) -> $(".discussion-module").each (index, elem) ->
view = new DiscussionModuleView(el: elem) view = new DiscussionModuleView(el: elem)
...@@ -8,3 +11,5 @@ $ -> ...@@ -8,3 +11,5 @@ $ ->
discussion = new Discussion() discussion = new Discussion()
discussion.reset(discussionData, {silent: false}) discussion.reset(discussionData, {silent: false})
view = new DiscussionView(el: elem, model: discussion) view = new DiscussionView(el: elem, model: discussion)
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
...@@ -12,26 +12,17 @@ class @DiscussionUtil ...@@ -12,26 +12,17 @@ class @DiscussionUtil
id = $(id).attr("_id") id = $(id).attr("_id")
return $$discussion_data[id] return $$discussion_data[id]
@getContentInfo: (id, attr) -> @addContent: (id, content) -> window.$$contents[id] = content
if not window.$$annotated_content_info?
window.$$annotated_content_info = {} @getContent: (id) -> window.$$contents[id]
(window.$$annotated_content_info[id] || {})[attr]
@addDiscussion: (id, discussion) -> window.$$discussions[id] = discussion
@setContentInfo: (id, attr, value) ->
if not window.$$annotated_content_info? @getDiscussion: (id) -> window.$$discussions[id]
window.$$annotated_content_info = {}
window.$$annotated_content_info[id] ||= {} @bulkUpdateContentInfo: (infos) ->
window.$$annotated_content_info[id][attr] = value for id, info of infos
@getContent(id).updateInfo(info)
@extendContentInfo: (id, newInfo) ->
if not window.$$annotated_content_info?
window.$$annotated_content_info = {}
window.$$annotated_content_info[id] = newInfo
@bulkExtendContentInfo: (newInfos) ->
if not window.$$annotated_content_info?
window.$$annotated_content_info = {}
window.$$annotated_content_info = $.extend window.$$annotated_content_info, newInfos
@generateDiscussionLink: (cls, txt, handler) -> @generateDiscussionLink: (cls, txt, handler) ->
$("<a>").addClass("discussion-link") $("<a>").addClass("discussion-link")
...@@ -79,9 +70,22 @@ class @DiscussionUtil ...@@ -79,9 +70,22 @@ class @DiscussionUtil
$.ajax(params).always -> $.ajax(params).always ->
$elem.removeAttr("disabled") $elem.removeAttr("disabled")
@handleAnchorAndReload: (response) -> @get: ($elem, url, success) ->
#window.location = window.location.pathname + "#" + response['id'] @safeAjax
window.location.reload() $elem: $elem
url: url
type: "GET"
dataType: "json"
success: success
@post: ($elem, url, data, success) ->
@safeAjax
$elem: $elem
url: url
type: "POST"
dataType: "json"
data: data
success: success
@bindLocalEvents: ($local, eventsHandler) -> @bindLocalEvents: ($local, eventsHandler) ->
for eventSelector, handler of eventsHandler for eventSelector, handler of eventsHandler
...@@ -98,22 +102,6 @@ class @DiscussionUtil ...@@ -98,22 +102,6 @@ class @DiscussionUtil
defaultText: "Tag your post: press enter after each tag" defaultText: "Tag your post: press enter after each tag"
removeWithBackspace: true removeWithBackspace: true
@isSubscribed: (id, type) ->
$$user_info? and (
if type == "thread"
id in $$user_info.subscribed_thread_ids
else if type == "commentable" or type == "discussion"
id in $$user_info.subscribed_commentable_ids
else
id in $$user_info.subscribed_user_ids
)
@isUpvoted: (id) ->
$$user_info? and (id in $$user_info.upvoted_ids)
@isDownvoted: (id) ->
$$user_info? and (id in $$user_info.downvoted_ids)
@formErrorHandler: (errorsField) -> @formErrorHandler: (errorsField) ->
(xhr, textStatus, error) -> (xhr, textStatus, error) ->
response = JSON.parse(xhr.responseText) response = JSON.parse(xhr.responseText)
......
...@@ -85,6 +85,7 @@ initializeFollowThread = (thread) -> ...@@ -85,6 +85,7 @@ initializeFollowThread = (thread) ->
Discussion.extendContentInfo response.content['id'], response['annotated_content_info'] Discussion.extendContentInfo response.content['id'], response['annotated_content_info']
Discussion.initializeContent($comment) Discussion.initializeContent($comment)
Discussion.bindContentEvents($comment) Discussion.bindContentEvents($comment)
@cancelReply()
$local(".discussion-reply-new").hide() $local(".discussion-reply-new").hide()
$local(".discussion-reply").show() $local(".discussion-reply").show()
$local(".discussion-edit").show() $local(".discussion-edit").show()
......
...@@ -5,11 +5,9 @@ ...@@ -5,11 +5,9 @@
</%def> </%def>
<%def name="render_content_with_comments(content)"> <%def name="render_content_with_comments(content)">
<div class="${content['type']}${helpers.show_if(' endorsed', content.get('endorsed'))}" _id="${content['id']}" _discussion_id="${content.get('commentable_id', '')}" _author_id="${helpers.show_if(content['user_id'], not content.get('anonymous'))}"> <div class="${content['type']}${helpers.show_if(' endorsed', content.get('endorsed'))}" _id="${content['id']}" _discussion_id="${content.get('commentable_id', '')}" _author_id="${helpers.show_if(content['user_id'], not content.get('anonymous'))}">
${render_content(content)} ${render_content(content)}
% if content.get('children') is not None: ${render_comments(content.get('children', []))}
${render_comments(content['children'])}
% endif
</div> </div>
</%def> </%def>
......
<%! from django.template.defaultfilters import escapejs %> <%! from django.template.defaultfilters import escapejs %>
<script type="text/javascript"> <script type="text/javascript">
var $$user_info = JSON.parse("${user_info | escapejs}");
var $$course_id = "${course_id | escapejs}"; var $$course_id = "${course_id | escapejs}";
if (typeof $$annotated_content_info === undefined) { if (typeof $$annotated_content_info === undefined) {
var $$annotated_content_info = {}; var $$annotated_content_info = {};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment