Feature: Improve reports ui (#7032)
* Further improvements to Reports UI - Clean up notes display - Clean up add new note form - Simplify controller - Allow reopening a report with a note - Show created at date for reports - Fix report details table formatting * Show history of report using Admin::ActionLog beneath the report * Fix incorrect log message when reopening a report * Implement fetching of all ActionLog items that could be related to the report * Ensure adding a report_note updates the report's updated_at * Limit Report History to actions that happened between the report being created and the report being resolved * Fix linting issues * Improve report history builder Thanks @gargron for the improvementsmain
parent
45c9f16f71
commit
d9b62e34da
|
@ -8,19 +8,26 @@ module Admin
|
||||||
authorize ReportNote, :create?
|
authorize ReportNote, :create?
|
||||||
|
|
||||||
@report_note = current_account.report_notes.new(resource_params)
|
@report_note = current_account.report_notes.new(resource_params)
|
||||||
|
@report = @report_note.report
|
||||||
|
|
||||||
if @report_note.save
|
if @report_note.save
|
||||||
if params[:create_and_resolve]
|
if params[:create_and_resolve]
|
||||||
@report_note.report.update!(action_taken: true, action_taken_by_account_id: current_account.id)
|
@report.resolve!(current_account)
|
||||||
log_action :resolve, @report_note.report
|
log_action :resolve, @report
|
||||||
|
|
||||||
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
|
redirect_to admin_reports_path, notice: I18n.t('admin.reports.resolved_msg')
|
||||||
else
|
return
|
||||||
redirect_to admin_report_path(@report_note.report_id), notice: I18n.t('admin.report_notes.created_msg')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if params[:create_and_unresolve]
|
||||||
|
@report.unresolve!
|
||||||
|
log_action :reopen, @report
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to admin_report_path(@report), notice: I18n.t('admin.report_notes.created_msg')
|
||||||
else
|
else
|
||||||
@report = @report_note.report
|
|
||||||
@report_notes = @report.notes.latest
|
@report_notes = @report.notes.latest
|
||||||
|
@report_history = @report.history
|
||||||
@form = Form::StatusBatch.new
|
@form = Form::StatusBatch.new
|
||||||
|
|
||||||
render template: 'admin/reports/show'
|
render template: 'admin/reports/show'
|
||||||
|
|
|
@ -13,6 +13,7 @@ module Admin
|
||||||
authorize @report, :show?
|
authorize @report, :show?
|
||||||
@report_note = @report.notes.new
|
@report_note = @report.notes.new
|
||||||
@report_notes = @report.notes.latest
|
@report_notes = @report.notes.latest
|
||||||
|
@report_history = @report.history
|
||||||
@form = Form::StatusBatch.new
|
@form = Form::StatusBatch.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,36 +39,33 @@ module Admin
|
||||||
@report.update!(assigned_account_id: nil)
|
@report.update!(assigned_account_id: nil)
|
||||||
log_action :unassigned, @report
|
log_action :unassigned, @report
|
||||||
when 'reopen'
|
when 'reopen'
|
||||||
@report.update!(action_taken: false, action_taken_by_account_id: nil)
|
@report.unresolve!
|
||||||
log_action :reopen, @report
|
log_action :reopen, @report
|
||||||
when 'resolve'
|
when 'resolve'
|
||||||
@report.update!(action_taken_by_current_attributes)
|
@report.resolve!(current_account)
|
||||||
log_action :resolve, @report
|
log_action :resolve, @report
|
||||||
when 'suspend'
|
when 'suspend'
|
||||||
Admin::SuspensionWorker.perform_async(@report.target_account.id)
|
Admin::SuspensionWorker.perform_async(@report.target_account.id)
|
||||||
|
|
||||||
log_action :resolve, @report
|
log_action :resolve, @report
|
||||||
log_action :suspend, @report.target_account
|
log_action :suspend, @report.target_account
|
||||||
|
|
||||||
resolve_all_target_account_reports
|
resolve_all_target_account_reports
|
||||||
@report.reload
|
|
||||||
when 'silence'
|
when 'silence'
|
||||||
@report.target_account.update!(silenced: true)
|
@report.target_account.update!(silenced: true)
|
||||||
|
|
||||||
log_action :resolve, @report
|
log_action :resolve, @report
|
||||||
log_action :silence, @report.target_account
|
log_action :silence, @report.target_account
|
||||||
|
|
||||||
resolve_all_target_account_reports
|
resolve_all_target_account_reports
|
||||||
@report.reload
|
|
||||||
else
|
else
|
||||||
raise ActiveRecord::RecordNotFound
|
raise ActiveRecord::RecordNotFound
|
||||||
end
|
end
|
||||||
end
|
@report.reload
|
||||||
|
|
||||||
def action_taken_by_current_attributes
|
|
||||||
{ action_taken: true, action_taken_by_account_id: current_account.id }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_all_target_account_reports
|
def resolve_all_target_account_reports
|
||||||
unresolved_reports_for_target_account.update_all(
|
unresolved_reports_for_target_account.update_all(action_taken: true, action_taken_by_account_id: current_account.id)
|
||||||
action_taken_by_current_attributes
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def unresolved_reports_for_target_account
|
def unresolved_reports_for_target_account
|
||||||
|
|
|
@ -145,6 +145,11 @@
|
||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-bottom: 1px solid $ui-base-color;
|
border-bottom: 1px solid $ui-base-color;
|
||||||
|
|
||||||
|
&.section-break {
|
||||||
|
margin: 30px 0;
|
||||||
|
border-bottom: 2px solid $ui-base-lighter-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.muted-hint {
|
.muted-hint {
|
||||||
|
@ -330,6 +335,36 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.report-note__comment {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-note__form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.report-note__textarea {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 0;
|
||||||
|
padding: 7px 4px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: $ui-base-color;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
outline: 0;
|
||||||
|
font-family: inherit;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-note__buttons {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-note__button {
|
||||||
|
margin: 0 0 5px 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.batch-form-box {
|
.batch-form-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
|
@ -39,4 +39,50 @@ class Report < ApplicationRecord
|
||||||
def media_attachments
|
def media_attachments
|
||||||
MediaAttachment.where(status_id: status_ids)
|
MediaAttachment.where(status_id: status_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assign_to_self!(current_account)
|
||||||
|
update!(assigned_account_id: current_account.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unassign!
|
||||||
|
update!(assigned_account_id: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve!(acting_account)
|
||||||
|
update!(action_taken: true, action_taken_by_account_id: acting_account.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unresolve!
|
||||||
|
update!(action_taken: false, action_taken_by_account_id: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def unresolved?
|
||||||
|
!action_taken?
|
||||||
|
end
|
||||||
|
|
||||||
|
def history
|
||||||
|
time_range = created_at..updated_at
|
||||||
|
|
||||||
|
sql = [
|
||||||
|
Admin::ActionLog.where(
|
||||||
|
target_type: 'Report',
|
||||||
|
target_id: id,
|
||||||
|
created_at: time_range
|
||||||
|
).unscope(:order),
|
||||||
|
|
||||||
|
Admin::ActionLog.where(
|
||||||
|
target_type: 'Account',
|
||||||
|
target_id: target_account_id,
|
||||||
|
created_at: time_range
|
||||||
|
).unscope(:order),
|
||||||
|
|
||||||
|
Admin::ActionLog.where(
|
||||||
|
target_type: 'Status',
|
||||||
|
target_id: status_ids,
|
||||||
|
created_at: time_range
|
||||||
|
).unscope(:order),
|
||||||
|
].map { |query| "(#{query.to_sql})" }.join(' UNION ALL ')
|
||||||
|
|
||||||
|
Admin::ActionLog.from("(#{sql}) AS admin_action_logs")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
class ReportNote < ApplicationRecord
|
class ReportNote < ApplicationRecord
|
||||||
belongs_to :account
|
belongs_to :account
|
||||||
belongs_to :report, inverse_of: :notes
|
belongs_to :report, inverse_of: :notes, touch: true
|
||||||
|
|
||||||
scope :latest, -> { reorder('created_at ASC') }
|
scope :latest, -> { reorder('created_at ASC') }
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
%tr
|
%li
|
||||||
%td
|
%h4
|
||||||
%p
|
= report_note.account.acct
|
||||||
%strong= report_note.account.acct
|
%div{ style: 'float: right' }
|
||||||
on
|
|
||||||
%time.formatted{ datetime: report_note.created_at.iso8601, title: l(report_note.created_at) }
|
%time.formatted{ datetime: report_note.created_at.iso8601, title: l(report_note.created_at) }
|
||||||
= 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)
|
= table_link_to 'trash', t('admin.reports.notes.delete'), admin_report_note_path(report_note), method: :delete if can?(:destroy, report_note)
|
||||||
%br/
|
%div{ class: 'report-note__comment' }
|
||||||
%br/
|
|
||||||
= simple_format(h(report_note.content))
|
= simple_format(h(report_note.content))
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
= t('admin.reports.report', id: @report.id)
|
= t('admin.reports.report', id: @report.id)
|
||||||
|
|
||||||
%div{ style: 'overflow: hidden; margin-bottom: 20px' }
|
%div{ style: 'overflow: hidden; margin-bottom: 20px' }
|
||||||
- if !@report.action_taken?
|
- if @report.unresolved?
|
||||||
%div{ style: 'float: right' }
|
%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.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'
|
= link_to t('admin.reports.suspend_account'), admin_report_path(@report, outcome: 'suspend'), method: :put, class: 'button'
|
||||||
|
@ -17,22 +17,29 @@
|
||||||
.table-wrapper
|
.table-wrapper
|
||||||
%table.table.inline-table
|
%table.table.inline-table
|
||||||
%tbody
|
%tbody
|
||||||
|
%tr
|
||||||
|
%th= t('admin.reports.created_at')
|
||||||
|
%td{colspan: 2}
|
||||||
|
%time.formatted{ datetime: @report.created_at.iso8601 }
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.reports.updated_at')
|
%th= t('admin.reports.updated_at')
|
||||||
%td{colspan: 2}
|
%td{colspan: 2}
|
||||||
%time.formatted{ datetime: @report.updated_at.iso8601 }
|
%time.formatted{ datetime: @report.updated_at.iso8601 }
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.reports.status')
|
%th= t('admin.reports.status')
|
||||||
%td{colspan: 2}
|
%td
|
||||||
- if @report.action_taken?
|
- if @report.action_taken?
|
||||||
= t('admin.reports.resolved')
|
= t('admin.reports.resolved')
|
||||||
= table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
|
|
||||||
- else
|
- else
|
||||||
= t('admin.reports.unresolved')
|
= t('admin.reports.unresolved')
|
||||||
|
%td{style: "text-align: right; overflow: hidden;"}
|
||||||
|
- if @report.action_taken?
|
||||||
|
= table_link_to 'envelope-open', t('admin.reports.reopen'), admin_report_path(@report, outcome: 'reopen'), method: :put
|
||||||
- if !@report.action_taken_by_account.nil?
|
- if !@report.action_taken_by_account.nil?
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.reports.action_taken_by')
|
%th= t('admin.reports.action_taken_by')
|
||||||
%td= @report.action_taken_by_account.acct
|
%td{colspan: 2}
|
||||||
|
= @report.action_taken_by_account.acct
|
||||||
- else
|
- else
|
||||||
%tr
|
%tr
|
||||||
%th= t('admin.reports.assigned')
|
%th= t('admin.reports.assigned')
|
||||||
|
@ -47,6 +54,8 @@
|
||||||
- if !@report.assigned_account.nil?
|
- if !@report.assigned_account.nil?
|
||||||
= table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put
|
= table_link_to 'trash', t('admin.reports.unassign'), admin_report_path(@report, outcome: 'unassign'), method: :put
|
||||||
|
|
||||||
|
%hr{ class: "section-break"}/
|
||||||
|
|
||||||
.report-accounts
|
.report-accounts
|
||||||
.report-accounts__item
|
.report-accounts__item
|
||||||
%h3= t('admin.reports.reported_account')
|
%h3= t('admin.reports.reported_account')
|
||||||
|
@ -88,22 +97,28 @@
|
||||||
= link_to admin_report_reported_status_path(@report, status), method: :delete, class: 'icon-button trash-button', title: t('admin.reports.delete'), data: { confirm: t('admin.reports.are_you_sure') }, remote: true do
|
= link_to admin_report_reported_status_path(@report, status), method: :delete, class: 'icon-button trash-button', title: t('admin.reports.delete'), data: { confirm: t('admin.reports.are_you_sure') }, remote: true do
|
||||||
= fa_icon 'trash'
|
= fa_icon 'trash'
|
||||||
|
|
||||||
%hr/
|
%hr{ class: "section-break"}/
|
||||||
|
|
||||||
%h3= t('admin.reports.notes.label')
|
%h3= t('admin.reports.notes.label')
|
||||||
|
|
||||||
- if @report_notes.length > 0
|
- if @report_notes.length > 0
|
||||||
.table-wrapper
|
%ul
|
||||||
%table.table
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th
|
|
||||||
%tbody
|
|
||||||
= render @report_notes
|
= render @report_notes
|
||||||
|
|
||||||
= simple_form_for @report_note, url: admin_report_notes_path do |f|
|
%h4= t('admin.reports.notes.new_label')
|
||||||
|
= form_for @report_note, url: admin_report_notes_path, html: { class: 'report-note__form' } do |f|
|
||||||
= render 'shared/error_messages', object: @report_note
|
= render 'shared/error_messages', object: @report_note
|
||||||
= f.input :content
|
= f.text_area :content, placeholder: t('admin.reports.notes.placeholder'), rows: 6, class: 'report-note__textarea'
|
||||||
= f.hidden_field :report_id
|
= f.hidden_field :report_id
|
||||||
= f.button :button, t('admin.reports.notes.create'), type: :submit
|
%div{ class: 'report-note__buttons' }
|
||||||
= f.button :button, t('admin.reports.notes.create_and_resolve'), type: :submit, name: :create_and_resolve
|
- if @report.unresolved?
|
||||||
|
= f.submit t('admin.reports.notes.create_and_resolve'), name: :create_and_resolve, class: 'button report-note__button'
|
||||||
|
- else
|
||||||
|
= f.submit t('admin.reports.notes.create_and_unresolve'), name: :create_and_unresolve, class: 'button report-note__button'
|
||||||
|
= f.submit t('admin.reports.notes.create'), class: 'button report-note__button'
|
||||||
|
|
||||||
|
- if @report_history.length > 0
|
||||||
|
%h3= t('admin.reports.history')
|
||||||
|
|
||||||
|
%ul
|
||||||
|
= render @report_history
|
||||||
|
|
|
@ -256,8 +256,8 @@ en:
|
||||||
title: Filter
|
title: Filter
|
||||||
title: Invites
|
title: Invites
|
||||||
report_notes:
|
report_notes:
|
||||||
created_msg: Moderation note successfully created!
|
created_msg: Report note successfully created!
|
||||||
destroyed_msg: Moderation note successfully destroyed!
|
destroyed_msg: Report note successfully deleted!
|
||||||
reports:
|
reports:
|
||||||
action_taken_by: Action taken by
|
action_taken_by: Action taken by
|
||||||
are_you_sure: Are you sure?
|
are_you_sure: Are you sure?
|
||||||
|
@ -266,15 +266,20 @@ en:
|
||||||
comment:
|
comment:
|
||||||
label: Report Comment
|
label: Report Comment
|
||||||
none: None
|
none: None
|
||||||
|
created_at: Reported
|
||||||
delete: Delete
|
delete: Delete
|
||||||
|
history: Moderation History
|
||||||
id: ID
|
id: ID
|
||||||
mark_as_resolved: Mark as resolved
|
mark_as_resolved: Mark as resolved
|
||||||
mark_as_unresolved: Mark as unresolved
|
mark_as_unresolved: Mark as unresolved
|
||||||
notes:
|
notes:
|
||||||
create: Add Note
|
create: Add Note
|
||||||
create_and_resolve: Resolve with Note
|
create_and_resolve: Resolve with Note
|
||||||
|
create_and_unresolve: Reopen with Note
|
||||||
delete: Delete
|
delete: Delete
|
||||||
label: Notes
|
label: Moderator Notes
|
||||||
|
new_label: Add Moderator Note
|
||||||
|
placeholder: Describe what actions have been taken, or any other updates to this report…
|
||||||
nsfw:
|
nsfw:
|
||||||
'false': Unhide media attachments
|
'false': Unhide media attachments
|
||||||
'true': Hide media attachments
|
'true': Hide media attachments
|
||||||
|
|
Loading…
Reference in New Issue