Commit 07f818da by Rocky Duan

got reply working under backbone framework

parent 9dedd532
from django.core.urlresolvers import reverse
from django.template.defaultfilters import escapejs
from django.conf import settings
from mitxmako.shortcuts import render_to_string
from mustache_helpers import mustache_helpers
......@@ -24,11 +23,11 @@ def show_if(text, condition):
# TODO there should be a better way to handle this
def include_mustache_templates():
mustache_dir = settings.PROJECT_ROOT / 'templates' / 'discussion'
mustache_dir = settings.PROJECT_ROOT / 'templates' / 'discussion' / 'mustache'
valid_file_name = lambda file_name: file_name.endswith('.mustache')
read_file = lambda file_name: (file_name, open(mustache_dir / file_name, "r").read())
strip_file_name = lambda x: (x[0].rpartition('.')[0], x[1])
wrap_in_tag = lambda x: "<script type='text/template' id='{0}'>{1}</script>".format(x[0], escapejs(x[1]))
wrap_in_tag = lambda x: "<script type='text/template' id='{0}'>{1}</script>".format(x[0], x[1])
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)))
......@@ -48,4 +47,4 @@ def render_content(content, additional_context={}):
context = merge_dict(context, additional_context)
partial_mustache_helpers = {k: partial(v, content) for k, v in mustache_helpers.items()}
context = merge_dict(context, partial_mustache_helpers)
return render_mustache('discussion/_content.mustache', context)
return render_mustache('discussion/mustache/_content.mustache', context)
......@@ -4,7 +4,6 @@ import json
class AjaxExceptionMiddleware(object):
def process_exception(self, request, exception):
import pdb; pdb.set_trace()
if isinstance(exception, CommentClientError) and request.is_ajax():
return JsonError(json.loads(exception.message))
return None
......@@ -18,6 +18,9 @@ class @Content extends Backbone.Model
can: (action) ->
DiscussionUtil.getContentInfo @id, action
thread_id: ->
if @get('type') == "comment" then @get('thread_id') else @id
initialize: ->
@set('comments', new Comments())
if @get('children')
......@@ -28,99 +31,110 @@ class @ContentView extends Backbone.View
$: (selector) ->
@$local.find(selector)
showSingleThread: (event) ->
if @showed
@$el.children(".comments").hide()
@showed = false
$showComments = @$(".discussion-show-comments")
prevHtml = $showComments.html()
$showComments.html prevHtml.replace "Hide", "Show"
else
if @retrieved
@$el.children(".comments").show()
@showed = true
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']
@retrieved = true
@showed = true
@$el.append(response['html'])
@model.get('comments').reset response.content.children, {silent: false}
@initCommentViews()
return
$threadTitle = @$(".thread-title")
$showComments = @$(".discussion-show-comments")
if not $showComments.hasClass("first-time") and (not $showComments.length or not $threadTitle.length)
return
discussionContent: ->
@_discussionContent ||= @$el.children(".discussion-content")
rebindHideEvents = ->
$threadTitle.unbind('click').click @hideSingleThread
$showComments.unbind('click').click @hideSingleThread
$showComments.removeClass("discussion-show-comments")
.addClass("discussion-hide-comments")
prevHtml = $showComments.html()
$showComments.html prevHtml.replace "Show", "Hide"
hideSingleThread: (event) ->
$showComments = @$(".discussion-show-comments")
@$el.children(".comments").hide()
@showed = false
$showComments.html $showComments.html().replace "Hide", "Show"
if not $showComments.hasClass("first-time") and @$el.children(".comments").length
showSingleThread: (event) ->
$showComments = @$(".discussion-show-comments")
retrieved = not $showComments.hasClass("first-time") and @model.get("children") != undefined
if retrieved
@$el.children(".comments").show()
rebindHideEvents()
$showComments.html $showComments.html().replace "Show", "Hide"
@showed = true
else
discussion_id = @model.discussion.id
url = DiscussionUtil.urlFor('retrieve_single_thread', discussion_id, @model.id)
DiscussionUtil.safeAjax
$elem: $.merge($threadTitle, $showComments)
$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()
$showComments.removeClass("first-time")
rebindHideEvents()
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
hideSingleThread: ->
$threadTitle = @$(".thread-title")
$hideComments = @$(".discussion-hide-comments")
$hideComments.removeClass("discussion-hide-comments")
.addClass("discussion-show-comments")
@$el.children(".comments").hide()
$threadTitle.unbind('click').click @showSingleThread
$hideComments.unbind('click').click @showSingleThread
prevHtml = $hideComments.html()
$hideComments.html prevHtml.replace "Hide", "Show"
reply: ->
if @model.get('type') == 'thread'
@showSingleThread()
$replyView = @$(".discussion-reply-new")
if $replyView.length
$replyView.show()
else
thread_id = if @model.get('type') == "comment" then @model.get('thread_id') else @model.id
thread_id = @model.thread_id()
view =
id: @model.id
showWatchCheckbox: not DiscussionUtil.isSubscribed(thread_id, "thread")
@$discussionContent.append Mustache.render DiscussionUtil.replyTemplate, view
DiscussionUtil.makeWmdEditor @$el, @$local, "reply-body"
@$(".discussion-submit-post").click @submitReply
@$(".discussion-cancel-post").click @cancelReply
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) ->
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
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
autowatch: 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", ""
#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)
commentView = new CommentView el: $comment[0], model: comment
@$(".discussion-reply-new").hide()
@$(".discussion-reply").show()
@$(".discussion-edit").show()
@discussionContent().attr("status", "normal")
cancelReply: ->
$replyView = @$(".discussion-reply-new")
if $replyView.length
......@@ -213,7 +227,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)
......@@ -233,7 +247,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)
......@@ -262,7 +276,6 @@ class @ContentView extends Backbone.View
events:
"click .thread-title": "showSingleThread"
"click .discussion-show-comments": "showSingleThread"
"click .discussion-hide-comments": "hideSingleThread"
"click .discussion-reply-thread": "reply"
"click .discussion-reply-comment": "reply"
"click .discussion-cancel-reply": "cancelReply"
......
if not @Discussion?
@Discussion = {}
Discussion = @Discussion
@Discussion = $.extend @Discussion,
newPostTemplate: """
<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-body reply-body"></div>
<input class="new-post-tags" placeholder="Tags" />
<div class="post-options">
<input type="checkbox" class="discussion-post-anonymously" id="discussion-post-anonymously-${discussion_id}">
<label for="discussion-post-anonymously-${discussion_id}">post anonymously</label>
<input type="checkbox" class="discussion-auto-watch" id="discussion-autowatch-${discussion_id}" checked="">
<label for="discussion-auto-watch-${discussion_id}">follow this thread</label>
</div>
<div class="new-post-control post-control">
<a class="discussion-cancel-post" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-post control-button" href="javascript:void(0)">Submit</a>
</div>
</form>
"""
replyTemplate: """
<form class="discussion-reply-new">
<ul class="discussion-errors"></ul>
<div class="reply-body"></div>
<input type="checkbox" class="discussion-post-anonymously" id="discussion-post-anonymously-{{id}}" />
<label for="discussion-post-anonymously-{{id}}">post anonymously</label>
{{#showWatchCheckbox}}
<input type="checkbox" class="discussion-auto-watch" id="discussion-autowatch-{{id}}" checked />
<label for="discussion-auto-watch-{{id}}">follow this thread</label>
{{/showWatchCheckbox}}
<br />
<div class = "reply-post-control">
<a class="discussion-cancel-post" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-post control-button" href="javascript:void(0)">Submit</a>
</div>
</form>
"""
editThreadTemplate: """
<form class="discussion-content-edit discussion-thread-edit" _id="{{id}}">
<ul class="discussion-errors discussion-update-errors"></ul>
<input type="text" class="thread-title-edit title-input" placeholder="Title" value="{{title}}"/>
<div class="thread-body-edit body-input">{{body}}</div>
<input class="thread-tags-edit" placeholder="Tags" value="{{tags}}" />
<div class = "edit-post-control">
<a class="discussion-cancel-update" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-update control-button" href="javascript:void(0)">Update</a>
</div>
</form>
"""
editCommentTemplate: """
<form class="discussion-content-edit discussion-comment-edit" _id="{{id}}">
<ul class="discussion-errors discussion-update-errors"></ul>
<div class="comment-body-edit body-input">{{body}}</div>
<div class = "edit-post-control">
<a class="discussion-cancel-update" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-update control-button" href="javascript:void(0)">Update</a>
</div>
</form>
"""
......@@ -143,7 +143,9 @@ class @DiscussionUtil
id = $content.attr("_id")
appended_id = "-#{cls_identifier}-#{id}"
imageUploadUrl = @urlFor('upload')
editor = Markdown.makeWmdEditor elem, appended_id, imageUploadUrl, @postMathJaxProcessor
_processor = (_this) ->
(text) -> _this.postMathJaxProcessor(text)
editor = Markdown.makeWmdEditor elem, appended_id, imageUploadUrl, _processor(@)
@wmdEditors["#{cls_identifier}-#{id}"] = editor
editor
......
<form class="discussion-content-edit discussion-comment-edit" _id="{{id}}">
<ul class="discussion-errors discussion-update-errors"></ul>
<div class="comment-body-edit body-input">{{body}}</div>
<div class = "edit-post-control">
<a class="discussion-cancel-update" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-update control-button" href="javascript:void(0)">Update</a>
</div>
</form>
<form class="discussion-content-edit discussion-thread-edit" _id="{{id}}">
<ul class="discussion-errors discussion-update-errors"></ul>
<input type="text" class="thread-title-edit title-input" placeholder="Title" value="{{title}}"/>
<div class="thread-body-edit body-input">{{body}}</div>
<input class="thread-tags-edit" placeholder="Tags" value="{{tags}}" />
<div class = "edit-post-control">
<a class="discussion-cancel-update" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-update control-button" href="javascript:void(0)">Update</a>
</div>
</form>
<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-body reply-body"></div>
<input class="new-post-tags" placeholder="Tags" />
<div class="post-options">
<input type="checkbox" class="discussion-post-anonymously" id="discussion-post-anonymously-${discussion_id}">
<label for="discussion-post-anonymously-${discussion_id}">post anonymously</label>
<input type="checkbox" class="discussion-auto-watch" id="discussion-autowatch-${discussion_id}" checked="">
<label for="discussion-auto-watch-${discussion_id}">follow this thread</label>
</div>
<div class="new-post-control post-control">
<a class="discussion-cancel-post" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-post control-button" href="javascript:void(0)">Submit</a>
</div>
</form>
<form class="discussion-reply-new">
<ul class="discussion-errors"></ul>
<div class="reply-body"></div>
<input type="checkbox" class="discussion-post-anonymously" id="discussion-post-anonymously-{{id}}" />
<label for="discussion-post-anonymously-{{id}}">post anonymously</label>
{{#showWatchCheckbox}}
<input type="checkbox" class="discussion-auto-watch" id="discussion-autowatch-{{id}}" checked />
<label for="discussion-auto-watch-{{id}}">follow this thread</label>
{{/showWatchCheckbox}}
<br />
<div class="reply-post-control">
<a class="discussion-cancel-post" href="javascript:void(0)">Cancel</a>
<a class="discussion-submit-post control-button" href="javascript:void(0)">Submit</a>
</div>
</form>
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