Skip to content

Commit

Permalink
Redesign admin accounts index (mastodon#9340)
Browse files Browse the repository at this point in the history
* Improve overview of accounts in admin UI

- Display suspended status, role, last activity and IP prominently
- Default to showing local accounts
- Default to not showing suspended accounts

* Remove unused strings

* Fix tests

* Allow filtering accounts by IP mask
  • Loading branch information
Gargron authored and hiyuki2578 committed Oct 2, 2019
1 parent 53c2174 commit 788a8e4
Show file tree
Hide file tree
Showing 56 changed files with 47 additions and 266 deletions.
2 changes: 1 addition & 1 deletion app/controllers/admin/accounts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def filter_params
:local,
:remote,
:by_domain,
:active,
:silenced,
:alphabetic,
:suspended,
:username,
:display_name,
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/admin/account_moderation_notes_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def admin_account_inline_link_to(account)

def name_tag_classes(account, inline = false)
classes = [inline ? 'inline-name-tag' : 'name-tag']
classes << 'suspended' if account.suspended?
classes << 'suspended' if account.suspended? || (account.local? && account.user.nil?)
classes.join(' ')
end
end
2 changes: 1 addition & 1 deletion app/helpers/admin/filter_helper.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Admin::FilterHelper
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended alphabetic username display_name email ip staff).freeze
ACCOUNT_FILTERS = %i(local remote by_domain active silenced suspended username display_name email ip staff).freeze
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
INVITE_FILTER = %i(available expired).freeze
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
Expand Down
8 changes: 5 additions & 3 deletions app/helpers/stream_entries_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ def account_action_button(account)
end
end

def account_badge(account)
def account_badge(account, all: false)
if account.bot?
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
elsif Setting.show_staff_badge && account.user_staff?
elsif (Setting.show_staff_badge && account.user_staff?) || all
content_tag(:div, class: 'roles') do
if account.user_admin?
if all && !account.user_staff?
content_tag(:div, t('admin.accounts.roles.user'), class: 'account-role')
elsif account.user_admin?
content_tag(:div, t('accounts.roles.admin'), class: 'account-role admin')
elsif account.user_moderator?
content_tag(:div, t('accounts.roles.moderator'), class: 'account-role moderator')
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/packs/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function main() {
content.textContent = timeAgoString({
formatMessage: ({ id, defaultMessage }, values) => (new IntlMessageFormat(messages[id] || defaultMessage, locale)).format(values),
formatDate: (date, options) => (new Intl.DateTimeFormat(locale, options)).format(date),
}, datetime, now, datetime.getFullYear());
}, datetime, now, now.getFullYear());
});

const reactComponents = document.querySelectorAll('[data-component]');
Expand Down
1 change: 1 addition & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class Account < ApplicationRecord
scope :suspended, -> { where(suspended: true) }
scope :without_suspended, -> { where(suspended: false) }
scope :recent, -> { reorder(id: :desc) }
scope :bots, -> { where(actor_type: %w(Application Service)) }
scope :alphabetic, -> { order(domain: :asc, username: :asc) }
scope :by_domain_accounts, -> { group(:domain).select(:domain, 'COUNT(*) AS accounts_count').order('accounts_count desc') }
scope :matches_username, ->(value) { where(arel_table[:username].matches("#{value}%")) }
Expand Down
23 changes: 12 additions & 11 deletions app/models/account_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@ class AccountFilter

def initialize(params)
@params = params
set_defaults!
end

def results
scope = Account.recent
scope = Account.recent.includes(:user)

params.each do |key, value|
scope.merge!(scope_for(key, value)) if value.present?
scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
end

scope
end

private

def set_defaults!
params['local'] = '1' if params['remote'].blank?
params['active'] = '1' if params['suspended'].blank? && params['silenced'].blank?
end

def scope_for(key, value)
case key.to_s
when 'local'
Expand All @@ -27,10 +33,10 @@ def scope_for(key, value)
Account.remote
when 'by_domain'
Account.where(domain: value)
when 'active'
Account.without_suspended
when 'silenced'
Account.silenced
when 'alphabetic'
Account.reorder(nil).alphabetic
when 'suspended'
Account.suspended
when 'username'
Expand All @@ -40,11 +46,7 @@ def scope_for(key, value)
when 'email'
accounts_with_users.merge User.matches_email(value)
when 'ip'
if valid_ip?(value)
accounts_with_users.merge User.with_recent_ip_address(value)
else
Account.default_scoped
end
valid_ip?(value) ? accounts_with_users.where('users.current_sign_in_ip <<= ?', value) : Account.none
when 'staff'
accounts_with_users.merge User.staff
else
Expand All @@ -57,8 +59,7 @@ def accounts_with_users
end

def valid_ip?(value)
IPAddr.new(value)
true
IPAddr.new(value) && true
rescue IPAddr::InvalidAddressError
false
end
Expand Down
1 change: 0 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ class User < ApplicationRecord
scope :inactive, -> { where(arel_table[:current_sign_in_at].lt(ACTIVE_DURATION.ago)) }
scope :active, -> { confirmed.where(arel_table[:current_sign_in_at].gteq(ACTIVE_DURATION.ago)).joins(:account).where(accounts: { suspended: false }) }
scope :matches_email, ->(value) { where(arel_table[:email].matches("#{value}%")) }
scope :with_recent_ip_address, ->(value) { where(arel_table[:current_sign_in_ip].eq(value).or(arel_table[:last_sign_in_ip].eq(value))) }

before_validation :sanitize_languages

Expand Down
23 changes: 10 additions & 13 deletions app/views/admin/accounts/_account.html.haml
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
%tr
%td.username
= account.username
%td
- unless account.local?
= link_to account.domain, admin_accounts_path(by_domain: account.domain)
= admin_account_link_to(account)
%td
- if account.local?
- if account.user.nil?
= t("admin.accounts.moderation.suspended")
- else
= t("admin.accounts.roles.#{account.user.role}")
%div{ style: 'margin: -2px 0' }= account_badge(account, all: true)
%td
- if account.user_current_sign_in_ip
%samp= account.user_current_sign_in_ip
- else
= account.protocol.humanize
\-
%td
= table_link_to 'circle', t('admin.accounts.web'), web_path("accounts/#{account.id}")
= table_link_to 'globe', t('admin.accounts.public'), TagManager.instance.url_for(account)
= table_link_to 'pencil', t('admin.accounts.edit'), admin_account_path(account.id)
- if account.user_current_sign_in_at
%time.time-ago{ datetime: account.user_current_sign_in_at.iso8601, title: l(account.user_current_sign_in_at) }= l account.user_current_sign_in_at
- else
\-
38 changes: 8 additions & 30 deletions app/views/admin/accounts/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,19 @@
.filter-subset
%strong= t('admin.accounts.location.title')
%ul
%li= filter_link_to t('admin.accounts.location.all'), local: nil, remote: nil
%li
- if selected? local: '1', remote: nil
= filter_link_to t('admin.accounts.location.local'), {local: nil, remote: nil}, {local: '1', remote: nil}
- else
= filter_link_to t('admin.accounts.location.local'), local: '1', remote: nil
%li
- if selected? remote: '1', local: nil
= filter_link_to t('admin.accounts.location.remote'), {remote: nil, local: nil}, {remote: '1', local: nil}
- else
= filter_link_to t('admin.accounts.location.remote'), remote: '1', local: nil
%li= filter_link_to t('admin.accounts.location.local'), remote: nil
%li= filter_link_to t('admin.accounts.location.remote'), remote: '1'
.filter-subset
%strong= t('admin.accounts.moderation.title')
%ul
%li= filter_link_to t('admin.accounts.moderation.all'), silenced: nil, suspended: nil
%li
- if selected? silenced: '1'
= filter_link_to t('admin.accounts.moderation.silenced'), {silenced: nil}, {silenced: '1'}
- else
= filter_link_to t('admin.accounts.moderation.silenced'), silenced: '1'
%li
- if selected? suspended: '1'
= filter_link_to t('admin.accounts.moderation.suspended'), {suspended: nil}, {suspended: '1'}
- else
= filter_link_to t('admin.accounts.moderation.suspended'), suspended: '1'
%li= filter_link_to t('admin.accounts.moderation.active'), silenced: nil, suspended: nil
%li= filter_link_to t('admin.accounts.moderation.silenced'), silenced: '1', suspended: nil
%li= filter_link_to t('admin.accounts.moderation.suspended'), suspended: '1', silenced: nil
.filter-subset
%strong= t('admin.accounts.role')
%ul
%li= filter_link_to t('admin.accounts.moderation.all'), staff: nil
%li= filter_link_to t('admin.accounts.roles.staff'), staff: '1'
.filter-subset
%strong= t('admin.accounts.order.title')
%ul
%li= filter_link_to t('admin.accounts.order.most_recent'), alphabetic: nil
%li= filter_link_to t('admin.accounts.order.alphabetic'), alphabetic: '1'

= form_tag admin_accounts_url, method: 'GET', class: 'simple_form' do
.fields-group
Expand All @@ -60,9 +38,9 @@
%thead
%tr
%th= t('admin.accounts.username')
%th= t('admin.accounts.domain')
%th
%th
%th= t('admin.accounts.role')
%th= t('admin.accounts.most_recent_ip')
%th= t('admin.accounts.most_recent_activity')
%tbody
= render @accounts

Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/accounts/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
%time.formatted{ datetime: @account.user_current_sign_in_at.iso8601, title: l(@account.user_current_sign_in_at) }
= l @account.user_current_sign_in_at
- else
Never
\-
- else
%tr
%th= t('admin.accounts.profile_url')
Expand Down
4 changes: 0 additions & 4 deletions config/locales/ar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ ar:
most_recent_ip: أحدث عنوان إيبي
no_limits_imposed: مِن دون حدود مشروطة
not_subscribed: غير مشترك
order:
alphabetic: أبجديًا
most_recent: الأحدث
title: الترتيب
outbox_url: رابط صندوق الصادر
perform_full_suspension: تعطيل
profile_url: رابط الملف الشخصي
Expand Down
4 changes: 0 additions & 4 deletions config/locales/ca.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ ca:
most_recent_ip: IP més recent
no_limits_imposed: Sense límits imposats
not_subscribed: No subscrit
order:
alphabetic: Alfabètic
most_recent: Més recent
title: Ordre
outbox_url: URL de la bústia de sortida
perform_full_suspension: Suspèn
profile_url: URL del perfil
Expand Down
4 changes: 0 additions & 4 deletions config/locales/co.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ co:
most_recent_ip: IP più ricente
no_limits_imposed: Nisuna limita imposta
not_subscribed: Micca abbunatu
order:
alphabetic: Alfabeticu
most_recent: Più ricente
title: Urdine
outbox_url: URL di l’outbox
perform_full_suspension: Suspende
profile_url: URL di u prufile
Expand Down
4 changes: 0 additions & 4 deletions config/locales/cs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ cs:
most_recent_ip: Nejnovější IP
no_limits_imposed: Nejsou nastavena žádná omezení
not_subscribed: Neodebírá
order:
alphabetic: Abecedně
most_recent: Nejnovější
title: Pořadí
outbox_url: URL odchozích zpráv
perform_full_suspension: Suspendovat
profile_url: URL profilu
Expand Down
4 changes: 0 additions & 4 deletions config/locales/cy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,6 @@ cy:
most_recent_ip: IP diweddaraf
no_limits_imposed: Dim terfynau wedi'i gosod
not_subscribed: Heb danysgrifio
order:
alphabetic: Allfabetig
most_recent: Diweddaraf
title: Trefnu
outbox_url: Allflwch URL
perform_full_suspension: Atal
profile_url: URL proffil
Expand Down
4 changes: 0 additions & 4 deletions config/locales/da.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,6 @@ da:
most_recent_activity: Seneste aktivitet
most_recent_ip: Senest IP
not_subscribed: Ikke abonneret
order:
alphabetic: Alfabetisk
most_recent: Seneste
title: Rækkefølge
outbox_url: Link til udgående
perform_full_suspension: Udeluk
profile_url: Link til profil
Expand Down
4 changes: 0 additions & 4 deletions config/locales/de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ de:
most_recent_ip: Letzte IP-Adresse
no_limits_imposed: Keine Limits eingesetzt
not_subscribed: Nicht abonniert
order:
alphabetic: Alphabetisch
most_recent: Neueste
title: Sortierung
outbox_url: Postausgangs-URL
perform_full_suspension: Sperren
profile_url: Profil-URL
Expand Down
4 changes: 0 additions & 4 deletions config/locales/el.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ el:
most_recent_ip: Πιο πρόσφατη IP
no_limits_imposed: Χωρίς όρια
not_subscribed: Άνευ συνδρομής
order:
alphabetic: Αλφαβητικά
most_recent: Πιο πρόσφατα
title: Ταξινόμηση
outbox_url: URL εξερχομένων
perform_full_suspension: Κάνε πλήρη αναστολή
profile_url: URL προφίλ
Expand Down
4 changes: 0 additions & 4 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ en:
most_recent_ip: Most recent IP
no_limits_imposed: No limits imposed
not_subscribed: Not subscribed
order:
alphabetic: Alphabetic
most_recent: Most recent
title: Order
outbox_url: Outbox URL
perform_full_suspension: Suspend
profile_url: Profile URL
Expand Down
4 changes: 0 additions & 4 deletions config/locales/eo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,6 @@ eo:
most_recent_activity: Lasta ago
most_recent_ip: Lasta IP
not_subscribed: Ne abonita
order:
alphabetic: Laŭalfabete
most_recent: Plej lastatempa
title: Ordo
outbox_url: Elira URL
perform_full_suspension: Tute haltigi
profile_url: Profila URL
Expand Down
4 changes: 0 additions & 4 deletions config/locales/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ es:
most_recent_ip: IP más reciente
no_limits_imposed: Sin límites impuestos
not_subscribed: No se está suscrito
order:
alphabetic: Alfabético
most_recent: Más reciente
title: Orden
outbox_url: URL de bandeja de salida
perform_full_suspension: Suspender
profile_url: URL del perfil
Expand Down
4 changes: 0 additions & 4 deletions config/locales/eu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ eu:
most_recent_ip: Azken IP-a
no_limits_imposed: Ez da mugarik ezarri
not_subscribed: Harpidetu gabe
order:
alphabetic: Alfabetikoa
most_recent: Azkena
title: Ordena
outbox_url: Irteera ontziaren URL-a
perform_full_suspension: Kanporatu
profile_url: Profilaren URL-a
Expand Down
4 changes: 0 additions & 4 deletions config/locales/fa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ fa:
most_recent_ip: آخرین IP ها
no_limits_imposed: بدون محدودیت
not_subscribed: عضو نیست
order:
alphabetic: الفبایی
most_recent: تازه‌ترین‌ها
title: ترتیب
outbox_url: نشانی صندوق خروجی
perform_full_suspension: تعلیق
profile_url: نشانی نمایه
Expand Down
4 changes: 0 additions & 4 deletions config/locales/fi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,6 @@ fi:
most_recent_activity: Viimeisin toiminta
most_recent_ip: Viimeisin IP
not_subscribed: Ei tilaaja
order:
alphabetic: Aakkosjärjestys
most_recent: Uusin
title: Järjestys
outbox_url: Lähtevän postilaatikon osoite
perform_full_suspension: Siirrä kokonaan jäähylle
profile_url: Profiilin osoite
Expand Down
4 changes: 0 additions & 4 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ fr:
most_recent_ip: Adresse IP la plus récente
no_limits_imposed: Aucune limite imposée
not_subscribed: Non abonné
order:
alphabetic: Alphabétique
most_recent: Plus récent
title: Tri
outbox_url: URL de sortie
perform_full_suspension: Suspendre
profile_url: URL du profil
Expand Down
Loading

0 comments on commit 788a8e4

Please sign in to comment.