basic editing functionality
This commit is contained in:
@@ -19,24 +19,22 @@ from django_comment_client.utils import JsonResponse, JsonError
|
||||
|
||||
def thread_author_only(fn):
|
||||
def verified_fn(request, *args, **kwargs):
|
||||
thread_id = args.get('thread_id', False) or \
|
||||
kwargs.get('thread_id', False)
|
||||
thread_id = kwargs.get('thread_id', False)
|
||||
thread = comment_client.get_thread(thread_id)
|
||||
if request.user.id == thread['user_id']:
|
||||
if str(request.user.id) == str(thread['user_id']):
|
||||
return fn(request, *args, **kwargs)
|
||||
else:
|
||||
return JsonError(400, "unauthorized")
|
||||
return JsonError("unauthorized")
|
||||
return verified_fn
|
||||
|
||||
def comment_author_only(fn):
|
||||
def verified_fn(request, *args, **kwargs):
|
||||
comment_id = args.get('comment_id', False) or \
|
||||
kwargs.get('comment_id', False)
|
||||
comment_id = kwargs.get('comment_id', False)
|
||||
comment = comment_client.get_comment(comment_id)
|
||||
if request.user.id == comment['user_id']:
|
||||
if str(request.user.id) == str(comment['user_id']):
|
||||
return fn(request, *args, **kwargs)
|
||||
else:
|
||||
return JsonError(400, "unauthorized")
|
||||
return JsonError("unauthorized")
|
||||
return verified_fn
|
||||
|
||||
def instructor_only(fn): #TODO add instructor verification
|
||||
@@ -81,7 +79,7 @@ def delete_thread(request, course_id, thread_id):
|
||||
response = comment_client.delete_thread(thread_id)
|
||||
return JsonResponse(response)
|
||||
|
||||
@thread_author_only
|
||||
@comment_author_only
|
||||
@login_required
|
||||
@require_POST
|
||||
def update_comment(request, course_id, comment_id):
|
||||
|
||||
@@ -100,8 +100,10 @@ class JsonResponse(HttpResponse):
|
||||
mimetype='application/json; charset=utf8')
|
||||
|
||||
class JsonError(HttpResponse):
|
||||
def __init__(self, error_message=""):
|
||||
content = simplejson.dumps({'errors': error_message},
|
||||
def __init__(self, error_messages=[]):
|
||||
if isinstance(error_messages, str):
|
||||
error_messages = [error_messages]
|
||||
content = simplejson.dumps({'errors': error_messages},
|
||||
indent=2,
|
||||
ensure_ascii=False)
|
||||
super(JsonError, self).__init__(content,
|
||||
|
||||
@@ -124,10 +124,12 @@ $ ->
|
||||
return
|
||||
|
||||
if not $elem.find(".wmd-panel").length
|
||||
initialText = $elem.html()
|
||||
$elem.empty()
|
||||
_append = appended_id || ""
|
||||
$wmdPanel = $("<div>").addClass("wmd-panel")
|
||||
.append($("<div>").attr("id", "wmd-button-bar#{_append}"))
|
||||
.append($("<textarea>").addClass("wmd-input").attr("id", "wmd-input#{_append}"))
|
||||
.append($("<textarea>").addClass("wmd-input").attr("id", "wmd-input#{_append}").html(initialText))
|
||||
.append($("<div>").attr("id", "wmd-preview#{_append}").addClass("wmd-panel wmd-preview"))
|
||||
$elem.append($wmdPanel)
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ generateDiscussionLink = (cls, txt, handler) ->
|
||||
Discussion =
|
||||
|
||||
replyTemplate: """
|
||||
<div class="discussion-reply-new">
|
||||
<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}}" />
|
||||
@@ -35,9 +35,32 @@ Discussion =
|
||||
<input type="checkbox" class="discussion-auto-watch" id="discussion-autowatch-{{id}}" checked />
|
||||
<label for="discussion-auto-watch-{{id}}">watch this thread</label>
|
||||
{{/showWatchCheckbox}}
|
||||
</div>
|
||||
<br />
|
||||
<a class="discussion-submit-reply control-button" href="javascript:void(0)">Submit</a>
|
||||
<a class="discussion-cancel-reply control-button" href="javascript:void(0)">Cancel</a>
|
||||
</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}}" />
|
||||
<a class="discussion-submit-update control-button" href="javascript:void(0)">Update</a>
|
||||
<a class="discussion-cancel-update control-button" href="javascript:void(0)">Cancel</a>
|
||||
</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>
|
||||
<a class="discussion-submit-update control-button" href="javascript:void(0)">Update</a>
|
||||
<a class="discussion-cancel-update control-button" href="javascript:void(0)">Cancel</a>
|
||||
</form>
|
||||
"""
|
||||
|
||||
urlFor: (name, param) ->
|
||||
{
|
||||
watch_commentable : "/courses/#{$$course_id}/discussion/#{param}/watch"
|
||||
@@ -140,15 +163,14 @@ Discussion =
|
||||
$local(".thread").each(initializeVote).each(initializeWatchThreads)
|
||||
initializeWatchDiscussion(discussion)
|
||||
|
||||
if $$tags?
|
||||
$local(".new-post-tags").tagsInput
|
||||
autocomplete_url: Discussion.urlFor('tags_autocomplete')
|
||||
autocomplete:
|
||||
remoteDataType: 'json'
|
||||
interactive: true
|
||||
defaultText: "add a tag"
|
||||
height: "30px"
|
||||
removeWithBackspace: true
|
||||
$local(".new-post-tags").tagsInput
|
||||
autocomplete_url: Discussion.urlFor('tags_autocomplete')
|
||||
autocomplete:
|
||||
remoteDataType: 'json'
|
||||
interactive: true
|
||||
defaultText: "add a tag"
|
||||
height: "30px"
|
||||
removeWithBackspace: true
|
||||
|
||||
bindContentEvents: (content) ->
|
||||
|
||||
@@ -162,12 +184,6 @@ Discussion =
|
||||
status = $discussionContent.attr("status") || "normal"
|
||||
if status == "normal"
|
||||
$local(".discussion-link").show()
|
||||
else if status == "reply"
|
||||
$local(".discussion-cancel-reply").show()
|
||||
$local(".discussion-submit-reply").show()
|
||||
else if status == "edit"
|
||||
$local(".discussion-cancel-edit").show()
|
||||
$local(".discussion-update-edit").show()
|
||||
|
||||
discussionContentHoverOut = ->
|
||||
$local(".discussion-link").hide()
|
||||
@@ -175,9 +191,9 @@ Discussion =
|
||||
$discussionContent.hover(discussionContentHoverIn, discussionContentHoverOut)
|
||||
|
||||
handleReply = (elem) ->
|
||||
editView = $local(".discussion-reply-new")
|
||||
if editView.length
|
||||
editView.show()
|
||||
$replyView = $local(".discussion-reply-new")
|
||||
if $replyView.length
|
||||
$replyView.show()
|
||||
else
|
||||
view = {
|
||||
id: id
|
||||
@@ -185,19 +201,16 @@ Discussion =
|
||||
}
|
||||
$discussionContent.append Mustache.render Discussion.replyTemplate, view
|
||||
Markdown.makeWmdEditor $local(".reply-body"), "-reply-body-#{id}", Discussion.urlFor('upload')
|
||||
cancelReply = generateDiscussionLink("discussion-cancel-reply", "Cancel", handleCancelReply)
|
||||
submitReply = generateDiscussionLink("discussion-submit-reply", "Submit", handleSubmitReply)
|
||||
$local(".discussion-submit-reply").click handleSubmitReply
|
||||
$local(".discussion-cancel-reply").click handleCancelReply
|
||||
$local(".discussion-link").hide()
|
||||
$(elem).after(submitReply).replaceWith(cancelReply)
|
||||
$discussionContent.attr("status", "reply")
|
||||
|
||||
handleCancelReply = (elem) ->
|
||||
editView = $local(".discussion-reply-new")
|
||||
if editView.length
|
||||
editView.hide()
|
||||
$local(".discussion-submit-reply").remove()
|
||||
$replyView = $local(".discussion-reply-new")
|
||||
if $replyView.length
|
||||
$replyView.hide()
|
||||
reply = generateDiscussionLink("discussion-reply", "Reply", handleReply)
|
||||
$local(".discussion-link").show()
|
||||
$(elem).replaceWith(reply)
|
||||
$discussionContent.attr("status", "normal")
|
||||
|
||||
@@ -231,10 +244,76 @@ Discussion =
|
||||
Discussion.handleAnchorAndReload(response)
|
||||
, 'json'
|
||||
|
||||
handleCancelEdit = (elem) ->
|
||||
$local(".discussion-content-edit").hide()
|
||||
$local(".discussion-content-wrapper").show()
|
||||
|
||||
handleEditThread = (elem) ->
|
||||
$local(".discussion-content-wrapper").hide()
|
||||
$editView = $local(".discussion-content-edit")
|
||||
if $editView.length
|
||||
$editView.show()
|
||||
else
|
||||
view = {
|
||||
id: id
|
||||
title: $local(".thread-title").html()
|
||||
body: $local(".thread-raw-body").html()
|
||||
tags: $local(".thread-raw-tags").html()
|
||||
}
|
||||
$discussionContent.append Mustache.render Discussion.editThreadTemplate, view
|
||||
Markdown.makeWmdEditor $local(".thread-body-edit"), "-thread-body-edit-#{id}", Discussion.urlFor('update_thread', id)
|
||||
$local(".thread-tags-edit").tagsInput
|
||||
autocomplete_url: Discussion.urlFor('tags_autocomplete')
|
||||
autocomplete:
|
||||
remoteDataType: 'json'
|
||||
interactive: true
|
||||
defaultText: ""
|
||||
height: "30px"
|
||||
removeWithBackspace: true
|
||||
$local(".discussion-submit-update").unbind("click").click -> handleSubmitEditThread(this)
|
||||
$local(".discussion-cancel-update").unbind("click").click -> handleCancelEdit(this)
|
||||
|
||||
handleSubmitEditThread = (elem) ->
|
||||
url = Discussion.urlFor('update_thread', id)
|
||||
title = $local(".thread-title-edit").val()
|
||||
body = $local("#wmd-input-thread-body-edit-#{id}").val()
|
||||
tags = $local(".thread-tags-edit").val()
|
||||
$.post url, {title: title, body: body, tags: tags}, (response, textStatus) ->
|
||||
if response.errors
|
||||
errorsField = $local(".discussion-update-errors").empty()
|
||||
for error in response.errors
|
||||
errorsField.append($("<li>").addClass("new-post-form-error").html(error))
|
||||
else
|
||||
Discussion.handleAnchorAndReload(response)
|
||||
, 'json'
|
||||
|
||||
handleEditComment = (elem) ->
|
||||
|
||||
$local(".discussion-content-wrapper").hide()
|
||||
$editView = $local(".discussion-content-edit")
|
||||
if $editView.length
|
||||
$editView.show()
|
||||
else
|
||||
view = {
|
||||
id: id
|
||||
body: $local(".comment-raw-body").html()
|
||||
}
|
||||
$discussionContent.append Mustache.render Discussion.editCommentTemplate, view
|
||||
Markdown.makeWmdEditor $local(".comment-body-edit"), "-comment-body-edit-#{id}", Discussion.urlFor('update_comment', id)
|
||||
$local(".discussion-submit-update").unbind("click").click -> handleSubmitEditComment(this)
|
||||
$local(".discussion-cancel-update").unbind("click").click -> handleCancelEdit(this)
|
||||
|
||||
handleSubmitEditComment= (elem) ->
|
||||
url = Discussion.urlFor('update_comment', id)
|
||||
body = $local("#wmd-input-comment-body-edit-#{id}").val()
|
||||
$.post url, {body: body}, (response, textStatus) ->
|
||||
if response.errors
|
||||
errorsField = $local(".discussion-update-errors").empty()
|
||||
for error in response.errors
|
||||
errorsField.append($("<li>").addClass("new-post-form-error").html(error))
|
||||
else
|
||||
Discussion.handleAnchorAndReload(response)
|
||||
, 'json'
|
||||
|
||||
$local(".discussion-reply").click ->
|
||||
handleReply(this)
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ $discussion_input_width: 85%;
|
||||
margin-top: flex-gutter(8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.discussion-title {
|
||||
@include discussion-font;
|
||||
@include discussion-clickable;
|
||||
@@ -104,16 +104,16 @@ $discussion_input_width: 85%;
|
||||
float: left;
|
||||
width: 70%;
|
||||
}
|
||||
.new-post-form {
|
||||
.new-post-title, .new-post-body {
|
||||
.new-post-form, .discussion-thread-edit {
|
||||
.title-input, .body-input {
|
||||
@include discussion-font;
|
||||
display: block !important;
|
||||
width: $discussion_input_width !important;
|
||||
}
|
||||
.new-post-body {
|
||||
.body-input {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.discussion-new-post {
|
||||
.control-button {
|
||||
@include discussion-font;
|
||||
color: #1d9dd9;
|
||||
display: block;
|
||||
@@ -127,6 +127,12 @@ $discussion_input_width: 85%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.discussion-content-edit, .discussion-reply-new {
|
||||
.control-button {
|
||||
display: inline-block;
|
||||
}
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
.thread {
|
||||
//display: none;
|
||||
margin-top: 30px;
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
${search_bar}
|
||||
<form class="new-post-form" _id="${discussion_id}">
|
||||
<ul class="discussion-errors"></ul>
|
||||
<input type="text" class="new-post-title" placeholder="Title"/>
|
||||
<div class="new-post-body"></div>
|
||||
<input type="text" class="new-post-title title-input" placeholder="Title"/>
|
||||
<div class="new-post-body body-input"></div>
|
||||
<input class="new-post-tags" placeholder="Tags"/>
|
||||
<a class="discussion-new-post" href="javascript:void(0)">New Post</a>
|
||||
<a class="discussion-new-post control-button" href="javascript:void(0)">New Post</a>
|
||||
</form>
|
||||
</div>
|
||||
% for thread in threads:
|
||||
|
||||
@@ -28,12 +28,13 @@
|
||||
|
||||
<%def name="render_content(content, type, **kwargs)">
|
||||
<div class="discussion-content">
|
||||
<div class="discussion-upper-wrapper clearfix">
|
||||
<div class="discussion-content-wrapper clearfix">
|
||||
${render_vote(content)}
|
||||
<div class="discussion-right-wrapper clearfix">
|
||||
${render_title(content, type, **kwargs)}
|
||||
<div class="discussion-content-view">
|
||||
<div class="content-body ${type}-body">${content['body'] | h}</div>
|
||||
<div class="content-raw-body ${type}-raw-body" style="display: none">${content['body'] | h}</div>
|
||||
${render_tags(content, type, **kwargs)}
|
||||
${render_bottom_bar(content, type, **kwargs)}
|
||||
</div>
|
||||
@@ -63,9 +64,10 @@
|
||||
% if type == "thread":
|
||||
<div class="thread-tags">
|
||||
% for tag in content['tags']:
|
||||
<a class="thread-tag" href="${url_for_tags([tag])}">${tag}</a>
|
||||
<a class="thread-tag" href="${url_for_tags([tag])}">${tag | h}</a>
|
||||
% endfor
|
||||
</div>
|
||||
<div class="thread-raw-tags" style="display: none">${tag | h}</div>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user