more refactoring; enabled partial re-rendering for votes, endorse, and closed
This commit is contained in:
@@ -51,7 +51,8 @@ def ajax_content_response(request, course_id, content, template_name):
|
||||
'content': content,
|
||||
}
|
||||
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({
|
||||
'html': html,
|
||||
'content': content,
|
||||
|
||||
@@ -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
|
||||
|
||||
import json
|
||||
import dateutil
|
||||
import django_comment_client.utils as utils
|
||||
import comment_client as cc
|
||||
|
||||
@@ -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])),
|
||||
}[discussion_type]()
|
||||
|
||||
annotated_content_infos = map(lambda x: utils.get_annotated_content_infos(course_id, x, request.user), threads)
|
||||
annotated_content_info = reduce(merge_dict, annotated_content_infos, {})
|
||||
user_info = cc.User.from_django_user(request.user).to_dict()
|
||||
|
||||
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 = {
|
||||
'threads': threads,
|
||||
'discussion_id': discussion_id,
|
||||
'user_id': user_id,
|
||||
'user_info': json.dumps(cc.User.from_django_user(request.user).to_dict()),
|
||||
'course_id': course_id,
|
||||
'request': request,
|
||||
'performed_search': _should_perform_search(request),
|
||||
@@ -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()
|
||||
|
||||
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 = {
|
||||
'discussion_id': discussion_id,
|
||||
'thread': thread,
|
||||
'user_info': json.dumps(cc.User.from_django_user(request.user).to_dict()),
|
||||
'annotated_content_info': json.dumps(annotated_content_info),
|
||||
'course_id': course_id,
|
||||
'request': request,
|
||||
@@ -183,8 +186,9 @@ def single_thread(request, course_id, discussion_id, thread_id):
|
||||
|
||||
if request.is_ajax():
|
||||
|
||||
user_info = cc.User.from_django_user(request.user).to_dict()
|
||||
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}
|
||||
html = render_to_string('discussion/_ajax_single_thread.html', context)
|
||||
|
||||
|
||||
@@ -160,23 +160,32 @@ class QueryCountDebugMiddleware(object):
|
||||
logging.info('%s queries run, total %s seconds' % (len(connection.queries), total_time))
|
||||
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 {
|
||||
'editable': check_permissions_by_view(user, course_id, content, "update_thread" if content['type'] == 'thread' else "update_comment"),
|
||||
'can_reply': check_permissions_by_view(user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_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"),
|
||||
'voted': voted,
|
||||
'subscribed': content['id'] in user_info['subscribed_thread_ids'],
|
||||
'ability': {
|
||||
'editable': check_permissions_by_view(user, course_id, content, "update_thread" if content['type'] == 'thread' else "update_comment"),
|
||||
'can_reply': check_permissions_by_view(user, course_id, content, "create_comment" if content['type'] == 'thread' else "create_sub_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 = {}
|
||||
def _annotate(content):
|
||||
infos[str(content['id'])] = get_annotated_content_info(course_id, content, user)
|
||||
def annotate(content):
|
||||
infos[str(content['id'])] = get_annotated_content_info(course_id, content, user, user_info)
|
||||
for child in content.get('children', []):
|
||||
_annotate(child)
|
||||
_annotate(thread)
|
||||
annotate(child)
|
||||
annotate(thread)
|
||||
return infos
|
||||
|
||||
def render_mustache(template_name, dictionary, *args, **kwargs):
|
||||
|
||||
@@ -9,60 +9,107 @@ class @Content extends Backbone.Model
|
||||
can_delete: '.admin-delete'
|
||||
can_openclose: '.admin-openclose'
|
||||
|
||||
isUpvoted: ->
|
||||
DiscussionUtil.isUpvoted @id
|
||||
urlMappers: {}
|
||||
|
||||
isDownvoted: ->
|
||||
DiscussionUtil.isDownvoted @id
|
||||
urlFor: (name) ->
|
||||
@urlMappers[name].apply(@)
|
||||
|
||||
can: (action) ->
|
||||
DiscussionUtil.getContentInfo @id, action
|
||||
|
||||
thread_id: ->
|
||||
if @get('type') == "comment" then @get('thread_id') else @id
|
||||
updateInfo: (info) ->
|
||||
@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: ->
|
||||
@set('comments', new Comments())
|
||||
if @get('children')
|
||||
@get('comments').reset @get('children'), {silent: false}
|
||||
DiscussionUtil.addContent @id, @
|
||||
@resetComments(@get('children'))
|
||||
|
||||
|
||||
class @ContentView extends Backbone.View
|
||||
|
||||
$: (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")
|
||||
|
||||
$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) ->
|
||||
$showComments = @$(".discussion-show-comments")
|
||||
@$el.children(".comments").hide()
|
||||
@showed = false
|
||||
$showComments.html $showComments.html().replace "Hide", "Show"
|
||||
@updateShowComments()
|
||||
|
||||
showSingleThread: (event) ->
|
||||
$showComments = @$(".discussion-show-comments")
|
||||
retrieved = not $showComments.hasClass("first-time") and @model.get("children") != undefined
|
||||
if retrieved
|
||||
if @retrieved()
|
||||
@$el.children(".comments").show()
|
||||
$showComments.html $showComments.html().replace "Show", "Hide"
|
||||
@showed = true
|
||||
@updateShowComments()
|
||||
else
|
||||
discussion_id = @model.discussion.id
|
||||
url = DiscussionUtil.urlFor('retrieve_single_thread', discussion_id, @model.id)
|
||||
DiscussionUtil.safeAjax
|
||||
$elem: $.merge @$(".thread-title"), @$(".discussion-show-comments")
|
||||
url: url
|
||||
type: "GET"
|
||||
dataType: 'json'
|
||||
success: (response, textStatus) =>
|
||||
DiscussionUtil.bulkExtendContentInfo response['annotated_content_info']
|
||||
@showed = true
|
||||
$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()
|
||||
$elem = $.merge @$(".thread-title"), @$showComments()
|
||||
url = @model.urlFor('retrieve_single_thread')
|
||||
DiscussionUtil.get $elem, url, (response, textStatus) =>
|
||||
@showed = true
|
||||
@updateShowComments()
|
||||
@$showComments().addClass("retrieved")
|
||||
@$el.children(".comments").replaceWith response.html
|
||||
@model.resetComments response.content.children
|
||||
@initCommentViews()
|
||||
DiscussionUtil.bulkUpdateContentInfo response.annotated_content_info
|
||||
|
||||
toggleSingleThread: (event) ->
|
||||
if @showed
|
||||
@@ -83,12 +130,11 @@ class @ContentView extends Backbone.View
|
||||
if $replyView.length
|
||||
$replyView.show()
|
||||
else
|
||||
thread_id = @model.thread_id()
|
||||
view =
|
||||
id: @model.id
|
||||
showWatchCheckbox: not DiscussionUtil.isSubscribed(thread_id, "thread")
|
||||
view = {}
|
||||
view.id = @model.id
|
||||
view.showWatchCheckbox = not @model.get('thread').get('subscribed')
|
||||
html = Mustache.render DiscussionUtil.getTemplate('_reply'), view
|
||||
@discussionContent().append html
|
||||
@$discussionContent().append html
|
||||
DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "reply-body"
|
||||
@$(".discussion-submit-post").click $.proxy(@submitReply, @)
|
||||
@$(".discussion-cancel-post").click $.proxy(@cancelReply, @)
|
||||
@@ -96,13 +142,7 @@ class @ContentView extends Backbone.View
|
||||
@$(".discussion-edit").hide()
|
||||
|
||||
submitReply: (event) ->
|
||||
if @model.get('type') == 'thread'
|
||||
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
|
||||
url = @model.urlFor('reply')
|
||||
|
||||
body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "reply-body"
|
||||
|
||||
@@ -122,19 +162,13 @@ class @ContentView extends Backbone.View
|
||||
success: (response, textStatus) =>
|
||||
DiscussionUtil.clearFormErrors @$(".discussion-errors")
|
||||
$comment = $(response.html)
|
||||
@$el.children(".comments").prepend($comment)
|
||||
@$el.children(".comments").prepend $comment
|
||||
DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "reply-body", ""
|
||||
#DiscussionUtil.setContentInfo response.content['id'], 'can_reply', true
|
||||
#DiscussionUtil.setContentInfo response.content['id'], 'editable', true
|
||||
comment = new Comment(response.content)
|
||||
DiscussionUtil.extendContentInfo comment.id, response['annotated_content_info']
|
||||
@model.get('children').push(response.content)
|
||||
@model.get('comments').add(comment)
|
||||
comment = @model.addComment response.content
|
||||
comment.updateInfo response.annotated_content_info
|
||||
commentView = new CommentView el: $comment[0], model: comment
|
||||
@$(".discussion-reply-new").hide()
|
||||
@$(".discussion-reply").show()
|
||||
@$(".discussion-edit").show()
|
||||
@discussionContent().attr("status", "normal")
|
||||
@cancelReply()
|
||||
|
||||
cancelReply: ->
|
||||
$replyView = @$(".discussion-reply-new")
|
||||
if $replyView.length
|
||||
@@ -143,77 +177,42 @@ class @ContentView extends Backbone.View
|
||||
@$(".discussion-edit").show()
|
||||
|
||||
unvote: (event) ->
|
||||
url = DiscussionUtil.urlFor("undo_vote_for_#{@model.get('type')}", @model.id)
|
||||
DiscussionUtil.safeAjax
|
||||
$elem: @$(".discussion-vote")
|
||||
url: url
|
||||
type: "POST"
|
||||
dataType: "json"
|
||||
success: (response, textStatus) =>
|
||||
if textStatus == "success"
|
||||
@$(".discussion-vote").removeClass("voted")
|
||||
@$(".discussion-votes-point").html response.votes.point
|
||||
url = @model.urlFor('unvote')
|
||||
$elem = @$(".discussion-vote")
|
||||
DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
|
||||
@model.set('voted', '')
|
||||
@model.set('votes_point', response.votes.point)
|
||||
|
||||
vote: (event) ->
|
||||
vote: (event, value) ->
|
||||
url = @model.urlFor("#{value}vote")
|
||||
$elem = @$(".discussion-vote")
|
||||
DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
|
||||
@model.set('voted', value)
|
||||
@model.set('votes_point', response.votes.point)
|
||||
|
||||
toggleVote: (event) ->
|
||||
$elem = $(event.target)
|
||||
if $elem.hasClass("voted")
|
||||
value = $elem.attr("value")
|
||||
if @model.get("voted") == value
|
||||
@unvote(event)
|
||||
else
|
||||
value = $elem.attr("value")
|
||||
url = Discussion.urlFor("#{value}vote_#{@model.get('type')}", @model.id)
|
||||
DiscussionUtil.safeAjax
|
||||
$elem: @$(".discussion-vote")
|
||||
url: url
|
||||
type: "POST"
|
||||
dataType: "json"
|
||||
success: (response, textStatus) =>
|
||||
if textStatus == "success"
|
||||
@$(".discussion-vote").removeClass("voted")
|
||||
@$(".discussion-vote-#{value}").addClass("voted")
|
||||
@$(".discussion-votes-point").html response.votes.point
|
||||
@vote(event, value)
|
||||
|
||||
endorse: (event) ->
|
||||
url = DiscussionUtil.urlFor('endorse_comment', @model.id)
|
||||
endorsed = not @$el.hasClass("endorsed")
|
||||
Discussion.safeAjax
|
||||
$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")
|
||||
toggleEndorse: (event) ->
|
||||
$elem = $(event.target)
|
||||
url = @model.urlFor('endorse')
|
||||
endorsed = @model.get('endorsed')
|
||||
data = { endorsed: not endorsed }
|
||||
DiscussionUtil.post $elem, url, data, (response, textStatus) =>
|
||||
@model.set('endorsed', not 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
|
||||
toggleClosed: (event) ->
|
||||
$elem = $(event.target)
|
||||
url = @model.urlFor('close')
|
||||
closed = @model.get('closed')
|
||||
data = { closed: not closed }
|
||||
DiscussionUtil.post $elem, url, data, (response, textStatus) =>
|
||||
@model.set('closed', not closed)
|
||||
|
||||
edit: ->
|
||||
$local(".discussion-content-wrapper").hide()
|
||||
@@ -227,7 +226,7 @@ class @ContentView extends Backbone.View
|
||||
body: $local(".thread-raw-body").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"
|
||||
$local(".thread-tags-edit").tagsInput Discussion.tagsInputOptions()
|
||||
$local(".discussion-submit-update").unbind("click").click -> handleSubmitEditThread(this)
|
||||
@@ -247,7 +246,7 @@ class @ContentView extends Backbone.View
|
||||
error: Discussion.formErrorHandler($local(".discussion-update-errors"))
|
||||
success: (response, textStatus) ->
|
||||
Discussion.clearFormErrors($local(".discussion-update-errors"))
|
||||
@discussionContent().replaceWith(response.html)
|
||||
@$discussionContent().replaceWith(response.html)
|
||||
Discussion.extendContentInfo response.content['id'], response['annotated_content_info']
|
||||
Discussion.initializeContent($content)
|
||||
Discussion.bindContentEvents($content)
|
||||
@@ -274,15 +273,15 @@ class @ContentView extends Backbone.View
|
||||
console.log e
|
||||
|
||||
events:
|
||||
"click .thread-title": "showSingleThread"
|
||||
"click .discussion-show-comments": "showSingleThread"
|
||||
"click .thread-title": "toggleSingleThread"
|
||||
"click .discussion-show-comments": "toggleSingleThread"
|
||||
"click .discussion-reply-thread": "reply"
|
||||
"click .discussion-reply-comment": "reply"
|
||||
"click .discussion-cancel-reply": "cancelReply"
|
||||
"click .discussion-vote-up": "vote"
|
||||
"click .discussion-vote-down": "vote"
|
||||
"click .admin-endorse": "endorse"
|
||||
"click .admin-openclose": "close"
|
||||
"click .discussion-vote-up": "toggleVote"
|
||||
"click .discussion-vote-down": "toggleVote"
|
||||
"click .admin-endorse": "toggleEndorse"
|
||||
"click .admin-openclose": "toggleClosed"
|
||||
"click .admin-edit": "edit"
|
||||
"click .admin-delete": "delete"
|
||||
|
||||
@@ -290,57 +289,65 @@ class @ContentView extends Backbone.View
|
||||
@$local = @$el.children(".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: ->
|
||||
$contentBody = @$(".content-body")
|
||||
$contentBody.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight $contentBody.html()
|
||||
MathJax.Hub.Queue ["Typeset", MathJax.Hub, $contentBody.attr("id")]
|
||||
|
||||
initActions: ->
|
||||
for action, elemSelector of @model.actions
|
||||
if not @model.can action
|
||||
@$(elemSelector).remove()
|
||||
|
||||
initTimeago: ->
|
||||
@$("span.timeago").timeago()
|
||||
|
||||
initPermalink: ->
|
||||
@$(".discussion-permanent-link").attr "href", @model.permalink()
|
||||
|
||||
if @model.get('type') == 'thread'
|
||||
discussion_id = @model.get('commentable_id')
|
||||
permalink = Discussion.urlFor("permanent_link_thread", discussion_id, @model.id)
|
||||
else
|
||||
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)
|
||||
renderPartial: ->
|
||||
for attr, value of @model.changedAttributes()
|
||||
if @partial[attr]
|
||||
@partial[attr].apply(@, [value])
|
||||
|
||||
@$(".discussion-permanent-link").attr "href", permalink
|
||||
initBindings: ->
|
||||
@model.view = @
|
||||
@model.bind('change', @renderPartial, @)
|
||||
|
||||
initialize: ->
|
||||
@model.view = @
|
||||
@initBindings()
|
||||
@initLocal()
|
||||
@initVote()
|
||||
@initTimeago()
|
||||
@initBody()
|
||||
@initPermalink()
|
||||
@initActions()
|
||||
@initCommentViews()
|
||||
|
||||
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 @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
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
class @Discussion extends Backbone.Collection
|
||||
model: Thread
|
||||
initialize: ->
|
||||
|
||||
DiscussionUtil.addDiscussion @id, @
|
||||
|
||||
@bind "add", (item) =>
|
||||
console.log item
|
||||
item.discussion = @
|
||||
|
||||
find: (id) ->
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
$ ->
|
||||
|
||||
window.$$contents = {}
|
||||
window.$$discussions = {}
|
||||
|
||||
$(".discussion-module").each (index, elem) ->
|
||||
view = new DiscussionModuleView(el: elem)
|
||||
|
||||
@@ -8,3 +11,5 @@ $ ->
|
||||
discussion = new Discussion()
|
||||
discussion.reset(discussionData, {silent: false})
|
||||
view = new DiscussionView(el: elem, model: discussion)
|
||||
|
||||
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
|
||||
|
||||
@@ -12,26 +12,17 @@ class @DiscussionUtil
|
||||
id = $(id).attr("_id")
|
||||
return $$discussion_data[id]
|
||||
|
||||
@getContentInfo: (id, attr) ->
|
||||
if not window.$$annotated_content_info?
|
||||
window.$$annotated_content_info = {}
|
||||
(window.$$annotated_content_info[id] || {})[attr]
|
||||
@addContent: (id, content) -> window.$$contents[id] = content
|
||||
|
||||
@setContentInfo: (id, attr, value) ->
|
||||
if not window.$$annotated_content_info?
|
||||
window.$$annotated_content_info = {}
|
||||
window.$$annotated_content_info[id] ||= {}
|
||||
window.$$annotated_content_info[id][attr] = value
|
||||
@getContent: (id) -> window.$$contents[id]
|
||||
|
||||
@extendContentInfo: (id, newInfo) ->
|
||||
if not window.$$annotated_content_info?
|
||||
window.$$annotated_content_info = {}
|
||||
window.$$annotated_content_info[id] = newInfo
|
||||
@addDiscussion: (id, discussion) -> window.$$discussions[id] = discussion
|
||||
|
||||
@bulkExtendContentInfo: (newInfos) ->
|
||||
if not window.$$annotated_content_info?
|
||||
window.$$annotated_content_info = {}
|
||||
window.$$annotated_content_info = $.extend window.$$annotated_content_info, newInfos
|
||||
@getDiscussion: (id) -> window.$$discussions[id]
|
||||
|
||||
@bulkUpdateContentInfo: (infos) ->
|
||||
for id, info of infos
|
||||
@getContent(id).updateInfo(info)
|
||||
|
||||
@generateDiscussionLink: (cls, txt, handler) ->
|
||||
$("<a>").addClass("discussion-link")
|
||||
@@ -79,9 +70,22 @@ class @DiscussionUtil
|
||||
$.ajax(params).always ->
|
||||
$elem.removeAttr("disabled")
|
||||
|
||||
@handleAnchorAndReload: (response) ->
|
||||
#window.location = window.location.pathname + "#" + response['id']
|
||||
window.location.reload()
|
||||
@get: ($elem, url, success) ->
|
||||
@safeAjax
|
||||
$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) ->
|
||||
for eventSelector, handler of eventsHandler
|
||||
@@ -98,22 +102,6 @@ class @DiscussionUtil
|
||||
defaultText: "Tag your post: press enter after each tag"
|
||||
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) ->
|
||||
(xhr, textStatus, error) ->
|
||||
response = JSON.parse(xhr.responseText)
|
||||
|
||||
@@ -85,6 +85,7 @@ initializeFollowThread = (thread) ->
|
||||
Discussion.extendContentInfo response.content['id'], response['annotated_content_info']
|
||||
Discussion.initializeContent($comment)
|
||||
Discussion.bindContentEvents($comment)
|
||||
@cancelReply()
|
||||
$local(".discussion-reply-new").hide()
|
||||
$local(".discussion-reply").show()
|
||||
$local(".discussion-edit").show()
|
||||
|
||||
@@ -5,11 +5,9 @@
|
||||
</%def>
|
||||
|
||||
<%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)}
|
||||
% if content.get('children') is not None:
|
||||
${render_comments(content['children'])}
|
||||
% endif
|
||||
${render_comments(content.get('children', []))}
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<%! from django.template.defaultfilters import escapejs %>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $$user_info = JSON.parse("${user_info | escapejs}");
|
||||
var $$course_id = "${course_id | escapejs}";
|
||||
if (typeof $$annotated_content_info === undefined) {
|
||||
var $$annotated_content_info = {};
|
||||
|
||||
Reference in New Issue
Block a user