Commit df203097 by Rocky Duan

basic editing functionality

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