Commit 7d32a90a by jsa

add ability to delete comments on responses in discussions.

parent eecb7fab
...@@ -2,7 +2,7 @@ describe 'All Content', -> ...@@ -2,7 +2,7 @@ describe 'All Content', ->
beforeEach -> beforeEach ->
# TODO: figure out a better way of handling this # TODO: figure out a better way of handling this
# It is set up in main.coffee DiscussionApp.start # It is set up in main.coffee DiscussionApp.start
window.$$course_id = 'mitX/999/test' window.$$course_id = 'edX/999/test'
window.user = new DiscussionUser {id: '567'} window.user = new DiscussionUser {id: '567'}
describe 'Content', -> describe 'Content', ->
...@@ -10,7 +10,7 @@ describe 'All Content', -> ...@@ -10,7 +10,7 @@ describe 'All Content', ->
@content = new Content { @content = new Content {
id: '01234567', id: '01234567',
user_id: '567', user_id: '567',
course_id: 'mitX/999/test', course_id: 'edX/999/test',
body: 'this is some content', body: 'this is some content',
abuse_flaggers: ['123'] abuse_flaggers: ['123']
} }
...@@ -22,7 +22,7 @@ describe 'All Content', -> ...@@ -22,7 +22,7 @@ describe 'All Content', ->
@content.initialize @content.initialize
expect(Content.contents['01234567']).toEqual @content expect(Content.contents['01234567']).toEqual @content
expect(@content.get 'id').toEqual '01234567' expect(@content.get 'id').toEqual '01234567'
expect(@content.get 'user_url').toEqual '/courses/mitX/999/test/discussion/forum/users/567' expect(@content.get 'user_url').toEqual '/courses/edX/999/test/discussion/forum/users/567'
expect(@content.get 'children').toEqual [] expect(@content.get 'children').toEqual []
expect(@content.get 'comments').toEqual(jasmine.any(Comments)) expect(@content.get 'comments').toEqual(jasmine.any(Comments))
......
...@@ -25,7 +25,7 @@ describe "DiscussionContentView", -> ...@@ -25,7 +25,7 @@ describe "DiscussionContentView", ->
@threadData = { @threadData = {
id: '01234567', id: '01234567',
user_id: '567', user_id: '567',
course_id: 'mitX/999/test', course_id: 'edX/999/test',
body: 'this is a thread', body: 'this is a thread',
created_at: '2013-04-03T20:08:39Z', created_at: '2013-04-03T20:08:39Z',
abuse_flaggers: ['123'], abuse_flaggers: ['123'],
......
...@@ -8,6 +8,8 @@ describe 'ResponseCommentShowView', -> ...@@ -8,6 +8,8 @@ describe 'ResponseCommentShowView', ->
<div class="response-body"><%- body %></div> <div class="response-body"><%- body %></div>
<div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="report misuse"> <div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="report misuse">
<i class="icon"></i><span class="flag-label"></span></div> <i class="icon"></i><span class="flag-label"></span></div>
<div style="display:none" class="discussion-delete-comment action-delete" data-role="comment-delete" data-tooltip="Delete Comment" role="button" aria-pressed="false" tabindex="0">
<i class="icon icon-remove"></i><span class="sr delete-label">Delete Comment</span></div>
<p class="posted-details">&ndash;posted <span class="timeago" title="<%- created_at %>"><%- created_at %></span> by <p class="posted-details">&ndash;posted <span class="timeago" title="<%- created_at %>"><%- created_at %></span> by
<% if (obj.username) { %> <% if (obj.username) { %>
<a href="<%- user_url %>" class="profile-link"><%- username %></a> <a href="<%- user_url %>" class="profile-link"><%- username %></a>
...@@ -18,18 +20,17 @@ describe 'ResponseCommentShowView', -> ...@@ -18,18 +20,17 @@ describe 'ResponseCommentShowView', ->
""" """
# set up a model for a new Comment # set up a model for a new Comment
@response = new Comment { @comment = new Comment {
id: '01234567', id: '01234567',
user_id: '567', user_id: '567',
course_id: 'mitX/999/test', course_id: 'edX/999/test',
body: 'this is a response', body: 'this is a response',
created_at: '2013-04-03T20:08:39Z', created_at: '2013-04-03T20:08:39Z',
abuse_flaggers: ['123'] abuse_flaggers: ['123']
roles: [] roles: []
} }
@view = new ResponseCommentShowView({ model: @response }) @view = new ResponseCommentShowView({ model: @comment })
spyOn(@view, "convertMath")
# spyOn(DiscussionUtil, 'loadRoles').andReturn []
it 'defines the tag', -> it 'defines the tag', ->
expect($('#jasmine-fixtures')).toExist expect($('#jasmine-fixtures')).toExist
...@@ -37,26 +38,36 @@ describe 'ResponseCommentShowView', -> ...@@ -37,26 +38,36 @@ describe 'ResponseCommentShowView', ->
expect(@view.el.tagName.toLowerCase()).toBe 'li' expect(@view.el.tagName.toLowerCase()).toBe 'li'
it 'is tied to the model', -> it 'is tied to the model', ->
expect(@view.model).toBeDefined(); expect(@view.model).toBeDefined()
describe 'rendering', -> describe 'rendering', ->
beforeEach -> beforeEach ->
spyOn(@view, 'renderAttrs') spyOn(@view, 'renderAttrs')
spyOn(@view, 'markAsStaff') spyOn(@view, 'markAsStaff')
spyOn(@view, 'convertMath')
it 'produces the correct HTML', -> it 'produces the correct HTML', ->
@view.render() @view.render()
expect(@view.el.innerHTML).toContain('"discussion-flag-abuse notflagged"') expect(@view.el.innerHTML).toContain('"discussion-flag-abuse notflagged"')
it 'can be flagged for abuse', -> it 'can be flagged for abuse', ->
@response.flagAbuse() @comment.flagAbuse()
expect(@response.get 'abuse_flaggers').toEqual ['123', '567'] expect(@comment.get 'abuse_flaggers').toEqual ['123', '567']
it 'can be unflagged for abuse', -> it 'can be unflagged for abuse', ->
temp_array = [] temp_array = []
temp_array.push(window.user.get('id')) temp_array.push(window.user.get('id'))
@response.set("abuse_flaggers",temp_array) @comment.set("abuse_flaggers",temp_array)
@response.unflagAbuse() @comment.unflagAbuse()
expect(@response.get 'abuse_flaggers').toEqual [] expect(@comment.get 'abuse_flaggers').toEqual []
describe 'comment deletion', ->
it 'triggers the delete event when the delete icon is clicked', ->
DiscussionUtil.loadRoles []
@comment.updateInfo {ability: {'can_delete': true}}
triggerTarget = jasmine.createSpy()
@view.bind "comment:_delete", triggerTarget
@view.render()
@view.$el.find('.action-delete').click()
expect(triggerTarget).toHaveBeenCalled()
describe 'ResponseCommentView', ->
beforeEach ->
@comment = new Comment {
id: '01234567',
user_id: '567',
course_id: 'edX/999/test',
body: 'this is a response',
created_at: '2013-04-03T20:08:39Z',
abuse_flaggers: ['123']
roles: ['Student']
}
@view = new ResponseCommentView({ model: @comment })
spyOn(@view, "render")
describe '_delete', ->
beforeEach ->
@comment.updateInfo {ability: {can_delete: true}}
@event = jasmine.createSpyObj('event', ['preventDefault', 'target'])
spyOn(@comment, "remove")
spyOn(@view.$el, "remove")
setAjaxResult = (isSuccess) ->
spyOn($, "ajax").andCallFake(
(params) =>
(if isSuccess then params.success else params.error) {}
{always: ->}
)
it 'requires confirmation before deleting', ->
spyOn(window, "confirm").andReturn(false)
setAjaxResult(true)
@view._delete(@event)
expect(window.confirm).toHaveBeenCalled()
expect($.ajax).not.toHaveBeenCalled()
expect(@comment.remove).not.toHaveBeenCalled()
it 'removes the deleted comment object', ->
setAjaxResult(true)
@view._delete(@event)
expect(@comment.remove).toHaveBeenCalled()
expect(@view.$el.remove).toHaveBeenCalled()
it 'calls the ajax comment deletion endpoint', ->
setAjaxResult(true)
@view._delete(@event)
expect(@event.preventDefault).toHaveBeenCalled()
expect($.ajax).toHaveBeenCalled()
expect($.ajax.mostRecentCall.args[0].url._parts.path).toEqual('/courses/edX/999/test/discussion/comments/01234567/delete')
it 'handles ajax errors', ->
spyOn(DiscussionUtil, "discussionAlert")
setAjaxResult(false)
@view._delete(@event)
expect(@event.preventDefault).toHaveBeenCalled()
expect($.ajax).toHaveBeenCalled()
expect(@comment.remove).not.toHaveBeenCalled()
expect(@view.$el.remove).not.toHaveBeenCalled()
expect(DiscussionUtil.discussionAlert).toHaveBeenCalled()
it 'does not delete a comment if the permission is false', ->
@comment.updateInfo {ability: {'can_delete': false}}
spyOn(window, "confirm")
setAjaxResult(true)
@view._delete(@event)
expect(window.confirm).not.toHaveBeenCalled()
expect($.ajax).not.toHaveBeenCalled()
expect(@comment.remove).not.toHaveBeenCalled()
expect(@view.$el.remove).not.toHaveBeenCalled()
if Backbone? if Backbone?
class @ResponseCommentShowView extends DiscussionContentView class @ResponseCommentShowView extends DiscussionContentView
events:
"click .action-delete": "_delete"
tagName: "li" tagName: "li"
initialize: -> initialize: ->
super() super()
@model.on "change", @updateModelDetails @model.on "change", @updateModelDetails
abilityRenderer:
can_delete:
enable: -> @$(".action-delete").show()
disable: -> @$(".action-delete").hide()
render: -> render: ->
@template = _.template($("#response-comment-show-template").html()) @template = _.template($("#response-comment-show-template").html())
params = @model.toJSON() params = @model.toJSON()
...@@ -40,6 +48,8 @@ if Backbone? ...@@ -40,6 +48,8 @@ if Backbone?
else if DiscussionUtil.isTA(@model.get("user_id")) else if DiscussionUtil.isTA(@model.get("user_id"))
@$el.find("a.profile-link").after('<span class="community-ta-label">' + gettext('Community TA') + '</span>') @$el.find("a.profile-link").after('<span class="community-ta-label">' + gettext('Community TA') + '</span>')
_delete: (event) ->
@trigger "comment:_delete", event
renderFlagged: => renderFlagged: =>
if window.user.id in @model.get("abuse_flaggers") or (DiscussionUtil.isFlagModerator and @model.get("abuse_flaggers").length > 0) if window.user.id in @model.get("abuse_flaggers") or (DiscussionUtil.isFlagModerator and @model.get("abuse_flaggers").length > 0)
......
...@@ -21,6 +21,7 @@ if Backbone? ...@@ -21,6 +21,7 @@ if Backbone?
@editView = null @editView = null
@showView = new ResponseCommentShowView(model: @model) @showView = new ResponseCommentShowView(model: @model)
@showView.bind "comment:_delete", @_delete
renderSubView: (view) -> renderSubView: (view) ->
view.setElement(@$el) view.setElement(@$el)
...@@ -29,3 +30,24 @@ if Backbone? ...@@ -29,3 +30,24 @@ if Backbone?
renderShowView: () -> renderShowView: () ->
@renderSubView(@showView) @renderSubView(@showView)
_delete: (event) =>
event.preventDefault()
if not @model.can('can_delete')
return
if not confirm gettext("Are you sure you want to delete this comment?")
return
url = @model.urlFor('_delete')
$elem = $(event.target)
DiscussionUtil.safeAjax
$elem: $elem
url: url
type: "POST"
success: (response, textStatus) =>
@model.remove()
@$el.remove()
error: =>
DiscussionUtil.discussionAlert(
gettext("Sorry"),
gettext("We had some trouble deleting this comment. Please try again.")
)
...@@ -91,6 +91,7 @@ if Backbone? ...@@ -91,6 +91,7 @@ if Backbone?
body: body body: body
success: (response, textStatus) -> success: (response, textStatus) ->
comment.set(response.content) comment.set(response.content)
comment.updateInfo(response.annotated_content_info)
view.render() # This is just to update the id for the most part, but might be useful in general view.render() # This is just to update the id for the most part, but might be useful in general
_delete: (event) => _delete: (event) =>
......
...@@ -2529,7 +2529,7 @@ body.discussion { ...@@ -2529,7 +2529,7 @@ body.discussion {
display:none; display:none;
} }
.discussion-flag-abuse { .discussion-flag-abuse, .discussion-delete-comment {
font-size: 12px; font-size: 12px;
float:right; float:right;
padding-right: 5px; padding-right: 5px;
...@@ -2542,7 +2542,7 @@ display:none; ...@@ -2542,7 +2542,7 @@ display:none;
opacity: 1.0; opacity: 1.0;
} }
} }
.notflagged .icon { .notflagged .icon {
display: block; display: block;
color: #333; color: #333;
......
...@@ -166,6 +166,8 @@ ...@@ -166,6 +166,8 @@
<div class="response-body">${'<%- body %>'}</div> <div class="response-body">${'<%- body %>'}</div>
<div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="${_('Report Misuse') | h}" role="button" aria-pressed="false" tabindex="0"> <div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="${_('Report Misuse') | h}" role="button" aria-pressed="false" tabindex="0">
<i class="icon icon-flag"></i><span class="sr flag-label">${_("Report Misuse")}</span></div> <i class="icon icon-flag"></i><span class="sr flag-label">${_("Report Misuse")}</span></div>
<div style="display: none" class="discussion-delete-comment action-delete" data-tooltip="${_('Delete Comment') | h}" role="button" tabindex="0">
<i class="icon icon-remove"></i><span class="sr">${_("Delete Comment")}</span></div>
<% <%
js_block = u""" js_block = u"""
interpolate( interpolate(
......
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