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
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user