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
This commit is contained in:
		
					parent
					
						
							
								b7420b8643
							
						
					
				
			
			
				commit
				
					
						ef0d22f232
					
				
			
		
					 7 changed files with 81 additions and 19 deletions
				
			
		|  | @ -2,7 +2,6 @@ | ||||||
| 
 | 
 | ||||||
| module Admin | module Admin | ||||||
|   class TagsController < BaseController |   class TagsController < BaseController | ||||||
|     before_action :set_tags, only: :index |  | ||||||
|     before_action :set_tag, except: [:index, :batch, :approve_all, :reject_all] |     before_action :set_tag, except: [:index, :batch, :approve_all, :reject_all] | ||||||
|     before_action :set_usage_by_domain, except: [:index, :batch, :approve_all, :reject_all] |     before_action :set_usage_by_domain, except: [:index, :batch, :approve_all, :reject_all] | ||||||
|     before_action :set_counters, except: [:index, :batch, :approve_all, :reject_all] |     before_action :set_counters, except: [:index, :batch, :approve_all, :reject_all] | ||||||
|  | @ -10,6 +9,7 @@ module Admin | ||||||
|     def index |     def index | ||||||
|       authorize :tag, :index? |       authorize :tag, :index? | ||||||
| 
 | 
 | ||||||
|  |       @tags = filtered_tags.page(params[:page]) | ||||||
|       @form = Form::TagBatch.new |       @form = Form::TagBatch.new | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  | @ -48,10 +48,6 @@ module Admin | ||||||
| 
 | 
 | ||||||
|     private |     private | ||||||
| 
 | 
 | ||||||
|     def set_tags |  | ||||||
|       @tags = filtered_tags.page(params[:page]) |  | ||||||
|     end |  | ||||||
| 
 |  | ||||||
|     def set_tag |     def set_tag | ||||||
|       @tag = Tag.find(params[:id]) |       @tag = Tag.find(params[:id]) | ||||||
|     end |     end | ||||||
|  | @ -73,16 +69,11 @@ module Admin | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def filtered_tags |     def filtered_tags | ||||||
|       scope = Tag |       TagFilter.new(filter_params).results | ||||||
|       scope = scope.discoverable if filter_params[:context] == 'directory' |  | ||||||
|       scope = scope.unreviewed if filter_params[:review] == 'unreviewed' |  | ||||||
|       scope = scope.reviewed.order(reviewed_at: :desc) if filter_params[:review] == 'reviewed' |  | ||||||
|       scope = scope.pending_review.order(requested_review_at: :desc) if filter_params[:review] == 'pending_review' |  | ||||||
|       scope.order(max_score: :desc) |  | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def filter_params |     def filter_params | ||||||
|       params.slice(:context, :review, :page).permit(:context, :review, :page) |       params.slice(:directory, :reviewed, :unreviewed, :pending_review, :page, :popular, :active, :name).permit(:directory, :reviewed, :unreviewed, :pending_review, :page, :popular, :active, :name) | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|     def tag_params |     def tag_params | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ module Admin::FilterHelper | ||||||
|   REPORT_FILTERS       = %i(resolved account_id target_account_id).freeze |   REPORT_FILTERS       = %i(resolved account_id target_account_id).freeze | ||||||
|   INVITE_FILTER        = %i(available expired).freeze |   INVITE_FILTER        = %i(available expired).freeze | ||||||
|   CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze |   CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze | ||||||
|   TAGS_FILTERS         = %i(context review).freeze |   TAGS_FILTERS         = %i(directory reviewed unreviewed pending_review popular active name).freeze | ||||||
|   INSTANCES_FILTERS    = %i(limited by_domain).freeze |   INSTANCES_FILTERS    = %i(limited by_domain).freeze | ||||||
|   FOLLOWERS_FILTERS    = %i(relationship status by_domain activity order).freeze |   FOLLOWERS_FILTERS    = %i(relationship status by_domain activity order).freeze | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ class Tag < ApplicationRecord | ||||||
|   scope :listable, -> { where(listable: [true, nil]) } |   scope :listable, -> { where(listable: [true, nil]) } | ||||||
|   scope :discoverable, -> { listable.joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) } |   scope :discoverable, -> { listable.joins(:account_tag_stat).where(AccountTagStat.arel_table[:accounts_count].gt(0)).order(Arel.sql('account_tag_stats.accounts_count desc')) } | ||||||
|   scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) } |   scope :most_used, ->(account) { joins(:statuses).where(statuses: { account: account }).group(:id).order(Arel.sql('count(*) desc')) } | ||||||
|  |   scope :matches_name, ->(value) { where(arel_table[:name].matches("#{value}%")) } | ||||||
| 
 | 
 | ||||||
|   delegate :accounts_count, |   delegate :accounts_count, | ||||||
|            :accounts_count=, |            :accounts_count=, | ||||||
|  |  | ||||||
							
								
								
									
										44
									
								
								app/models/tag_filter.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								app/models/tag_filter.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class TagFilter | ||||||
|  |   attr_reader :params | ||||||
|  | 
 | ||||||
|  |   def initialize(params) | ||||||
|  |     @params = params | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def results | ||||||
|  |     scope = Tag.unscoped | ||||||
|  | 
 | ||||||
|  |     params.each do |key, value| | ||||||
|  |       next if key.to_s == 'page' | ||||||
|  | 
 | ||||||
|  |       scope.merge!(scope_for(key, value.to_s.strip)) if value.present? | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     scope.order(id: :desc) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def scope_for(key, value) | ||||||
|  |     case key.to_s | ||||||
|  |     when 'directory' | ||||||
|  |       Tag.discoverable | ||||||
|  |     when 'reviewed' | ||||||
|  |       Tag.reviewed.order(reviewed_at: :desc) | ||||||
|  |     when 'unreviewed' | ||||||
|  |       Tag.unreviewed | ||||||
|  |     when 'pending_review' | ||||||
|  |       Tag.pending_review.order(requested_review_at: :desc) | ||||||
|  |     when 'popular' | ||||||
|  |       Tag.order('max_score DESC NULLS LAST') | ||||||
|  |     when 'active' | ||||||
|  |       Tag.order('last_status_at DESC NULLS LAST') | ||||||
|  |     when 'name' | ||||||
|  |       Tag.matches_name(value) | ||||||
|  |     else | ||||||
|  |       raise "Unknown filter: #{key}" | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | @ -8,16 +8,36 @@ | ||||||
|   .filter-subset |   .filter-subset | ||||||
|     %strong= t('admin.tags.context') |     %strong= t('admin.tags.context') | ||||||
|     %ul |     %ul | ||||||
|       %li= filter_link_to t('generic.all'), context: nil |       %li= filter_link_to t('generic.all'), directory: nil | ||||||
|       %li= filter_link_to t('admin.tags.directory'), context: 'directory' |       %li= filter_link_to t('admin.tags.directory'), directory: '1' | ||||||
| 
 | 
 | ||||||
|   .filter-subset |   .filter-subset | ||||||
|     %strong= t('admin.tags.review') |     %strong= t('admin.tags.review') | ||||||
|     %ul |     %ul | ||||||
|       %li= filter_link_to t('generic.all'), review: nil |       %li= filter_link_to t('generic.all'), reviewed: nil, unreviewed: nil, pending_review: nil | ||||||
|       %li= filter_link_to t('admin.tags.unreviewed'), review: 'unreviewed' |       %li= filter_link_to t('admin.tags.unreviewed'), unreviewed: '1', reviewed: nil, pending_review: nil | ||||||
|       %li= filter_link_to t('admin.tags.reviewed'), review: 'reviewed' |       %li= filter_link_to t('admin.tags.reviewed'), reviewed: '1', unreviewed: nil, pending_review: nil | ||||||
|       %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), review: 'pending_review' |       %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), pending_review: '1', reviewed: nil, unreviewed: nil | ||||||
|  | 
 | ||||||
|  |   .filter-subset | ||||||
|  |     %strong= t('generic.order_by') | ||||||
|  |     %ul | ||||||
|  |       %li= filter_link_to t('admin.tags.most_recent'), popular: nil, active: nil | ||||||
|  |       %li= filter_link_to t('admin.tags.most_popular'), popular: '1', active: nil | ||||||
|  |       %li= filter_link_to t('admin.tags.last_active'), active: '1', popular: nil | ||||||
|  | 
 | ||||||
|  | = form_tag admin_tags_url, method: 'GET', class: 'simple_form' do | ||||||
|  |   .fields-group | ||||||
|  |     - Admin::FilterHelper::TAGS_FILTERS.each do |key| | ||||||
|  |       = hidden_field_tag key, params[key] if params[key].present? | ||||||
|  | 
 | ||||||
|  |     - %i(name).each do |key| | ||||||
|  |       .input.string.optional | ||||||
|  |         = text_field_tag key, params[key], class: 'string optional', placeholder: I18n.t("admin.tags.#{key}") | ||||||
|  | 
 | ||||||
|  |     .actions | ||||||
|  |       %button= t('admin.accounts.search') | ||||||
|  |       = link_to t('admin.accounts.reset'), admin_tags_path, class: 'button negative' | ||||||
| 
 | 
 | ||||||
| %hr.spacer/ | %hr.spacer/ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -521,6 +521,10 @@ en: | ||||||
|       context: Context |       context: Context | ||||||
|       directory: In directory |       directory: In directory | ||||||
|       in_directory: "%{count} in directory" |       in_directory: "%{count} in directory" | ||||||
|  |       last_active: Last active | ||||||
|  |       most_popular: Most popular | ||||||
|  |       most_recent: Most recent | ||||||
|  |       name: Hashtag | ||||||
|       review: Review status |       review: Review status | ||||||
|       reviewed: Reviewed |       reviewed: Reviewed | ||||||
|       title: Hashtags |       title: Hashtags | ||||||
|  |  | ||||||
|  | @ -131,6 +131,8 @@ en: | ||||||
|         must_be_follower: Block notifications from non-followers |         must_be_follower: Block notifications from non-followers | ||||||
|         must_be_following: Block notifications from people you don't follow |         must_be_following: Block notifications from people you don't follow | ||||||
|         must_be_following_dm: Block direct messages from people you don't follow |         must_be_following_dm: Block direct messages from people you don't follow | ||||||
|  |       invite: | ||||||
|  |         comment: Comment | ||||||
|       invite_request: |       invite_request: | ||||||
|         text: Why do you want to join? |         text: Why do you want to join? | ||||||
|       notification_emails: |       notification_emails: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue