Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve admin page #4121

Merged
merged 4 commits into from
Jul 18, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions app/controllers/admin/reported_statuses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@ class ReportedStatusesController < BaseController
include Authorization

before_action :set_report
before_action :set_status
before_action :set_status, only: [:update, :destroy]

def create
@form = Form::StatusBatch.new(form_status_batch_params)
unless @form.save
flash[:alert] = t('admin.statuses.failed_to_execute')
end
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save

redirect_to admin_report_path(@report)
end

def update
@status.update(status_params)
Expand All @@ -15,7 +23,7 @@ def update
def destroy
authorize @status, :destroy?
RemovalWorker.perform_async(@status.id)
redirect_to admin_report_path(@report)
render json: @status
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end

private
Expand All @@ -24,6 +32,10 @@ def status_params
params.require(:status).permit(:sensitive)
end

def form_status_batch_params
params.require(:form_status_batch).permit(:action, status_ids: [])
end

def set_report
@report = Report.find(params[:report_id])
end
Expand Down
4 changes: 3 additions & 1 deletion app/controllers/admin/reports_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ def index
@reports = filtered_reports.page(params[:page])
end

def show; end
def show
@form = Form::StatusBatch.new
end

def update
process_report
Expand Down
70 changes: 70 additions & 0 deletions app/controllers/admin/statuses_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

module Admin
class StatusesController < BaseController
include Authorization

helper_method :current_params

before_action :set_account
before_action :set_status, only: [:update, :destroy]

PAR_PAGE = 20

def index
@statuses = @account.statuses
if params[:media]
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
@statuses.merge!(Status.where(id: account_media_status_ids))
end
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PAR_PAGE)

@form = Form::StatusBatch.new
end

def create
@form = Form::StatusBatch.new(form_status_batch_params)
unless @form.save
flash[:alert] = t('admin.statuses.failed_to_execute')
end
redirect_to admin_account_statuses_path(@account.id, current_params)
end
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save


def update
@status.update(status_params)
redirect_to admin_account_statuses_path(@account.id, current_params)
end

def destroy
authorize @status, :destroy?
RemovalWorker.perform_async(@status.id)
render json: @status
end

private

def status_params
params.require(:status).permit(:sensitive)
end

def form_status_batch_params
params.require(:form_status_batch).permit(:action, status_ids: [])
end

def set_status
@status = @account.statuses.find(params[:id])
end

def set_account
@account = Account.find(params[:account_id])
end

def current_params
page = (params[:page] || 1).to_i
{
media: params[:media],
page: page > 1 && page,
}.select { |_, value| value.present? }
end
end
end
40 changes: 40 additions & 0 deletions app/javascript/packs/admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { delegate } from 'rails-ujs';

function handleDeleteStatus(event) {
const [data] = event.detail;
const element = document.querySelector(`[data-id="${data.id}"]`);
if (element) {
element.parentNode.removeChild(element);
}
}

[].forEach.call(document.querySelectorAll('.trash-button'), (content) => {
content.addEventListener('ajax:success', handleDeleteStatus);
});

const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';

delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
[].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => {
content.checked = target.checked;
});
});

delegate(document, batchCheckboxClassName, 'change', () => {
const checkAllElement = document.querySelector('#batch_checkbox_all');
if (checkAllElement) {
checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
}
});

delegate(document, '.media-spoiler-show-button', 'click', () => {
[].forEach.call(document.querySelectorAll('.activity-stream .media-spoiler-wrapper'), (content) => {
content.classList.add('media-spoiler-wrapper__visible');
});
});

delegate(document, '.media-spoiler-hide-button', 'click', () => {
[].forEach.call(document.querySelectorAll('.activity-stream .media-spoiler-wrapper'), (content) => {
content.classList.remove('media-spoiler-wrapper__visible');
});
});
32 changes: 30 additions & 2 deletions app/javascript/styles/admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@
}
}

.report-status {
.report-status,
.account-status {
display: flex;
margin-bottom: 10px;

Expand All @@ -263,7 +264,8 @@
}
}

.report-status__actions {
.report-status__actions,
.account-status__actions {
flex: 0 0 auto;
display: flex;
flex-direction: column;
Expand All @@ -275,3 +277,29 @@
margin-bottom: 10px;
}
}

.batch-form-box {
display: flex;
margin-top: 5px;
}

.batch-checkbox,
.batch-checkbox-all {
display: flex;
align-items: center;
margin-right: 5px;
}

.back-link {
margin-bottom: 10px;
font-size: 14px;

a {
color: $classic-highlight-color;
text-decoration: none;

&:hover {
text-decoration: underline;
}
}
}
39 changes: 39 additions & 0 deletions app/models/form/status_batch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

class Form::StatusBatch
include ActiveModel::Model

attr_accessor :status_ids, :action

ACTION_TYPE = %w(nsfw_on nsfw_off delete).freeze

def save
case action
when 'nsfw_on', 'nsfw_off'
change_sensitive(action == 'nsfw_on')
when 'delete'
delete_statuses
end
end

private

def change_sensitive(sensitive)
media_attached_status_ids = MediaAttachment.where(status_id: status_ids).pluck(:status_id)
ApplicationRecord.transaction do
Status.where(id: media_attached_status_ids).find_each do |status|
status.update!(sensitive: sensitive)
end
end
true
rescue ActiveRecord::RecordInvalid
false
end

def delete_statuses
Status.where(id: status_ids).find_each do |status|
RemovalWorker.perform_async(status.id)
end
true
end
end
4 changes: 2 additions & 2 deletions app/views/admin/accounts/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@
%td= @account.followers_count
%tr
%th= t('admin.accounts.statuses')
%td= @account.statuses_count
%td= link_to @account.statuses_count, admin_account_statuses_path(@account.id)
%tr
%th= t('admin.accounts.media_attachments')
%td
= @account.media_attachments.count
= link_to @account.media_attachments.count, admin_account_statuses_path(@account.id, { media: true })
= surround '(', ')' do
= number_to_human_size @account.media_attachments.sum('file_file_size')
%tr
Expand Down
37 changes: 27 additions & 10 deletions app/views/admin/reports/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.reports.report', id: @report.id)

Expand All @@ -19,16 +22,30 @@
- unless @report.statuses.empty?
%hr/

- @report.statuses.each do |status|
.report-status
.activity-stream.activity-stream-headless
.entry= render 'stream_entries/simple_status', status: status
.report-status__actions
- unless status.media_attachments.empty?
= link_to admin_report_reported_status_path(@report, status, status: { sensitive: !status.sensitive }), method: :patch, class: 'icon-button nsfw-button', title: t("admin.reports.nsfw.#{!status.sensitive}") do
= fa_icon status.sensitive? ? 'eye' : 'eye-slash'
= 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') } do
= fa_icon 'trash'
= form_for(@form, url: admin_report_reported_statuses_path(@report.id)) do |f|
.filters
.filter-subset
%strong= t('admin.statuses.batch_action')
.batch-form-box
.batch-checkbox-all
= check_box_tag :batch_checkbox_all, nil, false
= f.select :action, Form::StatusBatch::ACTION_TYPE.map{|action| [t("admin.statuses.batch.#{action}"), action]}
= f.submit t('admin.statuses.execute'), data: { confirm: t('admin.reports.are_you_sure') }
.filter-subset
.media-spoiler-show-button.button= t('admin.statuses.media.show')
.media-spoiler-hide-button.button= t('admin.statuses.media.hide')
- @report.statuses.each do |status|
.report-status{ data: { id: status.id } }
.batch-checkbox
= f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id
.activity-stream.activity-stream-headless
.entry= render 'stream_entries/simple_status', status: status
.report-status__actions
- unless status.media_attachments.empty?
= link_to admin_report_reported_status_path(@report, status, status: { sensitive: !status.sensitive }), method: :put, class: 'icon-button nsfw-button', title: t("admin.reports.nsfw.#{!status.sensitive}") do
= fa_icon status.sensitive? ? 'eye' : 'eye-slash'
= 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'

%hr/

Expand Down
48 changes: 48 additions & 0 deletions app/views/admin/statuses/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
- content_for :header_tags do
= javascript_pack_tag 'admin', integrity: true, async: true, crossorigin: 'anonymous'

- content_for :page_title do
= t('admin.statuses.title')

.back-link
= link_to admin_account_path(@account.id) do
%i.fa.fa-chevron-left.fa-fw
= t('admin.statuses.back_to_account')

- if @statuses.empty?
.accounts-grid
= render 'accounts/nothing_here'
- else
= form_for(@form, url: admin_account_statuses_path(@account.id)) do |f|
= hidden_field_tag :page, params[:page]
= hidden_field_tag :media, params[:media]
.filters
.filter-subset
%strong= t('admin.statuses.batch_action')
.batch-form-box
.batch-checkbox-all
= check_box_tag :batch_checkbox_all, nil, false
= f.select :action, Form::StatusBatch::ACTION_TYPE.map{|action| [t("admin.statuses.batch.#{action}"), action]}
= f.submit t('admin.statuses.execute'), data: { confirm: t('admin.reports.are_you_sure') }
.filter-subset
%strong= t('admin.statuses.media.title')
%ul
%li= link_to t('admin.statuses.no_media'), admin_account_statuses_path(@account.id, current_params.merge(media: nil)), class: !params[:media] && 'selected'
%li= link_to t('admin.statuses.with_media'), admin_account_statuses_path(@account.id, current_params.merge(media: true)), class: params[:media] && 'selected'
.filter-subset
.media-spoiler-show-button.button= t('admin.statuses.media.show')
.media-spoiler-hide-button.button= t('admin.statuses.media.hide')
- @statuses.each do |status|
.account-status{ data: { id: status.id } }
.batch-checkbox
= f.check_box :status_ids, { multiple: true, include_hidden: false }, status.id
.activity-stream.activity-stream-headless
.entry= render 'stream_entries/simple_status', status: status
.account-status__actions
- unless status.media_attachments.empty?
= link_to admin_account_status_path(@account.id, status, current_params.merge(status: { sensitive: !status.sensitive })), method: :patch, class: 'icon-button nsfw-button', title: t("admin.reports.nsfw.#{!status.sensitive}") do
= fa_icon status.sensitive? ? 'eye' : 'eye-slash'
= link_to admin_account_status_path(@account.id, 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'

= paginate @statuses
16 changes: 16 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,22 @@ en:
title: Site Privacy Policy
site_title: Site title
title: Site Settings
statuses:
back_to_account: Back to account page
batch:
delete: Delete
nsfw_off: NSFW OFF
nsfw_on: NSFW ON
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NSFW? Isn't it now called 'Content warning' on Mastodon?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Content warning" is a function to hide sentences, and NSFW is a function to hide images. The implemented function is a function to change NSFW.

batch_action: Batch processing
execute: Execute
failed_to_execute: Failed to execute
media:
hide: Hide media
show: Show media
title: Media
no_media: No media
with_media: With media
title: Account statuses
subscriptions:
callback_url: Callback URL
confirmed: Confirmed
Expand Down