Skip to content
Extraits de code Groupes Projets
Valider 1748d3b9 rédigé par Lukas Matt's avatar Lukas Matt
Parcourir les fichiers

It is now possible to report comments

* Renamed PostReport to Report
* Added report button to SPV
* Updated rspec

refs diaspora/diaspora#4732
refs diaspora/diaspora#4710
refs diaspora/diaspora#4711
refs diaspora/diaspora#4517
parent ee6212c6
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 195 ajouts et 54 suppressions
Fichier déplacé
app.models.PostReport = Backbone.Model.extend({
urlRoot: '/post_report'
});
app.models.Report = Backbone.Model.extend({
urlRoot: '/report',
getReason: function() {
return prompt(Diaspora.I18n.t('report_prompt'), Diaspora.I18n.t('report_prompt_default'));
}
});
...@@ -5,7 +5,8 @@ app.views.Comment = app.views.Content.extend({ ...@@ -5,7 +5,8 @@ app.views.Comment = app.views.Content.extend({
events : function() { events : function() {
return _.extend({}, app.views.Content.prototype.events, { return _.extend({}, app.views.Content.prototype.events, {
"click .comment_delete": "destroyModel" "click .comment_delete": "destroyModel",
"click .comment_report": "report"
}); });
}, },
...@@ -31,6 +32,20 @@ app.views.Comment = app.views.Content.extend({ ...@@ -31,6 +32,20 @@ app.views.Comment = app.views.Content.extend({
canRemove : function() { canRemove : function() {
return app.currentUser.authenticated() && (this.ownComment() || this.postOwner()) return app.currentUser.authenticated() && (this.ownComment() || this.postOwner())
},
report: function(evt) {
if(evt) { evt.preventDefault(); }
var report = new app.models.Report();
var msg = report.getReason();
if (msg !== null) {
var id = this.model.id;
var type = $(evt.currentTarget).data("type");
report.fetch({
data: { id: id, type: type, text: msg },
type: 'POST'
});
}
} }
}); });
......
...@@ -6,7 +6,8 @@ app.views.Feedback = app.views.Base.extend({ ...@@ -6,7 +6,8 @@ app.views.Feedback = app.views.Base.extend({
events: { events: {
"click *[rel='auth-required']" : "requireAuth", "click *[rel='auth-required']" : "requireAuth",
"click .like" : "toggleLike", "click .like" : "toggleLike",
"click .reshare" : "resharePost" "click .reshare" : "resharePost",
"click .post_report" : "report"
}, },
tooltipSelector : ".label", tooltipSelector : ".label",
...@@ -44,5 +45,19 @@ app.views.Feedback = app.views.Base.extend({ ...@@ -44,5 +45,19 @@ app.views.Feedback = app.views.Base.extend({
if( app.currentUser.authenticated() ) { return } if( app.currentUser.authenticated() ) { return }
alert("you must be logged in to do that!") alert("you must be logged in to do that!")
return false; return false;
},
report: function(evt) {
if(evt) { evt.preventDefault(); }
var report = new app.models.Report();
var msg = report.getReason();
if (msg !== null) {
var id = this.model.id;
var type = $(evt.currentTarget).data("type");
report.fetch({
data: { id: id, type: type, text: msg },
type: 'POST'
});
}
} }
}); });
...@@ -13,5 +13,20 @@ app.views.Post = app.views.Base.extend({ ...@@ -13,5 +13,20 @@ app.views.Post = app.views.Base.extend({
showPost : function() { showPost : function() {
return (app.currentUser.get("showNsfw")) || !this.model.get("nsfw") return (app.currentUser.get("showNsfw")) || !this.model.get("nsfw")
},
report: function(evt) {
if(evt) { evt.preventDefault(); }
var report = new app.models.Report();
var msg = report.getReason();
if (msg !== null) {
var id = this.model.id;
var type = $(evt.currentTarget).data("type");
report.fetch({
data: { id: id, type: type, text: msg },
type: 'POST'
});
}
} }
}); });
...@@ -20,7 +20,7 @@ app.views.StreamPost = app.views.Post.extend({ ...@@ -20,7 +20,7 @@ app.views.StreamPost = app.views.Post.extend({
"click .remove_post": "destroyModel", "click .remove_post": "destroyModel",
"click .hide_post": "hidePost", "click .hide_post": "hidePost",
"click .post_report": "postReport", "click .post_report": "report",
"click .block_user": "blockUser" "click .block_user": "blockUser"
}, },
...@@ -108,21 +108,6 @@ app.views.StreamPost = app.views.Post.extend({ ...@@ -108,21 +108,6 @@ app.views.StreamPost = app.views.Post.extend({
this.remove(); this.remove();
}, },
postReport : function(evt) {
if(evt) { evt.preventDefault(); }
var text = prompt(Diaspora.I18n.t('post_report_prompt'),
Diaspora.I18n.t('post_report_prompt_default'));
var postReport = new app.models.PostReport();
postReport.fetch({
data: {
post_id: this.model.id,
text: text
},
type: 'POST'
});
},
focusCommentTextarea: function(evt){ focusCommentTextarea: function(evt){
evt.preventDefault(); evt.preventDefault();
this.$(".new_comment_form_wrapper").removeClass("hidden"); this.$(".new_comment_form_wrapper").removeClass("hidden");
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
@import 'facebox' @import 'facebox'
@import 'aspects' @import 'aspects'
@import 'popover' @import 'popover'
@import 'post_report'
@import 'stream_element' @import 'stream_element'
@import 'report'
/* ====== media ====== */ /* ====== media ====== */
.media .media
...@@ -211,10 +211,10 @@ ul.as-selections ...@@ -211,10 +211,10 @@ ul.as-selections
:z-index 6 :z-index 6
:float right :float right
.post_report .post_report, .comment_report
:display inline-block :display inline-block
.icons-postreport .icons-report
:height 14px :height 14px
:width 14px :width 14px
......
...@@ -141,6 +141,7 @@ ...@@ -141,6 +141,7 @@
&.globe:before { content: '\1f30e'; } /* 1f30e */ &.globe:before { content: '\1f30e'; } /* 1f30e */
&.graduation-cap:before { content: '\1f393 '; } /* 1f393 */ &.graduation-cap:before { content: '\1f393 '; } /* 1f393 */
&.heart-empty:before { content: '\2661'; } /* 2661 */ &.heart-empty:before { content: '\2661'; } /* 2661 */
&.report:before { content: '\21'; } /* 21 */
&.heart:before { content: '\2665'; } /* 2665 */ &.heart:before { content: '\2665'; } /* 2665 */
&.help:before { content: '\2753'; } /* 2753 */ &.help:before { content: '\2753'; } /* 2753 */
&.home:before { content: '\2302'; } /* 2302 */ &.home:before { content: '\2302'; } /* 2302 */
......
#post_report { #report {
padding-top: 2em; padding-top: 2em;
span { span {
display: block; display: block;
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
} }
.clear { .clear {
clear: both; clear: both;
border-bottom: 1px solid #808080;
padding-bottom: 1em; padding-bottom: 1em;
margin-bottom: 1em;
} }
} }
...@@ -61,6 +61,12 @@ ...@@ -61,6 +61,12 @@
i.comment:hover { i.comment:hover {
color: #424242; color: #424242;
} }
i.report.gray:hover {
color: $red;
}
i.report.red:hover {
color: #f55f5a;
}
i.heart.gray:hover { i.heart.gray:hover {
color: $red; color: $red;
} }
......
...@@ -6,13 +6,17 @@ ...@@ -6,13 +6,17 @@
</div> </div>
<div class="bd"> <div class="bd">
<div class="controls">
{{#if canRemove}} {{#if canRemove}}
<div class="controls"> <a href="#" class="delete comment_delete" title="{{t "delete"}}">
<a href="#" class="delete comment_delete" title="{{t "delete"}}"> <div alt="Deletelabel" class="icons-deletelabel" />
<div alt="Deletelabel" class="icons-deletelabel" /> <a/>
<a/> {{else}}
</div> <a href="#" data-type="comment" class="comment_report" title="{{t "report"}}">
<div class="icons-report control_icon"/>
</a>
{{/if}} {{/if}}
</div>
{{#with author}} {{#with author}}
<a href="/people/{{guid}}" class="author author-name {{hovercardable this}}"> <a href="/people/{{guid}}" class="author author-name {{hovercardable this}}">
......
...@@ -22,5 +22,9 @@ ...@@ -22,5 +22,9 @@
</a> </a>
{{/if}} {{/if}}
{{/if}} {{/if}}
<a href="#" rel="auth-required" data-type="post" class="post_report" title="{{t "report"}}">
<i class="entypo report gray large"/>
</a>
</div> </div>
</div> </div>
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
{{#if loggedIn}} {{#if loggedIn}}
<div class="controls"> <div class="controls">
{{#unless authorIsCurrentUser}} {{#unless authorIsCurrentUser}}
<a href="#" rel="nofollow" class="post_report" title="{{t "post_report"}}"> <a href="#" rel="nofollow" data-type="post" class="post_report" title="{{t "report"}}">
<div class="icons-postreport control_icon"/> <div class="icons-report control_icon"/>
</a> </a>
<a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}"> <a href="#" rel="nofollow" class="block_user" title="{{t "ignore"}}">
<div class="icons-ignoreuser control_icon"></div> <div class="icons-ignoreuser control_icon"></div>
......
class PostReportController < ApplicationController class ReportController < ApplicationController
before_filter :authenticate_user! before_filter :authenticate_user!
before_filter :redirect_unless_admin, :except => [:create] before_filter :redirect_unless_admin, :except => [:create]
def index def index
@post_report = PostReport.where(reviewed: false).all @report = Report.where(reviewed: false).all
end end
def update def update
if PostReport.exists?(post_id: params[:id]) if Report.where(post_type: params[:type]).exists?(post_id: params[:id])
mark_as_reviewed mark_as_reviewed
end end
redirect_to :action => :index and return redirect_to :action => :index and return
end end
def destroy def destroy
if Post.exists?(params[:id]) if (params[:type].eql? "post")
delete_post if Post.exists?(params[:id])
mark_as_reviewed delete_post
end
elsif (params[:type].eql? "comment")
if Comment.exists?(params[:id])
delete_comment
end
end end
redirect_to :action => :index and return redirect_to :action => :index and return
end end
def create def create
code = 400
username = current_user.username username = current_user.username
unless PostReport.where(post_id: params[:post_id]).exists?(user_id: username) post = Report.new(
post = PostReport.new( :post_id => params[:id],
:post_id => params[:post_id], :post_type => params[:type],
:user_id => username, :user_id => username,
:text => params[:text]) :text => params[:text])
unless Report.where("post_id = ? AND post_type = ?", params[:id], params[:type]).exists?(user_id: username)
result = post.save result = post.save
status(( 200 if result ) || ( 422 if !result )) code = 200 if result
else
status(409)
end end
render :nothing => true, :status => code
end end
private private
def delete_post def delete_post
post = Post.find(params[:id]) post = Post.find(params[:id])
current_user.retract(post) current_user.retract(post)
flash[:notice] = I18n.t 'post_report.status.destroyed' mark_as_reviewed
flash[:notice] = I18n.t 'report.status.destroyed'
end end
def mark_as_reviewed id = params[:id] def delete_comment
posts = PostReport.where(post_id: id) comment = Comment.find(params[:id])
posts.each do |post| #current_user.retract(comment)
post.update_attributes(reviewed: true) comment.destroy
end mark_as_reviewed
flash[:notice] = I18n.t 'post_report.status.marked' flash[:notice] = I18n.t 'report.status.destroyed'
end end
def status(code) def mark_as_reviewed
if code == 200 posts = Report.where("post_id = ? AND post_type = ?", params[:id], params[:type])
flash[:notice] = I18n.t 'post_report.status.created' posts.each do |post|
else post.update_attributes(reviewed: true)
flash[:error] = I18n.t 'post_report.status.failed'
end end
render :nothing => true, :status => code flash[:notice] = I18n.t 'report.status.marked'
end end
end end
# Copyright (c) 2012, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
module ReportHelper
def report_content(id, type)
if type.eql? "post"
raw t('report.post_label', title: link_to(post_page_title(Post.find_by_id(id)), post_path(id)))
elsif type.eql? "comment"
raw t('report.comment_label', data: comment_message(Comment.find_by_id(id)))
end
end
end
class PostReportMailer < ActionMailer::Base
default :from => AppConfig.mail.sender_address
def new_report
Role.admins.each do |role|
email = User.find_by_id(role.person_id).email
format(email).deliver
end
end
private
def format(email)
mail(to: email, subject: I18n.t('notifier.post_report_email.subject')) do |format|
format.text { render 'post_report/post_report_email' }
format.html { render 'post_report/post_report_email' }
end
end
end
class ReportMailer < ActionMailer::Base
default :from => AppConfig.mail.sender_address
def new_report(type, id)
url = AppConfig.pod_uri.to_s
url << report_index_path
resource = Hash[
:subject => I18n.t('notifier.report_email.subject', :type => type),
:url => url,
:type => type,
:id => id
]
Role.admins.each do |role|
resource[:email] = User.find_by_id(role.person_id).email
format(resource).deliver
end
end
private
def format(resource)
mail(to: resource[:email], subject: resource[:subject]) do |format|
format.html { render 'report/report_email', :locals => { :resource => resource } }
format.text { render 'report/report_email', :locals => { :resource => resource } }
end
end
end
class PostReport < ActiveRecord::Base class Report < ActiveRecord::Base
validates :user_id, presence: true validates :user_id, presence: true
validates :post_id, presence: true validates :post_id, presence: true
validates :post_type, presence: true
belongs_to :user belongs_to :user
belongs_to :post belongs_to :post
has_many :post_reports has_many :reports
after_create :send_report_notification after_create :send_report_notification
def send_report_notification def send_report_notification
Workers::Mail::PostReportWorker.perform_async Workers::Mail::ReportWorker.perform_async(self.post_type, self.post_id)
end end
end end
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%li= link_to t('.user_search'), user_search_path %li= link_to t('.user_search'), user_search_path
%li= link_to t('.weekly_user_stats'), weekly_user_stats_path %li= link_to t('.weekly_user_stats'), weekly_user_stats_path
%li= link_to t('.pod_stats'), pod_stats_path %li= link_to t('.pod_stats'), pod_stats_path
%li= link_to t('.post_report'), post_report_index_path %li= link_to t('.report'), report_index_path
%li= link_to t('.correlations'), correlations_path %li= link_to t('.correlations'), correlations_path
%li= link_to t('.sidekiq_monitor'), sidekiq_path %li= link_to t('.sidekiq_monitor'), sidekiq_path
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter