Skip to content
Snippets Groups Projects
Commit e3a71b16 authored by Jim Abramson's avatar Jim Abramson
Browse files

Merge pull request #2646 from edx/jsa/forum-delete-comments

add ability to delete comments on responses in discussions.
parents e0aa30f0 7d32a90a
No related merge requests found
......@@ -2,7 +2,7 @@ describe 'All Content', ->
beforeEach ->
# TODO: figure out a better way of handling this
# 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'}
describe 'Content', ->
......@@ -10,7 +10,7 @@ describe 'All Content', ->
@content = new Content {
id: '01234567',
user_id: '567',
course_id: 'mitX/999/test',
course_id: 'edX/999/test',
body: 'this is some content',
abuse_flaggers: ['123']
}
......@@ -22,7 +22,7 @@ describe 'All Content', ->
@content.initialize
expect(Content.contents['01234567']).toEqual @content
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 'comments').toEqual(jasmine.any(Comments))
......
......@@ -25,7 +25,7 @@ describe "DiscussionContentView", ->
@threadData = {
id: '01234567',
user_id: '567',
course_id: 'mitX/999/test',
course_id: 'edX/999/test',
body: 'this is a thread',
created_at: '2013-04-03T20:08:39Z',
abuse_flaggers: ['123'],
......
......@@ -8,6 +8,8 @@ describe 'ResponseCommentShowView', ->
<div class="response-body"><%- body %></div>
<div class="discussion-flag-abuse notflagged" data-role="thread-flag" data-tooltip="report misuse">
<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
<% if (obj.username) { %>
<a href="<%- user_url %>" class="profile-link"><%- username %></a>
......@@ -18,18 +20,17 @@ describe 'ResponseCommentShowView', ->
"""
# set up a model for a new Comment
@response = new Comment {
@comment = new Comment {
id: '01234567',
user_id: '567',
course_id: 'mitX/999/test',
course_id: 'edX/999/test',
body: 'this is a response',
created_at: '2013-04-03T20:08:39Z',
abuse_flaggers: ['123']
roles: []
}
@view = new ResponseCommentShowView({ model: @response })
# spyOn(DiscussionUtil, 'loadRoles').andReturn []
@view = new ResponseCommentShowView({ model: @comment })
spyOn(@view, "convertMath")
it 'defines the tag', ->
expect($('#jasmine-fixtures')).toExist
......@@ -37,26 +38,36 @@ describe 'ResponseCommentShowView', ->
expect(@view.el.tagName.toLowerCase()).toBe 'li'
it 'is tied to the model', ->
expect(@view.model).toBeDefined();
expect(@view.model).toBeDefined()
describe 'rendering', ->
beforeEach ->
spyOn(@view, 'renderAttrs')
spyOn(@view, 'markAsStaff')
spyOn(@view, 'convertMath')
it 'produces the correct HTML', ->
@view.render()
expect(@view.el.innerHTML).toContain('"discussion-flag-abuse notflagged"')
it 'can be flagged for abuse', ->
@response.flagAbuse()
expect(@response.get 'abuse_flaggers').toEqual ['123', '567']
@comment.flagAbuse()
expect(@comment.get 'abuse_flaggers').toEqual ['123', '567']
it 'can be unflagged for abuse', ->
temp_array = []
temp_array.push(window.user.get('id'))
@response.set("abuse_flaggers",temp_array)
@response.unflagAbuse()
expect(@response.get 'abuse_flaggers').toEqual []
@comment.set("abuse_flaggers",temp_array)
@comment.unflagAbuse()
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?
class @ResponseCommentShowView extends DiscussionContentView
events:
"click .action-delete": "_delete"
tagName: "li"
initialize: ->
super()
@model.on "change", @updateModelDetails
abilityRenderer:
can_delete:
enable: -> @$(".action-delete").show()
disable: -> @$(".action-delete").hide()
render: ->
@template = _.template($("#response-comment-show-template").html())
params = @model.toJSON()
......@@ -40,6 +48,8 @@ if Backbone?
else if DiscussionUtil.isTA(@model.get("user_id"))
@$el.find("a.profile-link").after('<span class="community-ta-label">' + gettext('Community TA') + '</span>')
_delete: (event) ->
@trigger "comment:_delete", event
renderFlagged: =>
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?
@editView = null
@showView = new ResponseCommentShowView(model: @model)
@showView.bind "comment:_delete", @_delete
renderSubView: (view) ->
view.setElement(@$el)
......@@ -29,3 +30,24 @@ if Backbone?
renderShowView: () ->
@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?
body: body
success: (response, textStatus) ->
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
_delete: (event) =>
......
......@@ -2529,7 +2529,7 @@ body.discussion {
display:none;
}
.discussion-flag-abuse {
.discussion-flag-abuse, .discussion-delete-comment {
font-size: 12px;
float:right;
padding-right: 5px;
......@@ -2542,7 +2542,7 @@ display:none;
opacity: 1.0;
}
}
.notflagged .icon {
display: block;
color: #333;
......
......@@ -166,6 +166,8 @@
<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">
<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"""
interpolate(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment