Commit fde77b7a by Rocky Duan

fixed user link and back button

parent e3728f68
if Backbone?
class @Content extends Backbone.Model
template: -> DiscussionUtil.getTemplate('_content')
actions:
editable: '.admin-edit'
can_reply: '.discussion-reply'
can_endorse: '.admin-endorse'
can_delete: '.admin-delete'
can_openclose: '.admin-openclose'
urlMappers: {}
urlFor: (name) ->
@urlMappers[name].apply(@)
can: (action) ->
DiscussionUtil.getContentInfo @id, action
updateInfo: (info) ->
@set('ability', info.ability)
@set('voted', info.voted)
@set('subscribed', info.subscribed)
addComment: (comment, options) ->
options ||= {}
if not options.silent
thread = @get('thread')
comments_count = parseInt(thread.get('comments_count'))
thread.set('comments_count', comments_count + 1)
@get('children').push comment
model = new Comment $.extend {}, comment, { thread: @get('thread') }
@get('comments').add model
model
removeComment: (comment) ->
thread = @get('thread')
comments_count = parseInt(thread.get('comments_count'))
thread.set('comments_count', comments_count - 1 - comment.getCommentsCount())
resetComments: (children) ->
@set 'children', []
@set 'comments', new Comments()
for comment in (children || [])
@addComment comment, { silent: true }
initialize: ->
DiscussionUtil.addContent @id, @
@resetComments(@get('children'))
class @ContentView extends Backbone.View
$: (selector) ->
@$local.find(selector)
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)
comments_count: (comments_count) ->
@$(".comments-count").html(comments_count)
subscribed: (subscribed) ->
if subscribed
@$(".discussion-follow-thread").addClass("discussion-unfollow-thread").html("Unfollow")
else
@$(".discussion-follow-thread").removeClass("discussion-unfollow-thread").html("Follow")
ability: (ability) ->
for action, elemSelector of @model.actions
if not ability[action]
@$(elemSelector).parent().hide()
else
@$(elemSelector).parent().show()
$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) ->
@$el.children(".comments").hide()
@showed = false
@updateShowComments()
showSingleThread: (event) ->
if @retrieved()
@$el.children(".comments").show()
@showed = true
@updateShowComments()
else
$elem = $.merge @$(".thread-title"), @$showComments()
url = @model.urlFor('retrieve')
DiscussionUtil.safeAjax
$elem: $elem
$loading: @$(".discussion-show-comments")
type: "GET"
url: url
success: (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
@hideSingleThread(event)
else
@showSingleThread(event)
initCommentViews: ->
@$el.children(".comments").children(".comment").each (index, elem) =>
model = @model.get('comments').find $(elem).attr("_id")
if not model.view
commentView = new CommentView el: elem, model: model
reply: ->
if @model.get('type') == 'thread'
@showSingleThread()
$replyView = @$(".discussion-reply-new")
if $replyView.length
$replyView.show()
else
view = {}
view.id = @model.id
view.showWatchCheckbox = not @model.get('thread').get('subscribed')
html = Mustache.render DiscussionUtil.getTemplate('_reply'), view
@$discussionContent().append html
DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "reply-body"
@$(".discussion-submit-post").click $.proxy(@submitReply, @)
@$(".discussion-cancel-post").click $.proxy(@cancelReply, @)
@$(".discussion-reply").hide()
@$(".discussion-edit").hide()
submitReply: (event) ->
url = @model.urlFor('reply')
body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "reply-body"
anonymous = false || @$(".discussion-post-anonymously").is(":checked")
autowatch = false || @$(".discussion-auto-watch").is(":checked")
DiscussionUtil.safeAjax
$elem: $(event.target)
$loading: $(event.target) if event
url: url
type: "POST"
dataType: 'json'
data:
body: body
anonymous: anonymous
auto_subscribe: autowatch
error: DiscussionUtil.formErrorHandler @$(".discussion-errors")
success: (response, textStatus) =>
DiscussionUtil.clearFormErrors @$(".discussion-errors")
$comment = $(response.html)
@$el.children(".comments").prepend $comment
DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "reply-body", ""
comment = @model.addComment response.content
commentView = new CommentView el: $comment[0], model: comment
comment.updateInfo response.annotated_content_info
if autowatch
@model.get('thread').set('subscribed', true)
@cancelReply()
cancelReply: ->
$replyView = @$(".discussion-reply-new")
if $replyView.length
$replyView.hide()
@$(".discussion-reply").show()
@$(".discussion-edit").show()
unvote: (event) ->
url = @model.urlFor('unvote')
$elem = @$(".discussion-vote")
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
success: (response, textStatus) =>
@model.set('voted', '')
@model.set('votes_point', response.votes.point)
vote: (event, value) ->
url = @model.urlFor("#{value}vote")
$elem = @$(".discussion-vote")
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
success: (response, textStatus) =>
@model.set('voted', value)
@model.set('votes_point', response.votes.point)
toggleVote: (event) ->
console.log("HERE")
$elem = $(event.target)
value = $elem.attr("value")
$elem.toggleClass("is-cast")
return false
# if @model.get("voted") == value
# @unvote(event)
# else
# @vote(event, value)
toggleEndorse: (event) ->
$elem = $(event.target)
url = @model.urlFor('endorse')
endorsed = @model.get('endorsed')
data = { endorsed: not endorsed }
DiscussionUtil.safeAjax
$elem: $elem
url: url
data: data
type: "POST"
success: (response, textStatus) =>
@model.set('endorsed', not endorsed)
toggleFollow: (event) ->
$elem = $(event.target)
subscribed = @model.get('subscribed')
if subscribed
url = @model.urlFor('unfollow')
else
url = @model.urlFor('follow')
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
success: (response, textStatus) =>
@model.set('subscribed', not subscribed)
toggleClosed: (event) ->
$elem = $(event.target)
url = @model.urlFor('close')
closed = @model.get('closed')
data = { closed: not closed }
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
data: data
success: (response, textStatus) =>
@model.set('closed', not closed)
@model.set('ability', response.ability)
edit: (event) ->
@$(".discussion-content-wrapper").hide()
$editView = @$(".discussion-content-edit")
if $editView.length
$editView.show()
else
view = {}
view.id = @model.id
if @model.get('type') == 'thread'
view.title = @model.get('title')
view.body = @model.get('body')
view.tags = @model.get('tags')
else
view.body = @model.get('body')
@$discussionContent().append Mustache.render DiscussionUtil.getTemplate("_edit_#{@model.get('type')}"), view
DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "#{@model.get('type')}-body-edit"
@$(".thread-tags-edit").tagsInput DiscussionUtil.tagsInputOptions()
@$(".discussion-submit-update").unbind("click").click $.proxy(@submitEdit, @)
@$(".discussion-cancel-update").unbind("click").click $.proxy(@cancelEdit, @)
submitEdit: (event) ->
url = @model.urlFor('update')
data = {}
if @model.get('type') == 'thread'
data.title = @$(".thread-title-edit").val()
data.body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "thread-body-edit"
data.tags = @$(".thread-tags-edit").val()
else
data.body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "comment-body-edit"
DiscussionUtil.safeAjax
$elem: $(event.target)
$loading: $(event.target) if event
url: url
type: "POST"
dataType: 'json'
data: data
error: DiscussionUtil.formErrorHandler @$(".discussion-update-errors")
success: (response, textStatus) =>
DiscussionUtil.clearFormErrors @$(".discussion-update-errors")
@$discussionContent().replaceWith(response.html)
if @model.get('type') == 'thread'
@model = new Thread response.content
else
@model = new Comment $.extend {}, response.content, { thread: @model.get('thread') }
@reconstruct()
@model.updateInfo response.annotated_content_info, { forceUpdate: true }
cancelEdit: (event) ->
@$(".discussion-content-edit").hide()
@$(".discussion-content-wrapper").show()
delete: (event) ->
url = @model.urlFor('delete')
if @model.get('type') == 'thread'
c = confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
else
c = confirm "Are you sure to delete this comment? "
if not c
return
$elem = $(event.target)
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
success: (response, textStatus) =>
@$el.remove()
if @model.get('type') == 'comment'
@model.get('thread').removeComment(@model)
events:
"click .discussion-follow-thread": "toggleFollow"
"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": "toggleVote"
"click .discussion-vote-down": "toggleVote"
"click .admin-endorse": "toggleEndorse"
"click .admin-openclose": "toggleClosed"
"click .admin-edit": "edit"
"click .admin-delete": "delete"
initLocal: ->
@$local = @$el.children(".local")
@$delegateElement = @$local
initTitle: ->
$contentTitle = @$(".thread-title")
if $contentTitle.length
$contentTitle.html DiscussionUtil.unescapeHighlightTag DiscussionUtil.stripLatexHighlight $contentTitle.html()
initBody: ->
$contentBody = @$(".content-body")
$contentBody.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight $contentBody.html()
MathJax.Hub.Queue ["Typeset", MathJax.Hub, $contentBody.attr("id")]
initTimeago: ->
@$("span.timeago").timeago()
renderPartial: ->
for attr, value of @model.changedAttributes()
if @partial[attr]
@partial[attr].apply(@, [value])
initBindings: ->
@model.view = @
@model.bind('change', @renderPartial, @)
initialize: ->
@initBindings()
@initLocal()
@initTimeago()
@initTitle()
@initBody()
@initCommentViews()
reconstruct: ->
@initBindings()
@initLocal()
@initTimeago()
@initTitle()
@initBody()
@delegateEvents()
class @Thread extends @Content
urlMappers:
'retrieve' : -> 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)
'update' : -> DiscussionUtil.urlFor('update_thread', @id)
'delete' : -> DiscussionUtil.urlFor('delete_thread', @id)
'follow' : -> DiscussionUtil.urlFor('follow_thread', @id)
'unfollow' : -> DiscussionUtil.urlFor('unfollow_thread', @id)
initialize: ->
@set('thread', @)
super()
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)
'update': -> DiscussionUtil.urlFor('update_comment', @id)
'delete': -> DiscussionUtil.urlFor('delete_comment', @id)
getCommentsCount: ->
count = 0
@get('comments').each (comment) ->
count += comment.getCommentsCount() + 1
count
class @CommentView extends @ContentView
class @Comments extends Backbone.Collection
model: Comment
initialize: ->
@bind "add", (item) =>
item.collection = @
find: (id) ->
_.first @where(id: id)
......@@ -8,6 +8,7 @@ class User(models.Model):
accessible_fields = ['username', 'email', 'follower_ids', 'upvoted_ids', 'downvoted_ids',
'id', 'external_id', 'subscribed_user_ids', 'children', 'course_id',
'subscribed_thread_ids', 'subscribed_commentable_ids',
'default_sort_key',
'threads_count', 'comments_count',
]
......
......@@ -47,6 +47,7 @@ if Backbone?
initialize: ->
DiscussionUtil.addContent @id, @
@set 'user_url', DiscussionUtil.urlFor('user_profile', @get('user_id'))
@resetComments(@get('children'))
......
......@@ -64,13 +64,16 @@ class @DiscussionUtil
openclose_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/close"
permanent_link_thread : "/courses/#{$$course_id}/discussion/forum/#{param}/threads/#{param1}"
permanent_link_comment : "/courses/#{$$course_id}/discussion/forum/#{param}/threads/#{param1}##{param2}"
user_profile : "/courses/#{$$course_id}/discussion/forum/users/#{param}"
}[name]
@safeAjax: (params) ->
$elem = params.$elem
if $elem.attr("disabled")
if $elem and $elem.attr("disabled")
return
params["url"] = URI(params["url"]).addSearch ajax: 1
params["beforeSend"] = ->
if $elem
$elem.attr("disabled", "disabled")
if params["$loading"]
if params["loadingCallback"]?
......@@ -78,6 +81,7 @@ class @DiscussionUtil
else
params["$loading"].loading()
$.ajax(params).always ->
if $elem
$elem.removeAttr("disabled")
if params["$loading"]
if params["loadedCallback"]?
......
......@@ -29,7 +29,9 @@ class @DiscussionThreadView extends Backbone.View
MathJax.Hub.Queue ["Typeset", MathJax.Hub, element.attr("id")]
renderResponses: ->
$.ajax @model.id, success: (data, textStatus, xhr) =>
DiscussionUtil.safeAjax
url: @model.id
success: (data, textStatus, xhr) =>
@$(".loading").remove()
comments = new Comments(data['content']['children'])
comments.each @renderResponse
......
<%namespace name="renderer" file="_content_renderer.html"/>
<%! from django_comment_client.mustache_helpers import url_for_user %>
<article class="discussion-article" data-id="${discussion_id| h}">
<a href="#" class="dogear"></a>
......@@ -8,7 +9,7 @@
<h1>${thread['title']}</h1>
<p class="posted-details">
<span class="timeago" title="${thread['created_at'] | h}">sometime</span> by
<a href="${thread['user_id']}">${thread['username']}</a>
<a href="${url_for_user(thread, thread['user_id'])}">${thread['username']}</a>
</p>
</header>
<div class="post-body">
......
......@@ -34,7 +34,7 @@
<h1>${'<%= title %>'}</h1>
<p class="posted-details">
<span class="timeago" title="${'<%= created_at %>'}">sometime</span> by
<a href="${'<%= user_id %>'}">${'<%= username %>'}</a>
<a href="${'<%= user_url %>'}">${'<%= username %>'}</a>
</p>
</header>
<div class="post-body">
......@@ -58,7 +58,7 @@
<script type="text/template" id="thread-response-template">
<header>
<a href="#" class="vote-btn" data-tooltip="vote"><span class="plus-icon"></span><span class="votes-count-number">${"<%= votes['up_count'] %>"}</span></a>
<a href="#" class="posted-by">${"<%= username %>"}</a>
<a href="${'<%= user_url %>'}" class="posted-by">${"<%= username %>"}</a>
<p class="posted-details" title="${'<%= created_at %>'}">Sometime</p>
</header>
<div class="response-body">${"<%= body %>"}</div>
......@@ -72,7 +72,7 @@
</script>
<script type="text/template" id="response-comment-template">
<p>${'<%= body %>'}<span class="posted-details">posted <span class="timeago" title="${'<%= created_at %>'}">sometime</span> by <a href="#">${'<%= username %>'}</a></span></p>
<p>${'<%= body %>'}<span class="posted-details">posted <span class="timeago" title="${'<%= created_at %>'}">sometime</span> by <a href="${'<%= user_url %>'}">${'<%= username %>'}</a></span></p>
</script>
<script type="text/template" id="thread-list-item-template">
......
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