Commit 26536902 by David Ormsbee

Merge pull request #520 from MITx/feature/rocky/discussion

add user profile and fixed edit
parents 22cbc1bd 6de05997
......@@ -21,7 +21,6 @@ from django.contrib.auth.models import User
from mitxmako.shortcuts import render_to_response, render_to_string
from courseware.courses import get_course_with_access
from django_comment_client.utils import JsonResponse, JsonError, extract
from django_comment_client.permissions import check_permissions_by_view
......@@ -282,7 +281,7 @@ def update_moderator_status(request, course_id, user_id):
'course_id': course_id,
'user': request.user,
'django_user': user,
'discussion_user': discussion_user.to_dict(),
'profiled_user': discussion_user.to_dict(),
}
return JsonResponse({
'html': render_to_string('discussion/ajax_user_profile.html', context)
......@@ -298,10 +297,13 @@ def search_similar_threads(request, course_id, commentable_id):
'text': text,
'commentable_id': commentable_id,
}
result = cc.search_similar_threads(course_id, recursive=False, query_params=query_params)
return JsonResponse(result)
threads = cc.search_similar_threads(course_id, recursive=False, query_params=query_params)
else:
return JsonResponse([])
theads = []
context = { 'threads': map(utils.extend_content, threads) }
return JsonResponse({
'html': render_to_string('discussion/_similar_posts.html', context)
})
@require_GET
def tags_autocomplete(request, course_id):
......@@ -334,8 +336,8 @@ def upload(request, course_id):#ajax upload file to a question or answer
# check file type
f = request.FILES['file-upload']
file_extension = os.path.splitext(f.name)[1].lower()
if not file_extension in settings.DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES:
file_types = "', '".join(settings.DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES)
if not file_extension in cc_settings.ALLOWED_UPLOAD_FILE_TYPES:
file_types = "', '".join(cc_settings.ALLOWED_UPLOAD_FILE_TYPES)
msg = _("allowed file types are '%(file_types)s'") % \
{'file_types': file_types}
raise exceptions.PermissionDenied(msg)
......@@ -354,15 +356,16 @@ def upload(request, course_id):#ajax upload file to a question or answer
# check file size
# byte
size = file_storage.size(new_file_name)
if size > settings.ASKBOT_MAX_UPLOAD_FILE_SIZE:
if size > cc_settings.MAX_UPLOAD_FILE_SIZE:
file_storage.delete(new_file_name)
msg = _("maximum upload file size is %(file_size)sK") % \
{'file_size': settings.ASKBOT_MAX_UPLOAD_FILE_SIZE}
{'file_size': cc_settings.MAX_UPLOAD_FILE_SIZE}
raise exceptions.PermissionDenied(msg)
except exceptions.PermissionDenied, e:
error = unicode(e)
except Exception, e:
print e
logging.critical(unicode(e))
error = _('Error uploading file. Please contact the site administrator. Thank you.')
......
......@@ -83,7 +83,7 @@ def render_discussion(request, course_id, threads, *args, **kwargs):
'base_url': base_url,
'query_params': strip_blank(strip_none(extract(query_params, ['page', 'sort_key', 'sort_order', 'tags', 'text']))),
'annotated_content_info': json.dumps(annotated_content_info),
'discussion_data': json.dumps({ discussion_id: threads }),
'discussion_data': json.dumps({ (discussion_id or user_id): threads })
}
context = dict(context.items() + query_params.items())
return render_to_string(template, context)
......@@ -250,7 +250,10 @@ def user_profile(request, course_id, user_id):
content = render_user_discussion(request, course_id, threads, user_id=user_id, query_params=query_params)
if request.is_ajax():
return utils.HtmlResponse(content)
return utils.JsonResponse({
'html': content,
'discussionData': threads,
})
else:
context = {
'course': course,
......
......@@ -12,7 +12,7 @@ import urllib
import os
def pluralize(singular_term, count):
if int(count) >= 2:
if int(count) >= 2 or int(count) == 0:
return singular_term + 's'
return singular_term
......@@ -33,24 +33,10 @@ def include_mustache_templates():
file_contents = map(read_file, filter(valid_file_name, os.listdir(mustache_dir)))
return '\n'.join(map(wrap_in_tag, map(strip_file_name, file_contents)))
def permalink(content):
if content['type'] == 'thread':
return reverse('django_comment_client.forum.views.single_thread',
args=[content['course_id'], content['commentable_id'], content['id']])
else:
return reverse('django_comment_client.forum.views.single_thread',
args=[content['course_id'], content['commentable_id'], content['thread_id']]) + '#' + content['id']
def render_content(content, additional_context={}):
content_info = {
'displayed_title': content.get('highlighted_title') or content.get('title', ''),
'displayed_body': content.get('highlighted_body') or content.get('body', ''),
'raw_tags': ','.join(content.get('tags', [])),
'permalink': permalink(content),
}
context = {
'content': merge_dict(content, content_info),
'content': extend_content(content),
content['type']: True,
}
context = merge_dict(context, additional_context)
......
......@@ -7,7 +7,8 @@ import inspect
def pluralize(content, text):
num, word = text.split(' ')
if int(num or '0') >= 2:
num = int(num or '0')
if num >= 2 or num == 0:
return word + 's'
else:
return word
......
from django.conf import settings
MAX_COMMENT_DEPTH = None
MAX_UPLOAD_FILE_SIZE = 1024 * 1024 #result in bytes
ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
if hasattr(settings, 'DISCUSSION_SETTINGS'):
MAX_COMMENT_DEPTH = settings.DISCUSSION_SETTINGS.get('MAX_COMMENT_DEPTH')
MAX_UPLOAD_FILE_SIZE = settings.DISCUSSION_SETTINGS.get('MAX_UPLOAD_FILE_SIZE') or MAX_UPLOAD_FILE_SIZE
ALLOWED_UPLOAD_FILE_TYPES = settings.DISCUSSION_SETTINGS.get('ALLOWED_UPLOAD_FILE_TYPES') or ALLOWED_UPLOAD_FILE_TYPES
......@@ -197,3 +197,20 @@ def url_for_tags(course_id, tags):
def render_mustache(template_name, dictionary, *args, **kwargs):
template = middleware.lookup['main'].get_template(template_name).source
return pystache.render(template, dictionary)
def permalink(content):
if content['type'] == 'thread':
return reverse('django_comment_client.forum.views.single_thread',
args=[content['course_id'], content['commentable_id'], content['id']])
else:
return reverse('django_comment_client.forum.views.single_thread',
args=[content['course_id'], content['commentable_id'], content['thread_id']]) + '#' + content['id']
def extend_content(content):
content_info = {
'displayed_title': content.get('highlighted_title') or content.get('title', ''),
'displayed_body': content.get('highlighted_body') or content.get('body', ''),
'raw_tags': ','.join(content.get('tags', [])),
'permalink': permalink(content),
}
return merge_dict(content, content_info)
class @Content extends Backbone.Model
if Backbone?
class @Content extends Backbone.Model
template: -> DiscussionUtil.getTemplate('_content')
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
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)
@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"
thread.set('comments_count', comments_count - 1 - comment.getCommentsCount())
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"]
resetComments: (children) ->
@set 'children', []
@set 'comments', new Comments()
for comment in (children || [])
@addComment comment, { silent: true }
votes_point: (votes_point) ->
@$(".discussion-votes-point").html(votes_point)
comments_count: (comments_count) ->
@$(".comments-count").html(comments_count)
initialize: ->
DiscussionUtil.addContent @id, @
@resetComments(@get('children'))
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().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) ->
@$el.children(".comments").hide()
@showed = false
@updateShowComments()
showSingleThread: (event) ->
if @retrieved()
@$el.children(".comments").show()
@showed = true
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().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) ->
@$el.children(".comments").hide()
@showed = false
@updateShowComments()
else
$elem = $.merge @$(".thread-title"), @$showComments()
url = @model.urlFor('retrieve')
DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
showSingleThread: (event) ->
if @retrieved()
@$el.children(".comments").show()
@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)
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
@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.post $elem, url, {}, (response, textStatus) =>
@model.set('voted', '')
@model.set('votes_point', response.votes.point)
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)
value = $elem.attr("value")
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.post $elem, url, data, (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.post $elem, url, {}, (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.post $elem, url, data, (response, textStatus) =>
@model.set('closed', not closed)
edit: (event) ->
@$(".discussion-content-wrapper").hide()
$editView = @$(".discussion-content-edit")
if $editView.length
$editView.show()
else
view = {}
view.id = @model.id
else
$elem = $.merge @$(".thread-title"), @$showComments()
url = @model.urlFor('retrieve')
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
@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)
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
@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.post $elem, url, {}, (response, textStatus) =>
@model.set('voted', '')
@model.set('votes_point', response.votes.point)
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)
value = $elem.attr("value")
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.post $elem, url, data, (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.post $elem, url, {}, (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.post $elem, url, data, (response, textStatus) =>
@model.set('closed', not closed)
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 = @$(".thread-raw-title").html()
view.body = @$(".thread-raw-body").html()
view.tags = @$(".thread-raw-tags").html()
else
view.body = @$(".comment-raw-body").html()
@$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)
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)
@model.set response.content
@model.updateInfo response.annotated_content_info
cancelEdit: (event) ->
@$(".discussion-content-edit").hide()
@$(".discussion-content-wrapper").show()
delete: (event) ->
url = @model.urlFor('delete')
if @model.get('type') == 'thread'
view.title = @$(".thread-raw-title").html()
view.body = @$(".thread-raw-body").html()
view.tags = @$(".thread-raw-tags").html()
c = confirm "Are you sure to delete thread \"#{@model.get('title')}\"?"
else
view.body = @$(".comment-raw-body").html()
@$discussionContent().append Mustache.render DiscussionUtil.getTemplate("_edit_#{@model.get('type')}"), view
Discussion.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)
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)
@model.set response.content
@model.updateInfo response.annotated_content_info
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.post $elem, url, {}, (response, textStatus) =>
@$el.remove()
@model.get('thread').removeComment(@model)
c = confirm "Are you sure to delete this comment? "
if not c
return
$elem = $(event.target)
DiscussionUtil.post $elem, url, {}, (response, textStatus) =>
@$el.remove()
@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()
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()
initPermalink: ->
@$(".discussion-permanent-link").attr "href", @model.permalink()
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()
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()
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)
'update': -> DiscussionUtil.urlFor('update_comment', @id)
'delete': -> DiscussionUtil.urlFor('delete_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)
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)
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)
class @Discussion extends Backbone.Collection
model: Thread
initialize: ->
DiscussionUtil.addDiscussion @id, @
@bind "add", (item) =>
item.discussion = @
find: (id) ->
_.first @where(id: id)
addThread: (thread, options) ->
options ||= {}
model = new Thread thread
@add model
model
class @DiscussionView extends Backbone.View
$: (selector) ->
@$local.find(selector)
initLocal: ->
@$local = @$el.children(".local")
@$delegateElement = @$local
initialize: ->
@initLocal()
@model.id = @$el.attr("_id")
@model.view = @
@$el.children(".threads").children(".thread").each (index, elem) =>
threadView = new ThreadView el: elem, model: @model.find $(elem).attr("_id")
if @$el.hasClass("forum-discussion")
$(".discussion-sidebar").find(".sidebar-new-post-button")
.unbind('click').click $.proxy @newPost, @
else if @$el.hasClass("inline-discussion")
@newPost()
reload: ($elem, url) ->
if not url then return
DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
$parent = @$el.parent()
@$el.replaceWith(response.html)
$discussion = $parent.find("section.discussion")
@model.reset(response.discussionData, { silent: false })
view = new DiscussionView el: $discussion[0], model: @model
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
loadSimilarPost: (event) ->
$title = @$(".new-post-title")
$wrapper = @$(".new-post-similar-posts-wrapper")
$similarPosts = @$(".new-post-similar-posts")
prevText = $title.attr("prev-text")
text = $title.val()
if text == prevText
if @$(".similar-post").length
$wrapper.show()
else if $.trim(text).length
$elem = $(event.target)
url = DiscussionUtil.urlFor 'search_similar_threads', @model.id
data = { text: @$(".new-post-title").val() }
DiscussionUtil.get $elem, url, data, (response, textStatus) =>
$similarPosts.empty()
if $.type(response) == "array" and response.length
if Backbone?
class @Discussion extends Backbone.Collection
model: Thread
initialize: ->
DiscussionUtil.addDiscussion @id, @
@bind "add", (item) =>
item.discussion = @
find: (id) ->
_.first @where(id: id)
addThread: (thread, options) ->
options ||= {}
model = new Thread thread
@add model
model
class @DiscussionView extends Backbone.View
$: (selector) ->
@$local.find(selector)
initLocal: ->
@$local = @$el.children(".local")
@$delegateElement = @$local
initialize: ->
@initLocal()
@model.id = @$el.attr("_id")
@model.view = @
@$el.children(".threads").children(".thread").each (index, elem) =>
threadView = new ThreadView el: elem, model: @model.find $(elem).attr("_id")
if @$el.hasClass("forum-discussion")
$(".discussion-sidebar").find(".sidebar-new-post-button")
.unbind('click').click $.proxy @newPost, @
else if @$el.hasClass("inline-discussion")
@newPost()
reload: ($elem, url) ->
if not url then return
DiscussionUtil.get $elem, url, {}, (response, textStatus) =>
$parent = @$el.parent()
@$el.replaceWith(response.html)
$discussion = $parent.find("section.discussion")
@model.reset(response.discussionData, { silent: false })
view = new DiscussionView el: $discussion[0], model: @model
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
$("html, body").animate({ scrollTop: 0 }, 0)
loadSimilarPost: (event) ->
console.log "loading similar"
$title = @$(".new-post-title")
$wrapper = @$(".new-post-similar-posts-wrapper")
$similarPosts = @$(".new-post-similar-posts")
prevText = $title.attr("prev-text")
text = $title.val()
if text == prevText
if @$(".similar-post").length
$wrapper.show()
for thread in response
$similarPost = $("<a>").addClass("similar-post")
.html(thread["title"])
.attr("href", "javascript:void(0)") #TODO
.appendTo($similarPosts)
else
$wrapper.hide()
else
$wrapper.hide()
$title.attr("prev-text", text)
newPost: ->
if not @$(".wmd-panel").length
view = { discussion_id: @model.id }
@$el.children(".discussion-non-content").append Mustache.render DiscussionUtil.getTemplate("_new_post"), view
$newPostBody = @$(".new-post-body")
DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
$input = DiscussionUtil.getWmdInput @$el, $.proxy(@$, @), "new-post-body"
$input.attr("placeholder", "post a new topic...")
if @$el.hasClass("inline-discussion")
$input.bind 'focus', (e) =>
else if $.trim(text).length
$elem = $(event.target)
url = DiscussionUtil.urlFor 'search_similar_threads', @model.id
data = { text: @$(".new-post-title").val() }
DiscussionUtil.safeAjax
$elem: $elem
url: url
data: data
dataType: 'json'
success: (response, textStatus) =>
$wrapper.html(response.html)
if $wrapper.find(".similar-post").length
$wrapper.show()
$wrapper.find(".hide-similar-posts").click =>
$wrapper.hide()
else
$wrapper.hide()
$title.attr("prev-text", text)
newPost: ->
if not @$(".wmd-panel").length
view = { discussion_id: @model.id }
@$el.children(".discussion-non-content").append Mustache.render DiscussionUtil.getTemplate("_new_post"), view
$newPostBody = @$(".new-post-body")
DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body"
$input = DiscussionUtil.getWmdInput @$el, $.proxy(@$, @), "new-post-body"
$input.attr("placeholder", "post a new topic...")
if @$el.hasClass("inline-discussion")
$input.bind 'focus', (e) =>
@$(".new-post-form").removeClass('collapsed')
else if @$el.hasClass("forum-discussion")
@$(".new-post-form").removeClass('collapsed')
else if @$el.hasClass("forum-discussion")
@$(".new-post-form").removeClass('collapsed')
@$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
@$(".new-post-title").blur $.proxy(@loadSimilarPost, @)
@$(".hide-similar-posts").click =>
@$(".new-post-similar-posts-wrapper").hide()
@$(".discussion-submit-post").click $.proxy(@submitNewPost, @)
@$(".discussion-cancel-post").click $.proxy(@cancelNewPost, @)
@$(".new-post-form").show()
submitNewPost: (event) ->
title = @$(".new-post-title").val()
body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "new-post-body"
tags = @$(".new-post-tags").val()
anonymous = false || @$(".discussion-post-anonymously").is(":checked")
autowatch = false || @$(".discussion-auto-watch").is(":checked")
url = DiscussionUtil.urlFor('create_thread', @model.id)
DiscussionUtil.safeAjax
$elem: $(event.target)
url: url
type: "POST"
dataType: 'json'
data:
title: title
body: body
tags: tags
anonymous: anonymous
auto_subscribe: autowatch
error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
success: (response, textStatus) =>
DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
$thread = $(response.html)
@$el.children(".threads").prepend($thread)
@$(".new-post-title").val("")
DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "new-post-body", ""
@$(".new-post-tags").val("")
@$(".new-post-tags").importTags("")
thread = @model.addThread response.content
threadView = new ThreadView el: $thread[0], model: thread
thread.updateInfo response.annotated_content_info
@cancelNewPost()
@$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions()
@$(".new-post-title").blur $.proxy(@loadSimilarPost, @)
@$(".hide-similar-posts").click =>
@$(".new-post-similar-posts-wrapper").hide()
@$(".discussion-submit-post").click $.proxy(@submitNewPost, @)
@$(".discussion-cancel-post").click $.proxy(@cancelNewPost, @)
cancelNewPost: (event) ->
if @$el.hasClass("inline-discussion")
@$(".new-post-form").addClass("collapsed")
else if @$el.hasClass("forum-discussion")
@$(".new-post-form").hide()
search: (event) ->
event.preventDefault()
$elem = $(event.target)
url = URI($elem.attr("action")).addSearch({text: @$(".search-input").val()})
@reload($elem, url)
sort: ->
$elem = $(event.target)
url = $elem.attr("sort-url")
@reload($elem, url)
page: (event) ->
$elem = $(event.target)
url = $elem.attr("page-url")
@reload($elem, url)
events:
"submit .search-wrapper>.discussion-search-form": "search"
"click .discussion-search-link": "search"
"click .discussion-sort-link": "sort"
"click .discussion-page-link": "page"
@$(".new-post-form").show()
submitNewPost: (event) ->
title = @$(".new-post-title").val()
body = DiscussionUtil.getWmdContent @$el, $.proxy(@$, @), "new-post-body"
tags = @$(".new-post-tags").val()
anonymous = false || @$(".discussion-post-anonymously").is(":checked")
autowatch = false || @$(".discussion-auto-watch").is(":checked")
url = DiscussionUtil.urlFor('create_thread', @model.id)
DiscussionUtil.safeAjax
$elem: $(event.target)
url: url
type: "POST"
dataType: 'json'
data:
title: title
body: body
tags: tags
anonymous: anonymous
auto_subscribe: autowatch
error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors"))
success: (response, textStatus) =>
DiscussionUtil.clearFormErrors(@$(".new-post-form-errors"))
$thread = $(response.html)
@$el.children(".threads").prepend($thread)
@$(".new-post-similar-posts").empty()
@$(".new-post-similar-posts-wrapper").hide()
@$(".new-post-title").val("").attr("prev-text", "")
DiscussionUtil.setWmdContent @$el, $.proxy(@$, @), "new-post-body", ""
@$(".new-post-tags").val("")
@$(".new-post-tags").importTags("")
thread = @model.addThread response.content
threadView = new ThreadView el: $thread[0], model: thread
thread.updateInfo response.annotated_content_info
@cancelNewPost()
cancelNewPost: (event) ->
if @$el.hasClass("inline-discussion")
@$(".new-post-form").addClass("collapsed")
else if @$el.hasClass("forum-discussion")
@$(".new-post-form").hide()
search: (event) ->
event.preventDefault()
$elem = $(event.target)
url = URI($elem.attr("action")).addSearch({text: @$(".search-input").val()})
@reload($elem, url)
sort: ->
$elem = $(event.target)
url = $elem.attr("sort-url")
@reload($elem, url)
page: (event) ->
$elem = $(event.target)
url = $elem.attr("page-url")
@reload($elem, url)
events:
"submit .search-wrapper>.discussion-search-form": "search"
"click .discussion-search-link": "search"
"click .discussion-sort-link": "sort"
"click .discussion-page-link": "page"
class @DiscussionModuleView extends Backbone.View
events:
"click .discussion-show": "toggleDiscussion"
toggleDiscussion: (event) ->
if @showed
@$("section.discussion").hide()
$(event.target).html("Show Discussion")
@showed = false
else
if @retrieved
@$("section.discussion").show()
$(event.target).html("Hide Discussion")
@showed = true
if Backbone?
class @DiscussionModuleView extends Backbone.View
events:
"click .discussion-show": "toggleDiscussion"
toggleDiscussion: (event) ->
if @showed
@$("section.discussion").hide()
$(event.target).html("Show Discussion")
@showed = false
else
$elem = $(event.target)
discussion_id = $elem.attr("discussion_id")
url = DiscussionUtil.urlFor 'retrieve_discussion', discussion_id
Discussion.safeAjax
$elem: $elem
url: url
type: "GET"
dataType: 'json'
success: (response, textStatus) =>
@$el.append(response.html)
$discussion = @$el.find("section.discussion")
$(event.target).html("Hide Discussion")
discussion = new Discussion()
discussion.reset(response.discussionData, {silent: false})
view = new DiscussionView(el: $discussion[0], model: discussion)
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
@retrieved = true
@showed = true
if @retrieved
@$("section.discussion").show()
$(event.target).html("Hide Discussion")
@showed = true
else
$elem = $(event.target)
discussion_id = $elem.attr("discussion_id")
url = DiscussionUtil.urlFor 'retrieve_discussion', discussion_id
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "GET"
dataType: 'json'
success: (response, textStatus) =>
@$el.append(response.html)
$discussion = @$el.find("section.discussion")
$(event.target).html("Hide Discussion")
discussion = new Discussion()
discussion.reset(response.discussionData, {silent: false})
view = new DiscussionView(el: $discussion[0], model: discussion)
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
@retrieved = true
@showed = true
......@@ -12,4 +12,10 @@ $ ->
discussion.reset(discussionData, {silent: false})
view = new DiscussionView(el: elem, model: discussion)
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
if window.$$annotated_content_info?
DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info)
$userProfile = $(".discussion-sidebar>.user-profile")
if $userProfile.length
console.log "initialize user profile"
view = new DiscussionUserProfileView(el: $userProfile[0])
if not @Discussion?
@Discussion = {}
class @DiscussionUserProfileView extends Backbone.View
toggleModeratorStatus: (event) ->
confirmValue = confirm("Are you sure?")
if not confirmValue then return
$elem = $(event.target)
if $elem.hasClass("sidebar-promote-moderator-button")
isModerator = true
else if $elem.hasClass("sidebar-revoke-moderator-button")
isModerator = false
else
console.error "unrecognized moderator status"
return
url = DiscussionUtil.urlFor('update_moderator_status', $$profiled_user_id)
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
dataType: 'json'
data:
is_moderator: isModerator
error: (response, textStatus, e) ->
console.log e
success: (response, textStatus) =>
parent = @$el.parent()
@$el.replaceWith(response.html)
view = new DiscussionUserProfileView el: parent.children(".user-profile")
Discussion = @Discussion
@Discussion = $.extend @Discussion,
initializeUserProfile: ($userProfile) ->
$local = Discussion.generateLocal $userProfile
handleUpdateModeratorStatus = (elem, isModerator) ->
confirmValue = confirm("Are you sure?")
if not confirmValue then return
url = Discussion.urlFor('update_moderator_status', $$profiled_user_id)
Discussion.safeAjax
$elem: $(elem)
url: url
type: "POST"
dataType: 'json'
data:
is_moderator: isModerator
error: (response, textStatus, e) ->
console.log e
success: (response, textStatus) ->
parent = $userProfile.parent()
$userProfile.replaceWith(response.html)
Discussion.initializeUserProfile parent.children(".user-profile")
Discussion.bindLocalEvents $local,
"click .sidebar-revoke-moderator-button": (event) ->
handleUpdateModeratorStatus(this, false)
"click .sidebar-promote-moderator-button": (event) ->
handleUpdateModeratorStatus(this, true)
initializeUserActiveDiscussion: ($discussion) ->
events:
"click .sidebar-toggle-moderator-button": "toggleModeratorStatus"
......@@ -22,6 +22,7 @@
## <script type="text/javascript" src="${static.url('js/vendor/CodeMirror-2.25/mode/python/python.js')}"></script>
<%static:js group='courseware'/>
<%static:js group='discussion'/>
<%include file="../discussion/_js_body_dependencies.html" />
......
<%! import django_comment_client.helpers as helpers %>
<%def name="render_content(content)">
${helpers.render_content(content)}
<%def name="render_content(content, *args, **kwargs)">
${helpers.render_content(content, *args, **kwargs)}
</%def>
<%def name="render_content_with_comments(content)">
<%def name="render_content_with_comments(content, *args, **kwargs)">
<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_comments(content.get('children', []))}
${render_content(content, *args, **kwargs)}
${render_comments(content.get('children', []), *args, **kwargs)}
</div>
</%def>
<%def name="render_comments(comments)">
<%def name="render_comments(comments, *args, **kwargs)">
<div class="comments">
% for comment in comments:
${render_content_with_comments(comment)}
${render_content_with_comments(comment, *args, **kwargs)}
% endfor
</div>
</%def>
% if len(threads) > 0:
Similar Posts:
<a class="hide-similar-posts" href="javascript:void(0)">Hide</a>
<div class="new-post-similar-posts">
% for thread in threads:
<a class="similar-post" href="${thread['permalink']}">${thread['title']}</a>
% endfor
</div>
% endif
<%namespace name="renderer" file="_thread.html"/>
<%namespace name="renderer" file="_content_renderer.html"/>
<section class="discussion user-active-discussion">
<section class="discussion user-active-discussion" _id="${user_id}">
<div class="discussion-non-content discussion-local"></div>
<div class="discussion-non-content local"></div>
<div class="threads">
% for thread in threads:
${renderer.render_thread(course_id, thread, show_comments=True)}
${renderer.render_content_with_comments(thread, {'partial_comments': True})}
% endfor
</div>
......
<%! from django_comment_client.utils import pluralize %>
<%! from django_comment_client.helpers import pluralize %>
<%! from django_comment_client.permissions import has_permission, check_permissions_by_view %>
<%! from operator import attrgetter %>
......@@ -15,9 +15,9 @@
<div class="sidebar-comments-count"><span>${profiled_user['comments_count']}</span> ${pluralize('comment', profiled_user['comments_count'])}</div>
% if check_permissions_by_view(user, course.id, content=None, name='update_moderator_status'):
% if "Moderator" in role_names:
<a href="javascript:void(0)" class="sidebar-revoke-moderator-button">Revoke Moderator provileges</a>
<a href="javascript:void(0)" class="sidebar-toggle-moderator-button sidebar-revoke-moderator-button">Revoke Moderator provileges</a>
% else:
<a href="javascript:void(0)" class="sidebar-promote-moderator-button">Promote to Moderator</a>
<a href="javascript:void(0)" class="sidebar-toggle-moderator-button sidebar-promote-moderator-button">Promote to Moderator</a>
% endif
% endif
</div>
<%inherit file="../main.html" />
<%namespace name='static' file='../static_content.html'/>
<%block name="bodyclass">discussion</%block>
<%block name="title"><title>Discussion – MITx 6.002x</title></%block>
<%block name="title"><title>Discussion – ${course.number}</title></%block>
<%block name="headextra">
<%static:css group='course'/>
......
......@@ -37,7 +37,7 @@
anonymous
{{/content.anonymous}}
{{^content.anonymous}}
{{content.username}}
<a href="{{##url_for_user}}{{content.user_id}}{{/url_for_user}}">{{content.username}}</a>
{{/content.anonymous}}
</div>
<div class="show-comments-wrapper">
......
<form class="new-post-form collapsed" id="new-post-form" style="display: block; ">
<ul class="new-post-form-errors discussion-errors"></ul>
<input type="text" class="new-post-title title-input" placeholder="Title" />
<div class="new-post-similar-posts-wrapper" style="display: none">
Similar Posts:
<a class="hide-similar-posts" href="javascript:void(0)">Hide</a>
<div class="new-post-similar-posts"></div>
</div>
<div class="new-post-similar-posts-wrapper" style="display: none"></div>
<div class="new-post-body reply-body"></div>
<input class="new-post-tags" placeholder="Tags" />
<div class="post-options">
......
<%inherit file="../main.html" />
<%namespace name='static' file='../static_content.html'/>
<%block name="bodyclass">discussion</%block>
<%block name="title"><title>Discussion – MITx 6.002x</title></%block>
<%block name="title"><title>Discussion – ${course.number}</title></%block>
<%block name="headextra">
<%static:css group='course'/>
......
<%! from django.template.defaultfilters import escapejs %>
<%namespace name="renderer" file="_thread.html"/>
<%inherit file="../main.html" />
<%namespace name='static' file='../static_content.html'/>
<%block name="bodyclass">discussion</%block>
<%block name="title"><title>Discussion – MITx 6.002x</title></%block>
<%block name="title"><title>Discussion – ${course.number}</title></%block>
<%block name="headextra">
<%static:css group='course'/>
<%include file="_js_head_dependencies.html" />
</%block>
<%block name="js_extra">
<%include file="_js_dependencies.html" />
<%include file="_js_body_dependencies.html" />
<%static:js group='discussion'/>
</%block>
<%include file="/courseware/course_navigation.html" args="active_page='discussion'" />
<%include file="../courseware/course_navigation.html" args="active_page='discussion'" />
<section class="container">
<div class="course-wrapper">
......
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