Skip to content

Commit ef0d22f

Browse files
mayaehGargron
authored andcommitted
Add search and sort functions to hashtag admin UI (#11829)
* Add search and sort functions to hashtag admin UI * Move scope processing from tags_controller to tag_filter * Fix based on method naming conventions * Fixed not to get 500 errors for invalid requests
1 parent b7420b8 commit ef0d22f

7 files changed

Lines changed: 81 additions & 19 deletions

File tree

app/controllers/admin/tags_controller.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
module Admin
44
class TagsController < BaseController
5-
before_action :set_tags, only: :index
65
before_action :set_tag, except: [:index, :batch, :approve_all, :reject_all]
76
before_action :set_usage_by_domain, except: [:index, :batch, :approve_all, :reject_all]
87
before_action :set_counters, except: [:index, :batch, :approve_all, :reject_all]
98

109
def index
1110
authorize :tag, :index?
1211

12+
@tags = filtered_tags.page(params[:page])
1313
@form = Form::TagBatch.new
1414
end
1515

@@ -48,10 +48,6 @@ def update
4848

4949
private
5050

51-
def set_tags
52-
@tags = filtered_tags.page(params[:page])
53-
end
54-
5551
def set_tag
5652
@tag = Tag.find(params[:id])
5753
end
@@ -73,16 +69,11 @@ def set_counters
7369
end
7470

7571
def filtered_tags
76-
scope = Tag
77-
scope = scope.discoverable if filter_params[:context] == 'directory'
78-
scope = scope.unreviewed if filter_params[:review] == 'unreviewed'
79-
scope = scope.reviewed.order(reviewed_at: :desc) if filter_params[:review] == 'reviewed'
80-
scope = scope.pending_review.order(requested_review_at: :desc) if filter_params[:review] == 'pending_review'
81-
scope.order(max_score: :desc)
72+
TagFilter.new(filter_params).results
8273
end
8374

8475
def filter_params
85-
params.slice(:context, :review, :page).permit(:context, :review, :page)
76+
params.slice(:directory, :reviewed, :unreviewed, :pending_review, :page, :popular, :active, :name).permit(:directory, :reviewed, :unreviewed, :pending_review, :page, :popular, :active, :name)
8677
end
8778

8879
def tag_params

app/helpers/admin/filter_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Admin::FilterHelper
55
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
66
INVITE_FILTER = %i(available expired).freeze
77
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
8-
TAGS_FILTERS = %i(context review).freeze
8+
TAGS_FILTERS = %i(directory reviewed unreviewed pending_review popular active name).freeze
99
INSTANCES_FILTERS = %i(limited by_domain).freeze
1010
FOLLOWERS_FILTERS = %i(relationship status by_domain activity order).freeze
1111

app/models/tag.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class Tag < ApplicationRecord
3939
scope :listable, -> { where(listable: [true, nil]) }
4040
scope :discoverable, -> { listable.joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) }
4141
scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) }
42+
scope :matches_name, ->(value) { where(arel_table[:name].matches("#{value}%")) }
4243

4344
delegate :accounts_count,
4445
:accounts_count=,

app/models/tag_filter.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
class TagFilter
4+
attr_reader :params
5+
6+
def initialize(params)
7+
@params = params
8+
end
9+
10+
def results
11+
scope = Tag.unscoped
12+
13+
params.each do |key, value|
14+
next if key.to_s == 'page'
15+
16+
scope.merge!(scope_for(key, value.to_s.strip)) if value.present?
17+
end
18+
19+
scope.order(id: :desc)
20+
end
21+
22+
private
23+
24+
def scope_for(key, value)
25+
case key.to_s
26+
when 'directory'
27+
Tag.discoverable
28+
when 'reviewed'
29+
Tag.reviewed.order(reviewed_at: :desc)
30+
when 'unreviewed'
31+
Tag.unreviewed
32+
when 'pending_review'
33+
Tag.pending_review.order(requested_review_at: :desc)
34+
when 'popular'
35+
Tag.order('max_score DESC NULLS LAST')
36+
when 'active'
37+
Tag.order('last_status_at DESC NULLS LAST')
38+
when 'name'
39+
Tag.matches_name(value)
40+
else
41+
raise "Unknown filter: #{key}"
42+
end
43+
end
44+
end

app/views/admin/tags/index.html.haml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,36 @@
88
.filter-subset
99
%strong= t('admin.tags.context')
1010
%ul
11-
%li= filter_link_to t('generic.all'), context: nil
12-
%li= filter_link_to t('admin.tags.directory'), context: 'directory'
11+
%li= filter_link_to t('generic.all'), directory: nil
12+
%li= filter_link_to t('admin.tags.directory'), directory: '1'
1313

1414
.filter-subset
1515
%strong= t('admin.tags.review')
1616
%ul
17-
%li= filter_link_to t('generic.all'), review: nil
18-
%li= filter_link_to t('admin.tags.unreviewed'), review: 'unreviewed'
19-
%li= filter_link_to t('admin.tags.reviewed'), review: 'reviewed'
20-
%li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), review: 'pending_review'
17+
%li= filter_link_to t('generic.all'), reviewed: nil, unreviewed: nil, pending_review: nil
18+
%li= filter_link_to t('admin.tags.unreviewed'), unreviewed: '1', reviewed: nil, pending_review: nil
19+
%li= filter_link_to t('admin.tags.reviewed'), reviewed: '1', unreviewed: nil, pending_review: nil
20+
%li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), pending_review: '1', reviewed: nil, unreviewed: nil
21+
22+
.filter-subset
23+
%strong= t('generic.order_by')
24+
%ul
25+
%li= filter_link_to t('admin.tags.most_recent'), popular: nil, active: nil
26+
%li= filter_link_to t('admin.tags.most_popular'), popular: '1', active: nil
27+
%li= filter_link_to t('admin.tags.last_active'), active: '1', popular: nil
28+
29+
= form_tag admin_tags_url, method: 'GET', class: 'simple_form' do
30+
.fields-group
31+
- Admin::FilterHelper::TAGS_FILTERS.each do |key|
32+
= hidden_field_tag key, params[key] if params[key].present?
33+
34+
- %i(name).each do |key|
35+
.input.string.optional
36+
= text_field_tag key, params[key], class: 'string optional', placeholder: I18n.t("admin.tags.#{key}")
37+
38+
.actions
39+
%button= t('admin.accounts.search')
40+
= link_to t('admin.accounts.reset'), admin_tags_path, class: 'button negative'
2141

2242
%hr.spacer/
2343

config/locales/en.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,10 @@ en:
521521
context: Context
522522
directory: In directory
523523
in_directory: "%{count} in directory"
524+
last_active: Last active
525+
most_popular: Most popular
526+
most_recent: Most recent
527+
name: Hashtag
524528
review: Review status
525529
reviewed: Reviewed
526530
title: Hashtags

config/locales/simple_form.en.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ en:
131131
must_be_follower: Block notifications from non-followers
132132
must_be_following: Block notifications from people you don't follow
133133
must_be_following_dm: Block direct messages from people you don't follow
134+
invite:
135+
comment: Comment
134136
invite_request:
135137
text: Why do you want to join?
136138
notification_emails:

0 commit comments

Comments
 (0)