0
0
Fork 0

Feature: Report improvements (#6967) (#7000)

* Implement Assignment of Reports (#6967)

* Change translation of admin.report.comment.label to "Report Comment" for clarity

As we'll soon add the ability for reports to have comments on them, this clarification makes sense.

* Implement notes for Reports

This enables moderators to leave comments about a report whilst they work on it

* Fix display of report moderation notes

* Allow reports to be reopened / marked as unresolved

* Redirect to reports listing upon resolution of report

* Implement "resolve with note" functionality

* Add inverse relationship for report notes

* Remove additional database querying when loading report notes

* Fix tests for reports

* Fix localisations for report notes / reports
This commit is contained in:
Emelia Smith 2018-04-02 22:04:14 +02:00 committed by Eugen Rochko
parent 36eac8ba90
commit e85cffb236
17 changed files with 290 additions and 25 deletions

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
module Admin
class ReportNotesController < BaseController
before_action :set_report_note, only: [:destroy]
def create
authorize ReportNote, :create?
@report_note = current_account.report_notes.new(resource_params)
if @report_note.save
if params[:create_and_resolve]
@report_note.report.update!(action_taken: true, action_taken_by_account_id: current_account.id)
log_action :resolve, @report_note.report
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
else
redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.created_msg')
end
else
@report = @report_note.report
@report_notes = @report.notes.latest
@form = Form::StatusBatch.new
render template: 'admin/reports/show'
end
end
def destroy
authorize @report_note, :destroy?
@report_note.destroy!
redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.destroyed_msg')
end
private
def resource_params
params.require(:report_note).permit(
:content,
:report_id
)
end
def set_report_note
@report_note = ReportNote.find(params[:id])
end
end
end

View file

@ -11,19 +11,35 @@ module Admin
def show
authorize @report, :show?
@report_note = @report.notes.new
@report_notes = @report.notes.latest
@form = Form::StatusBatch.new
end
def update
authorize @report, :update?
process_report
redirect_to admin_report_path(@report)
if @report.action_taken?
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
else
redirect_to admin_report_path(@report)
end
end
private
def process_report
case params[:outcome].to_s
when 'assign_to_self'
@report.update!(assigned_account_id: current_account.id)
log_action :assigned_to_self, @report
when 'unassign'
@report.update!(assigned_account_id: nil)
log_action :unassigned, @report
when 'reopen'
@report.update!(action_taken: false, action_taken_by_account_id: nil)
log_action :reopen, @report
when 'resolve'
@report.update!(action_taken_by_current_attributes)
log_action :resolve, @report
@ -32,11 +48,13 @@ module Admin
log_action :resolve, @report
log_action :suspend, @report.target_account
resolve_all_target_account_reports
@report.reload
when 'silence'
@report.target_account.update!(silenced: true)
log_action :resolve, @report
log_action :silence, @report.target_account
resolve_all_target_account_reports
@report.reload
else
raise ActiveRecord::RecordNotFound
end

View file

@ -86,7 +86,7 @@ module Admin::ActionLogsHelper
opposite_verbs?(log) ? 'negative' : 'positive'
when :update, :reset_password, :disable_2fa, :memorialize
'neutral'
when :demote, :silence, :disable, :suspend, :remove_avatar
when :demote, :silence, :disable, :suspend, :remove_avatar, :reopen
'negative'
when :destroy
opposite_verbs?(log) ? 'positive' : 'negative'

View file

@ -95,6 +95,8 @@ class Account < ApplicationRecord
has_many :reports
has_many :targeted_reports, class_name: 'Report', foreign_key: :target_account_id
has_many :report_notes, dependent: :destroy
# Moderation notes
has_many :account_moderation_notes, dependent: :destroy
has_many :targeted_moderation_notes, class_name: 'AccountModerationNote', foreign_key: :target_account_id, dependent: :destroy

View file

@ -12,12 +12,16 @@
# account_id :integer not null
# action_taken_by_account_id :integer
# target_account_id :integer not null
# assigned_account_id :integer
#
class Report < ApplicationRecord
belongs_to :account
belongs_to :target_account, class_name: 'Account'
belongs_to :action_taken_by_account, class_name: 'Account', optional: true
belongs_to :assigned_account, class_name: 'Account', optional: true
has_many :notes, class_name: 'ReportNote', foreign_key: :report_id, inverse_of: :report, dependent: :destroy
scope :unresolved, -> { where(action_taken: false) }
scope :resolved, -> { where(action_taken: true) }

21
app/models/report_note.rb Normal file
View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: report_notes
#
# id :integer not null, primary key
# content :text not null
# report_id :integer not null
# account_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
#
class ReportNote < ApplicationRecord
belongs_to :account
belongs_to :report, inverse_of: :notes
scope :latest, -> { reorder('created_at ASC') }
validates :content, presence: true, length: { maximum: 500 }
end

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
class ReportNotePolicy < ApplicationPolicy
def create?
staff?
end
def destroy?
admin? || owner?
end
private
def owner?
record.account_id == current_account&.id
end
end

View file

@ -0,0 +1,11 @@
%tr
%td
%p
%strong= report_note.account.acct
on
%time.formatted{ datetime: report_note.created_at.iso8601, title: l(report_note.created_at) }
= l report_note.created_at
= table_link_to 'trash', t('admin.reports.notes.delete'), admin_report_note_path(report_note), method: :delete if can?(:destroy, report_note)
%br/
%br/
= simple_format(h(report_note.content))

View file

@ -17,5 +17,10 @@
%span{ title: t('admin.accounts.media_attachments') }
= fa_icon('camera')
= report.media_attachments.count
%td
- if report.assigned_account.nil?
\-
- else
= link_to report.assigned_account.acct, admin_account_path(report.assigned_account.id)
%td
= table_link_to 'circle', t('admin.reports.view'), admin_report_path(report)

View file

@ -20,6 +20,7 @@
%th= t('admin.reports.reported_by')
%th= t('admin.reports.comment.label')
%th= t('admin.reports.report_contents')
%th= t('admin.reports.assigned')
%th
%tbody
= render @reports

View file

@ -4,24 +4,68 @@
- content_for :page_title do
= t('admin.reports.report', id: @report.id)
%div{ style: 'overflow: hidden; margin-bottom: 20px' }
- if !@report.action_taken?
%div{ style: 'float: right' }
= link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
= link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
%div{ style: 'float: left' }
= link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button'
- else
= link_to t('admin.reports.mark_as_unresolved'), admin_report_path(@report, outcome: 'reopen'), method: :put, class: 'button'
.table-wrapper
%table.table.inline-table
%tbody
%tr
%th= t('admin.reports.updated_at')
%td{colspan: 2}
%time.formatted{ datetime: @report.updated_at.iso8601 }
%tr
%th= t('admin.reports.status')
%td{colspan: 2}
- if @report.action_taken?
= t('admin.reports.resolved')
= table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
- else
= t('admin.reports.unresolved')
- if !@report.action_taken_by_account.nil?
%tr
%th= t('admin.reports.action_taken_by')
%td= @report.action_taken_by_account.acct
- else
%tr
%th= t('admin.reports.assigned')
%td
- if @report.assigned_account.nil?
\-
- else
= link_to @report.assigned_account.acct, admin_account_path(@report.assigned_account.id)
%td{style: "text-align: right"}
- if @report.assigned_account != current_user.account
= table_link_to 'user', t('admin.reports.assign_to_self'), admin_report_path(@report, outcome: 'assign_to_self'), method: :put
- if !@report.assigned_account.nil?
= table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put
.report-accounts
.report-accounts__item
%strong= t('admin.reports.reported_account')
%h3= t('admin.reports.reported_account')
= render 'authorize_follows/card', account: @report.target_account, admin: true
= render 'admin/accounts/card', account: @report.target_account
.report-accounts__item
%strong= t('admin.reports.reported_by')
%h3= t('admin.reports.reported_by')
= render 'authorize_follows/card', account: @report.account, admin: true
= render 'admin/accounts/card', account: @report.account
%p
%strong= t('admin.reports.comment.label')
\:
= simple_format(@report.comment.presence || t('admin.reports.comment.none'))
%h3= t('admin.reports.comment.label')
= simple_format(@report.comment.presence || t('admin.reports.comment.none'))
- unless @report.statuses.empty?
%hr/
%h3= t('admin.reports.statuses')
= form_for(@form, url: admin_report_reported_statuses_path(@report.id)) do |f|
.batch-form-box
.batch-checkbox-all
@ -46,14 +90,20 @@
%hr/
- if !@report.action_taken?
%div{ style: 'overflow: hidden' }
%div{ style: 'float: right' }
= link_to t('admin.reports.silence_account'), admin_report_path(@report, outcome: 'silence'), method: :put, class: 'button'
= link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
%div{ style: 'float: left' }
= link_to t('admin.reports.mark_as_resolved'), admin_report_path(@report, outcome: 'resolve'), method: :put, class: 'button'
- elsif !@report.action_taken_by_account.nil?
%p
%strong #{t('admin.reports.action_taken_by')}:
= @report.action_taken_by_account.acct
%h3= t('admin.reports.notes.label')
- if @report_notes.length > 0
.table-wrapper
%table.table
%thead
%tr
%th
%tbody
= render @report_notes
= simple_form_for @report_note, url: admin_report_notes_path do |f|
= render 'shared/error_messages', object: @report_note
= f.input :content
= f.hidden_field :report_id
= f.button :button, t('admin.reports.notes.create'), type: :submit
= f.button :button, t('admin.reports.notes.create_and_resolve'), type: :submit, name: :create_and_resolve