From 7a737c79cc06e931afef2eaebd971ea0324e0741 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 7 Aug 2019 16:13:34 +0200 Subject: Add number of pending accounts and pending hashtags to admin dashboard (#11514) --- app/views/admin/tags/show.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/views/admin/tags') diff --git a/app/views/admin/tags/show.html.haml b/app/views/admin/tags/show.html.haml index 27c8dc92b..5f3a8e4d9 100644 --- a/app/views/admin/tags/show.html.haml +++ b/app/views/admin/tags/show.html.haml @@ -9,8 +9,8 @@ .fields-group = f.input :usable, as: :boolean, wrapper: :with_label - = f.input :trendable, as: :boolean, wrapper: :with_label - = f.input :listable, as: :boolean, wrapper: :with_label + = f.input :trendable, as: :boolean, wrapper: :with_label, disabled: !Setting.trends + = f.input :listable, as: :boolean, wrapper: :with_label, disabled: !Setting.profile_directory .actions = f.button :button, t('generic.save_changes'), type: :submit -- cgit From 94c54997cf6dc3bef2af67a070a61cc10595339c Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 7 Aug 2019 17:08:30 +0200 Subject: Fix trending tags returning less items than requested sometimes (#11513) Add better sorting defaults to the hashtags admin UI Add "not reviewed" filter to hashtags admin UI --- app/controllers/admin/tags_controller.rb | 7 ++++--- app/models/tag.rb | 3 ++- app/models/trending_tags.rb | 9 +++++---- app/views/admin/tags/index.html.haml | 1 + config/locales/en.yml | 1 + 5 files changed, 13 insertions(+), 8 deletions(-) (limited to 'app/views/admin/tags') diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb index ed271aedc..794bb114a 100644 --- a/app/controllers/admin/tags_controller.rb +++ b/app/controllers/admin/tags_controller.rb @@ -36,9 +36,10 @@ module Admin def filtered_tags scope = Tag scope = scope.discoverable if filter_params[:context] == 'directory' - scope = scope.reviewed if filter_params[:review] == 'reviewed' - scope = scope.pending_review if filter_params[:review] == 'pending_review' - scope.reorder(score: :desc) + 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(score: :desc) end def filter_params diff --git a/app/models/tag.rb b/app/models/tag.rb index e2fe91da1..1364d1dba 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -30,7 +30,8 @@ class Tag < ApplicationRecord validate :validate_name_change, if: -> { !new_record? && name_changed? } scope :reviewed, -> { where.not(reviewed_at: nil) } - scope :pending_review, -> { where(reviewed_at: nil).where.not(requested_review_at: nil) } + scope :unreviewed, -> { where(reviewed_at: nil) } + scope :pending_review, -> { unreviewed.where.not(requested_review_at: nil) } scope :usable, -> { where(usable: [true, nil]) } scope :discoverable, -> { where(listable: [true, nil]).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')) } diff --git a/app/models/trending_tags.rb b/app/models/trending_tags.rb index 0a7e2feac..594ae9520 100644 --- a/app/models/trending_tags.rb +++ b/app/models/trending_tags.rb @@ -5,6 +5,7 @@ class TrendingTags EXPIRE_HISTORY_AFTER = 7.days.seconds EXPIRE_TRENDS_AFTER = 1.day.seconds THRESHOLD = 5 + LIMIT = 10 class << self include Redisable @@ -18,18 +19,18 @@ class TrendingTags end def get(limit, filtered: true) - tag_ids = redis.zrevrange("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", 0, limit - 1).map(&:to_i) + tag_ids = redis.zrevrange("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", 0, LIMIT - 1).map(&:to_i) tags = Tag.where(id: tag_ids) tags = tags.where(trendable: true) if filtered tags = tags.each_with_object({}) { |tag, h| h[tag.id] = tag } - tag_ids.map { |tag_id| tags[tag_id] }.compact + tag_ids.map { |tag_id| tags[tag_id] }.compact.take(limit) end def trending?(tag) rank = redis.zrevrank("#{KEY}:#{Time.now.utc.beginning_of_day.to_i}", tag.id) - rank.present? && rank <= 10 + rank.present? && rank <= LIMIT end private @@ -59,7 +60,7 @@ class TrendingTags old_rank = redis.zrevrank(key, tag.id) redis.zadd(key, score, tag.id) - request_review!(tag) if (old_rank.nil? || old_rank > 10) && redis.zrevrank(key, tag.id) <= 10 && !tag.trendable? && tag.requires_review? && !tag.requested_review? + request_review!(tag) if (old_rank.nil? || old_rank > LIMIT) && redis.zrevrank(key, tag.id) <= LIMIT && !tag.trendable? && tag.requires_review? && !tag.requested_review? end redis.expire(key, EXPIRE_TRENDS_AFTER) diff --git a/app/views/admin/tags/index.html.haml b/app/views/admin/tags/index.html.haml index 5e4ee21f5..d994955ef 100644 --- a/app/views/admin/tags/index.html.haml +++ b/app/views/admin/tags/index.html.haml @@ -12,6 +12,7 @@ %strong= t('admin.tags.review') %ul %li= filter_link_to t('generic.all'), review: nil + %li= filter_link_to t('admin.tags.unreviewed'), review: 'unreviewed' %li= filter_link_to t('admin.tags.reviewed'), review: 'reviewed' %li= filter_link_to safe_join([t('admin.accounts.moderation.pending'), "(#{Tag.pending_review.count})"], ' '), review: 'pending_review' diff --git a/config/locales/en.yml b/config/locales/en.yml index 7b24df016..17ff24726 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -498,6 +498,7 @@ en: title: Hashtags trending_right_now: Trending right now unique_uses_today: "%{count} posting today" + unreviewed: Not reviewed updated_msg: Hashtag settings updated successfully title: Administration warning_presets: -- cgit From 3a6b6c63f22e31c9b113428d6c69be451a3bcc17 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 7 Aug 2019 20:20:39 +0200 Subject: Add breakdown of usage by source to admin UI for hashtags (#11517) Allows determining where the majority of posts in a hashtag come from on a given day at a glance. --- app/controllers/admin/tags_controller.rb | 25 +++++++++++++++++++++++++ app/views/admin/tags/show.html.haml | 29 +++++++++++++++++++++++++++++ config/locales/en.yml | 3 +++ 3 files changed, 57 insertions(+) (limited to 'app/views/admin/tags') diff --git a/app/controllers/admin/tags_controller.rb b/app/controllers/admin/tags_controller.rb index 794bb114a..d62361eaa 100644 --- a/app/controllers/admin/tags_controller.rb +++ b/app/controllers/admin/tags_controller.rb @@ -4,6 +4,8 @@ module Admin class TagsController < BaseController before_action :set_tags, only: :index before_action :set_tag, except: :index + before_action :set_usage_by_domain, except: :index + before_action :set_counters, except: :index def index authorize :tag, :index? @@ -33,6 +35,21 @@ module Admin @tag = Tag.find(params[:id]) end + def set_usage_by_domain + @usage_by_domain = @tag.statuses + .where(visibility: :public) + .where(Status.arel_table[:id].gteq(Mastodon::Snowflake.id_at(Time.now.utc.beginning_of_day))) + .joins(:account) + .group('accounts.domain') + .reorder('statuses_count desc') + .pluck('accounts.domain, count(*) AS statuses_count') + end + + def set_counters + @accounts_today = @tag.history.first[:accounts] + @accounts_week = Redis.current.pfcount(*current_week_days.map { |day| "activity:tags:#{@tag.id}:#{day}:accounts" }) + end + def filtered_tags scope = Tag scope = scope.discoverable if filter_params[:context] == 'directory' @@ -49,5 +66,13 @@ module Admin def tag_params params.require(:tag).permit(:name, :trendable, :usable, :listable) end + + def current_week_days + now = Time.now.utc.beginning_of_day.to_date + + (Date.commercial(now.cwyear, now.cweek)..now).map do |date| + date.to_time.utc.beginning_of_day.to_i + end + end end end diff --git a/app/views/admin/tags/show.html.haml b/app/views/admin/tags/show.html.haml index 5f3a8e4d9..6a1e03065 100644 --- a/app/views/admin/tags/show.html.haml +++ b/app/views/admin/tags/show.html.haml @@ -1,6 +1,22 @@ - content_for :page_title do = "##{@tag.name}" +.dashboard__counters + %div + = link_to web_url("timelines/tag/#{@tag.name}") do + .dashboard__counters__num= number_with_delimiter @accounts_today + .dashboard__counters__label= t 'admin.tags.accounts_today' + %div + %div + .dashboard__counters__num= number_with_delimiter @accounts_week + .dashboard__counters__label= t 'admin.tags.accounts_week' + %div + = link_to explore_hashtag_path(@tag) do + .dashboard__counters__num= number_with_delimiter @tag.accounts_count + .dashboard__counters__label= t 'admin.tags.directory' + +%hr.spacer/ + = simple_form_for @tag, url: admin_tag_path(@tag.id) do |f| = render 'shared/error_messages', object: @tag @@ -14,3 +30,16 @@ .actions = f.button :button, t('generic.save_changes'), type: :submit + +%hr.spacer/ + +%h3= t 'admin.tags.breakdown' + +.table-wrapper + %table.table + %tbody + - @usage_by_domain.each do |(domain, count)| + %tr + %th= domain || site_hostname + %td= "#{number_with_delimiter((count.to_f / @tag.history[0][:uses].to_f) * 100)}%" + %td= number_with_delimiter count diff --git a/config/locales/en.yml b/config/locales/en.yml index b677a6651..7fd0536ae 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -498,6 +498,9 @@ en: title: Account statuses with_media: With media tags: + accounts_today: Unique uses today + accounts_week: Unique uses this week + breakdown: Breakdown of today's usage by source context: Context directory: In directory in_directory: "%{count} in directory" -- cgit